Current Path : /var/www/axolotl/data/www/krym.axolotls.ru/bitrix/modules/disk/admin/ |
Current File : /var/www/axolotl/data/www/krym.axolotls.ru/bitrix/modules/disk/admin/smart_migration_webdav.php |
<?php use Bitrix\Disk\AttachedObject; use Bitrix\Disk\Driver; use Bitrix\Disk\Folder; use Bitrix\Disk\Internals\Error\ErrorCollection; use Bitrix\Disk\Internals\ExternalLinkTable; use Bitrix\Disk\Internals\FolderTable; use Bitrix\Disk\Internals\SharingTable; use Bitrix\Disk\Ui\Text; use Bitrix\Main\Application; use Bitrix\Disk\ProxyType; use Bitrix\Main\Config\Option; use Bitrix\Disk\RightsManager; use Bitrix\Main\Localization\Loc; use Bitrix\Main\Type\DateTime; use Bitrix\Main\ModuleManager; use Bitrix\Main\SiteTable; use Bitrix\Main\IO; require_once($_SERVER['DOCUMENT_ROOT'] . '/bitrix/modules/main/include/prolog_admin_before.php'); /** @var CAllUser $USER */ /** @var CAllMain $APPLICATION */ global $USER, $APPLICATION; if (!$USER->IsAdmin()) { $APPLICATION->AuthForm(GetMessage('ACCESS_DENIED')); } class SmartMigrationWebdavLogger extends \Bitrix\Main\Diag\FileExceptionHandlerLog { const MAX_LOG_SIZE = 10000000; const DEFAULT_LOG_FILE = "bitrix/modules/disk_convertor.log"; private $logFile; private $logFileHistory; private $maxLogSize; private $level; public function initialize(array $options) { $this->logFile = static::DEFAULT_LOG_FILE; if (isset($options["file"]) && !empty($options["file"])) $this->logFile = $options["file"]; $this->logFile = preg_replace("'[\\\\/]+'", "/", $this->logFile); if ((substr($this->logFile, 0, 1) !== "/") && !preg_match("#^[a-z]:/#", $this->logFile)) $this->logFile = Application::getDocumentRoot()."/".$this->logFile; $this->logFileHistory = $this->logFile.".old." . time(); $this->maxLogSize = static::MAX_LOG_SIZE; if (isset($options["log_size"]) && ($options["log_size"] > 0)) $this->maxLogSize = intval($options["log_size"]); if (isset($options["level"]) && ($options["level"] > 0)) $this->level = intval($options["level"]); } public function writeToLog($text) { if (empty($text)) return; $logFile = $this->logFile; $logFileHistory = $this->logFileHistory; $oldAbortStatus = ignore_user_abort(true); if ($fp = @fopen($logFile, "ab")) { if (@flock($fp, LOCK_EX)) { $logSize = @filesize($logFile); $logSize = intval($logSize); if ($logSize > $this->maxLogSize) { $this->logFileHistory = $this->logFile.".old." . time(); $logFileHistory = $this->logFileHistory; @copy($logFile, $logFileHistory); ftruncate($fp, 0); } @fwrite($fp, $text); @fflush($fp); @flock($fp, LOCK_UN); @fclose($fp); } } ignore_user_abort($oldAbortStatus); } } class SmartMigrationWebdav { const RUN_STEPS_WITH_MODIFY_DATA = true; const DENY_TASK = PHP_INT_MAX; const COULD_NOT_FIND_IBLOCK_TASK = -2; const STATUS_FINISH = 2; const STATUS_TIME_EXPIRED = 3; const STATUS_ERROR = 4; const UF_DISK_FILE_ID = 'UF_DISK_FILE_ID'; const UF_DISK_FILE_STATUS = 'UF_DISK_FILE_STATUS'; const UF_DISK_FOLDER_ID = 'UF_DISK_FOLDER_ID'; const UF_DISK_INTO_TRASH = 'UF_DISK_INTO_TRASH'; const UF_DISK_STATUS_MIGRATE = 'UF_DISK_ST_MIGRATE'; const STATUS_MIGRATE_FINAL = 2; const STATUS_MIGRATE_WITHOUT_TRASH = 3; const STATUS_MIGRATE_WITHOUT_STRUCTURE = 4; const STATUS_MIGRATE_SKIP = 5; const STATUS_MIGRATE_WITH_FILES = 6; public static $countConvertElements = 0; public static $countConvertSections = 0; public static $countSuccessfulSteps = 0; protected $currentIblockId; protected $timeStart = 0; /** @var SmartMigrationWebdavLogger */ protected $logger; /** @var array|null */ protected $iblockTasks = null; /** @var array|null */ protected $diskTasks = null; protected $iblockOperationsByTask; protected $diskOperationsByTask; /** * Seconds * @var int */ protected $maxExecution = 38; /** \Bitrix\Disk\Storage */ protected $currentStorage; /** @var Folder[] */ protected $currentFolderMap; protected $runWorkWithBizproc = false; /** @var \Bitrix\Main\DB\Connection */ protected $connection; protected $isOracle = false; protected $isMysql = false; protected $isMssql = false; /** @var \Bitrix\Main\DB\SqlHelper */ protected $sqlHelper; protected $useGZipCompression; protected $publishDocs = false; public function __construct(array $options = array()) { $this->setTimeStart(time()); $this->logger = new SmartMigrationWebdavLogger(); $this->logger->initialize(array()); $this->connection = Application::getInstance()->getConnection(); $this->sqlHelper = $this->connection->getSqlHelper(); $this->isOracle = $this->connection instanceof \Bitrix\Main\DB\OracleConnection; $this->isMysql = $this->connection instanceof \Bitrix\Main\DB\MysqlCommonConnection; $this->isMssql = $this->connection instanceof \Bitrix\Main\DB\MssqlConnection; if(!empty($options['publishDocs'])) { $this->publishDocs = $options['publishDocs']; } $this->log(array( 'PublishDocs', (bool)$this->publishDocs, )); } public function getConcatFunction() { if(!$this->isMssql) { return call_user_func_array(array($this->sqlHelper, 'getConcatFunction'), func_get_args()); } $data = array(); foreach(func_get_args() as $value) { $data[] = "CAST($value as VARCHAR(255))"; } unset($value); return implode(' + ', $data); } public function log($data) { if(!is_string($data)) { $data = print_r($data, true); } $this->logger->writeToLog('Date:' . date('r') . "\n" . $data . "\n\n"); } /** * @param int $timeStart */ public function setTimeStart($timeStart) { $this->timeStart = $timeStart; } /** * @return int */ public function getTimeStart() { return $this->timeStart; } protected function isTimeExpired() { return (time() - $this->getTimeStart()) > $this->maxExecution; } /** * Check expired by time and throw exception * @param bool $force * @throws TimeExecutionException */ protected function abortIfNeeded($force = false) { if($force || $this->isTimeExpired()) { throw new TimeExecutionException(); } } protected function checkRequired() { if(!CModule::includeModule('disk')) { throw new Exception('Bad include disk'); } if(!CModule::includeModule('iblock')) { throw new Exception('Bad include iblock'); } if(!CModule::includeModule('webdav')) { throw new Exception('Bad include webdav'); } $this->runWorkWithBizproc = CModule::includeModule('bizproc'); } public function setStepFinished($stepName, $description = '') { $stepName = strtr($stepName, array(':' => '')); COption::SetOptionString( 'disk', '~sF' . md5($stepName), 'Y' ); self::$countSuccessfulSteps++; $this->log(array( "finished", "Step {$stepName}", $description, )); return $this; } public function isStepFinished($stepName, $description = '') { $stepName = strtr($stepName, array(':' => '')); $finished = COption::GetOptionString('disk', '~sF' . md5($stepName), 'N') == 'Y'; if(!$finished) { $this->log(array( "Start", "Step {$stepName}", $description, )); } else { self::$countSuccessfulSteps++; $this->log(array( "Skip", "Step {$stepName}", )); } return $finished; } protected function runResorting() { if($this->isStepFinished(__METHOD__)) { return; } $lastId = $this->getLastIblockId(); $q = CIBlock::GetList(array("ID"=>"ASC"), array("TYPE" => "library", ">ID" => $lastId)); if($q) { while($iblock = $q->fetch()) { $this->abortIfNeeded(); CIBlockSection::treeReSort($iblock['ID']); $this->storeIblockId($iblock['ID']); } } $this->storeIblockId(0); $this->setStepFinished(__METHOD__); } protected function getIblockWithUserFiles() { static $userIblockIds = array(); if($userIblockIds) { return $userIblockIds; } $q = CIBlock::GetList(array("ID"=>"ASC"), array("CODE" => "user_files%", "TYPE" => "library")); if($q) { while($iblock = $q->fetch()) { $userIblockIds[$iblock['ID']] = $iblock; } } return $userIblockIds; } protected function getIblockIdsWithGroupFiles() { static $groupIblockIds = array(); if($groupIblockIds) { return $groupIblockIds; } $q = CIBlock::GetList(array("ID"=>"ASC"), array("CODE" => "group_files%", "TYPE" => "library")); if($q) { while($iblock = $q->fetch()) { $groupIblockIds[$iblock['ID']] = $iblock; } } return $groupIblockIds; } protected function getIblockIdsWithCommonFiles() { static $commonIblockIds = array(); if($commonIblockIds) { return $commonIblockIds; } $q = CIBlock::GetList(array('ID' => 'ASC'), array('!CODE' => array('group_files%', 'user_files%'), 'TYPE' => 'library')); if($q) { while($iblock = $q->fetch()) { $commonIblockIds[$iblock['ID']] = $iblock; } } return $commonIblockIds; } protected function getLibraryIblocks() { static $iblocks = array(); if($iblocks) { return $iblocks; } $q = CIBlock::GetList(array('ID' => 'ASC'), array('TYPE' => 'library')); if($q) { while($iblock = $q->fetch()) { $iblocks[$iblock['ID']] = $iblock; } } return $iblocks; } protected function moveUserStorageFromIblock(array $iblock) { $this->log(array( __METHOD__, 'start', $iblock['ID'], )); $sqlHelper = $this->connection->getSqlHelper(); $iblockId = (int)$iblock['ID']; $siteId = $sqlHelper->forSql($iblock['LID']); $proxyType = $sqlHelper->forSql(ProxyType\User::className()); if($this->isMysql) { $sql = " INSERT IGNORE INTO b_disk_storage (NAME, MODULE_ID, ENTITY_TYPE, ENTITY_ID, ENTITY_MISC_DATA, ROOT_OBJECT_ID, USE_INTERNAL_RIGHTS, SITE_ID, XML_ID) SELECT NAME, 'disk', '{$proxyType}', " . $this->sqlHelper->getIsNullFunction('CREATED_BY', 0) . ", null, ID, 1, '{$siteId}', ID FROM b_iblock_section WHERE IBLOCK_ID = {$iblockId} AND (IBLOCK_SECTION_ID = 0 OR IBLOCK_SECTION_ID IS NULL) "; } if($this->isOracle || $this->isMssql) { $sql = " INSERT INTO b_disk_storage (NAME, MODULE_ID, ENTITY_TYPE, ENTITY_ID, ENTITY_MISC_DATA, ROOT_OBJECT_ID, USE_INTERNAL_RIGHTS, SITE_ID, XML_ID) SELECT NAME, 'disk', '{$proxyType}', " . $this->sqlHelper->getIsNullFunction('CREATED_BY', 0) . ", null, ID, 1, '{$siteId}', ID FROM b_iblock_section IBLOCK WHERE IBLOCK_ID = {$iblockId} AND (IBLOCK_SECTION_ID = 0 OR IBLOCK_SECTION_ID IS NULL) AND NOT EXISTS(SELECT * FROM b_disk_storage WHERE MODULE_ID = 'disk' AND ENTITY_TYPE = '{$proxyType}' AND ENTITY_ID = " . $sqlHelper->getIsNullFunction('CREATED_BY', 0) . ") "; } $this->connection->queryExecute($sql); if($this->isMssql) { $this->connection->queryExecute('SET IDENTITY_INSERT b_disk_object ON'); } $this->connection->queryExecute(" INSERT INTO b_disk_object (ID, REAL_OBJECT_ID, NAME, TYPE, CODE, STORAGE_ID, PARENT_ID, CREATE_TIME, UPDATE_TIME, SYNC_UPDATE_TIME, CREATED_BY, UPDATED_BY, XML_ID, WEBDAV_SECTION_ID, WEBDAV_IBLOCK_ID) SELECT sec.ID, sec.ID, sec.NAME, 2, null, storage.ID, null, sec.DATE_CREATE, sec.DATE_CREATE, sec.DATE_CREATE, sec.CREATED_BY, null, sec.ID, sec.ID, sec.IBLOCK_ID FROM b_iblock_section sec INNER JOIN b_disk_storage storage ON storage.ROOT_OBJECT_ID = sec.ID WHERE sec.IBLOCK_ID = {$iblockId} AND (sec.IBLOCK_SECTION_ID = 0 OR sec.IBLOCK_SECTION_ID IS NULL) "); $this->connection->queryExecute(" INSERT INTO b_disk_object (ID, REAL_OBJECT_ID, NAME, TYPE, CODE, STORAGE_ID, PARENT_ID, CREATE_TIME, UPDATE_TIME, SYNC_UPDATE_TIME, CREATED_BY, UPDATED_BY, XML_ID, WEBDAV_SECTION_ID, WEBDAV_IBLOCK_ID) SELECT sec.ID, sec.ID, " . $this->getConcatFunction('sec.NAME', "'_'", 'ib.LID') . ", 2, 'FROM_SITE_MOVED', ds.ID, ds.ROOT_OBJECT_ID, sec.DATE_CREATE, sec.DATE_CREATE, sec.DATE_CREATE, sec.CREATED_BY, null, sec.ID, sec.ID, sec.IBLOCK_ID FROM b_iblock_section sec INNER JOIN b_disk_storage ds ON ds.ENTITY_ID = sec.CREATED_BY AND ds.ENTITY_TYPE='{$proxyType}' INNER JOIN b_iblock ib ON sec.IBLOCK_ID=ib.ID WHERE sec.IBLOCK_ID = {$iblockId} AND (sec.IBLOCK_SECTION_ID = 0 OR sec.IBLOCK_SECTION_ID IS NULL) AND NOT EXISTS(SELECT 'x' FROM b_disk_storage ds1 WHERE ds1.ROOT_OBJECT_ID=sec.ID) "); if($this->isMssql) { $this->connection->queryExecute('SET IDENTITY_INSERT b_disk_object OFF'); } $this->log(array( __METHOD__, 'finish', $iblock['ID'], )); } protected function moveGroupStorageFromIblock(array $iblock) { $this->log(array( __METHOD__, 'start', $iblock['ID'], )); $iblockId = (int)$iblock['ID']; $sqlHelper = $this->sqlHelper; $siteId = $sqlHelper->forSql($iblock['LID']); $proxyType = $sqlHelper->forSql(ProxyType\Group::className()); if($this->isMysql) { $sql = " INSERT IGNORE INTO b_disk_storage (NAME, MODULE_ID, ENTITY_TYPE, ENTITY_ID, ENTITY_MISC_DATA, ROOT_OBJECT_ID, USE_INTERNAL_RIGHTS, SITE_ID, XML_ID) SELECT NAME, 'disk', '{$proxyType}', SOCNET_GROUP_ID, null, ID, 1, null, ID FROM b_iblock_section sec WHERE IBLOCK_ID = {$iblockId} AND SOCNET_GROUP_ID IS NOT NULL AND (IBLOCK_SECTION_ID = 0 OR IBLOCK_SECTION_ID IS NULL) AND EXISTS(SELECT * FROM b_sonet_group sg WHERE sg.ID=sec.SOCNET_GROUP_ID ) "; } if($this->isOracle || $this->isMssql) { $sql = " INSERT INTO b_disk_storage (NAME, MODULE_ID, ENTITY_TYPE, ENTITY_ID, ENTITY_MISC_DATA, ROOT_OBJECT_ID, USE_INTERNAL_RIGHTS, SITE_ID, XML_ID) SELECT NAME, 'disk', '{$proxyType}', SOCNET_GROUP_ID, null, ID, 1, null, ID FROM b_iblock_section sec WHERE IBLOCK_ID = {$iblockId} AND SOCNET_GROUP_ID IS NOT NULL AND (IBLOCK_SECTION_ID = 0 OR IBLOCK_SECTION_ID IS NULL) AND EXISTS(SELECT * FROM b_sonet_group sg WHERE sg.ID=sec.SOCNET_GROUP_ID ) AND NOT EXISTS(SELECT * FROM b_disk_storage WHERE MODULE_ID = 'disk' AND ENTITY_TYPE = '{$proxyType}' AND ENTITY_ID = " . $sqlHelper->getIsNullFunction('SOCNET_GROUP_ID', 0) . ") "; } $this->connection->queryExecute($sql); if($this->isMssql) { $this->connection->queryExecute('SET IDENTITY_INSERT b_disk_object ON'); } $this->connection->queryExecute(" INSERT INTO b_disk_object (ID, REAL_OBJECT_ID, NAME, TYPE, CODE, STORAGE_ID, PARENT_ID, CREATE_TIME, UPDATE_TIME, SYNC_UPDATE_TIME, CREATED_BY, UPDATED_BY, XML_ID, WEBDAV_SECTION_ID, WEBDAV_IBLOCK_ID) SELECT sec.ID, sec.ID, sec.NAME, 2, null, storage.ID, null, sec.DATE_CREATE, sec.DATE_CREATE, sec.DATE_CREATE, " . $sqlHelper->getIsNullFunction('sec.CREATED_BY', 0) . ", null, sec.ID, sec.ID, sec.IBLOCK_ID FROM b_iblock_section sec INNER JOIN b_disk_storage storage ON storage.ROOT_OBJECT_ID = sec.ID WHERE sec.IBLOCK_ID = {$iblockId} AND SOCNET_GROUP_ID IS NOT NULL AND (sec.IBLOCK_SECTION_ID = 0 OR sec.IBLOCK_SECTION_ID IS NULL) "); $this->connection->queryExecute(" INSERT INTO b_disk_object (ID, REAL_OBJECT_ID, NAME, TYPE, CODE, STORAGE_ID, PARENT_ID, CREATE_TIME, UPDATE_TIME, SYNC_UPDATE_TIME, CREATED_BY, UPDATED_BY, XML_ID, WEBDAV_SECTION_ID, WEBDAV_IBLOCK_ID) SELECT sec.ID, sec.ID, " . $this->getConcatFunction('sec.NAME', "'_'", 'ib.LID') . ", 2, 'FROM_SITE_MOVED', ds.ID, ds.ROOT_OBJECT_ID, sec.DATE_CREATE, sec.DATE_CREATE, sec.DATE_CREATE, " . $sqlHelper->getIsNullFunction('sec.CREATED_BY', 0) . ", null, sec.ID, sec.ID, sec.IBLOCK_ID FROM b_iblock_section sec INNER JOIN b_disk_storage ds ON ds.ENTITY_ID = sec.SOCNET_GROUP_ID AND ds.ENTITY_TYPE='{$proxyType}' INNER JOIN b_iblock ib ON sec.IBLOCK_ID=ib.ID INNER JOIN b_sonet_group sg ON sg.ID=sec.SOCNET_GROUP_ID WHERE sec.IBLOCK_ID = {$iblockId} AND sec.SOCNET_GROUP_ID IS NOT NULL AND (sec.IBLOCK_SECTION_ID = 0 OR sec.IBLOCK_SECTION_ID IS NULL) AND NOT EXISTS(SELECT 'x' FROM b_disk_storage ds1 WHERE ds1.ROOT_OBJECT_ID=sec.ID) "); if($this->isMssql) { $this->connection->queryExecute('SET IDENTITY_INSERT b_disk_object OFF'); } if($this->runWorkWithBizproc) { $classDocument = $sqlHelper->forSql(\Bitrix\Disk\BizProcDocumentCompatible::className()); if($this->isOracle) { $this->connection->queryExecute(" INSERT INTO b_bp_workflow_template (ID, MODULE_ID, ENTITY, DOCUMENT_TYPE, AUTO_EXECUTE, NAME, DESCRIPTION, TEMPLATE, PARAMETERS, VARIABLES, MODIFIED, USER_ID, SYSTEM_CODE, ACTIVE) SELECT SQ_B_BP_WORKFLOW_TEMPLATE.nextval, 'disk', '{$classDocument}', " . $this->getConcatFunction("'STORAGE_'", 's.ID') . ", t.AUTO_EXECUTE, t.NAME, t.DESCRIPTION, t.TEMPLATE, t.PARAMETERS, t.VARIABLES, t.MODIFIED, t.USER_ID, t.SYSTEM_CODE, t.ACTIVE FROM b_bp_workflow_template t INNER JOIN b_disk_storage s ON s.ENTITY_TYPE = '{$proxyType}' AND t.DOCUMENT_TYPE = " . $this->getConcatFunction("'iblock_{$iblockId}_group_'", 's.ENTITY_ID') . " WHERE t.MODULE_ID = 'webdav' AND t.ENTITY = 'CIBlockDocumentWebdavSocnet' "); } else { $this->connection->queryExecute(" INSERT INTO b_bp_workflow_template (MODULE_ID, ENTITY, DOCUMENT_TYPE, AUTO_EXECUTE, NAME, DESCRIPTION, TEMPLATE, PARAMETERS, VARIABLES, MODIFIED, USER_ID, SYSTEM_CODE, ACTIVE) SELECT 'disk', '{$classDocument}', " . $this->getConcatFunction("'STORAGE_'", 's.ID') . ", t.AUTO_EXECUTE, t.NAME, t.DESCRIPTION, t.TEMPLATE, t.PARAMETERS, t.VARIABLES, t.MODIFIED, t.USER_ID, t.SYSTEM_CODE, t.ACTIVE FROM b_bp_workflow_template t INNER JOIN b_disk_storage s ON s.ENTITY_TYPE = '{$proxyType}' AND t.DOCUMENT_TYPE = " . $this->getConcatFunction("'iblock_{$iblockId}_group_'", 's.ENTITY_ID') . " WHERE t.MODULE_ID = 'webdav' AND t.ENTITY = 'CIBlockDocumentWebdavSocnet' "); } $dbRes = CIBlockSection::GetList(array(), array( 'IBLOCK_ID' => $iblockId, '!SOCNET_GROUP_ID' => false, '=UF_USE_BP' => 'Y', 'SECTION_ID' => 0), false, array('ID', 'UF_USE_BP')); if ($dbRes) { $miscData = $this->connection->getSqlHelper()->forSql(serialize(array( 'BIZPROC_ENABLED' => true, ))); $rootObjectIdArray = array(); while($res = $dbRes->Fetch()) { $rootObjectIdArray[$res['ID']] = intval($res['ID']); } if($rootObjectIdArray) { $rootObjectIds = implode(",", $rootObjectIdArray); $this->connection->queryExecute("UPDATE b_disk_storage SET ENTITY_MISC_DATA='{$miscData}' WHERE ROOT_OBJECT_ID IN ({$rootObjectIds})"); } } } $this->log(array( __METHOD__, 'finish', $iblock['ID'], )); } protected function moveSections() { if($this->isStepFinished(__METHOD__)) { return; } $appendWhere = ' AND obj.PARENT_ID IS NULL '; $hasStorageFromDiffSites = $this->connection->query("SELECT * FROM b_disk_object WHERE CODE = 'FROM_SITE_MOVED' AND PARENT_ID IS NOT NULL")->fetch(); if($hasStorageFromDiffSites) { $appendWhere = " AND (obj.PARENT_ID IS NULL OR obj.CODE = 'FROM_SITE_MOVED')"; } $this->log(array( 'appendWhere', $appendWhere )); //move all desc of object. Object is root of storage(group, user) if($this->isMysql) { $sql = " INSERT IGNORE INTO b_disk_object (ID, REAL_OBJECT_ID, NAME, TYPE, CODE, STORAGE_ID, PARENT_ID, CREATE_TIME, UPDATE_TIME, SYNC_UPDATE_TIME, CREATED_BY, UPDATED_BY, XML_ID, WEBDAV_SECTION_ID, WEBDAV_IBLOCK_ID) SELECT child.ID, child.ID, child.NAME, 2, IF(child.XML_ID='CREATED_DOC_FOLDER', 'FOR_CREATED_FILES', child.CODE), obj.STORAGE_ID, child.IBLOCK_SECTION_ID, child.DATE_CREATE, " . $this->sqlHelper->getIsNullFunction('child.TIMESTAMP_X', 'child.DATE_CREATE') . ", " . $this->sqlHelper->getIsNullFunction('child.TIMESTAMP_X', 'child.DATE_CREATE') . ", " . $this->sqlHelper->getIsNullFunction('child.CREATED_BY', 0) . ", child.MODIFIED_BY, child.ID, child.ID, child.IBLOCK_ID FROM b_iblock_section child INNER JOIN b_iblock_section sec ON child.LEFT_MARGIN > sec.LEFT_MARGIN AND child.RIGHT_MARGIN < sec.RIGHT_MARGIN AND child.IBLOCK_ID = sec.IBLOCK_ID INNER JOIN b_disk_object obj ON (obj.ID = sec.ID {$appendWhere}) "; } elseif($this->isOracle || $this->isMssql) { $sql = " INSERT INTO b_disk_object (ID, REAL_OBJECT_ID, NAME, TYPE, CODE, STORAGE_ID, PARENT_ID, CREATE_TIME, UPDATE_TIME, SYNC_UPDATE_TIME, CREATED_BY, UPDATED_BY, XML_ID, WEBDAV_SECTION_ID, WEBDAV_IBLOCK_ID) SELECT child.ID, child.ID, child.NAME, 2, (CASE WHEN child.XML_ID='CREATED_DOC_FOLDER' THEN 'FOR_CREATED_FILES' ELSE child.CODE END), obj.STORAGE_ID, child.IBLOCK_SECTION_ID, child.DATE_CREATE, " . $this->sqlHelper->getIsNullFunction('child.TIMESTAMP_X', 'child.DATE_CREATE') . ", " . $this->sqlHelper->getIsNullFunction('child.TIMESTAMP_X', 'child.DATE_CREATE') . ", " . $this->sqlHelper->getIsNullFunction('child.CREATED_BY', 0) . ", child.MODIFIED_BY, child.ID, child.ID, child.IBLOCK_ID FROM b_iblock_section child INNER JOIN b_iblock_section sec ON child.LEFT_MARGIN > sec.LEFT_MARGIN AND child.RIGHT_MARGIN < sec.RIGHT_MARGIN AND child.IBLOCK_ID = sec.IBLOCK_ID INNER JOIN b_disk_object obj ON (obj.ID = sec.ID {$appendWhere}) WHERE NOT EXISTS(SELECT 'x' FROM b_disk_object WHERE NAME = child.NAME AND PARENT_ID = child.IBLOCK_SECTION_ID AND child.IBLOCK_SECTION_ID IS NOT NULL) "; } if($this->isMssql) { $this->connection->queryExecute('SET IDENTITY_INSERT b_disk_object ON'); } $this->connection->queryExecute($sql); if($this->isMssql) { $this->connection->queryExecute('SET IDENTITY_INSERT b_disk_object OFF'); } if($hasStorageFromDiffSites) { $this->connection->queryExecute("UPDATE b_disk_object SET CODE = null WHERE CODE = 'FROM_SITE_MOVED' AND PARENT_ID IS NOT NULL"); } $this->setStepFinished(__METHOD__); $this->abortIfNeeded(true); } protected function moveNonUniqueSections() { if($this->isStepFinished(__METHOD__)) { return; } $sqlHelper = $this->connection->getSqlHelper(); if($this->isMysql) { $sql = " INSERT INTO b_disk_object (ID, REAL_OBJECT_ID, NAME, TYPE, CODE, STORAGE_ID, PARENT_ID, CREATE_TIME, UPDATE_TIME, SYNC_UPDATE_TIME, CREATED_BY, UPDATED_BY, XML_ID, WEBDAV_SECTION_ID, WEBDAV_IBLOCK_ID) SELECT child.ID, child.ID, " . $this->getConcatFunction('child.NAME', "'_'", 'child.ID') . ", 2, IF(child.XML_ID='CREATED_DOC_FOLDER', 'FOR_CREATED_FILES', child.CODE), obj.STORAGE_ID, child.IBLOCK_SECTION_ID, child.DATE_CREATE, " . $this->sqlHelper->getIsNullFunction('child.TIMESTAMP_X', 'child.DATE_CREATE') . ", " . $this->sqlHelper->getIsNullFunction('child.TIMESTAMP_X', 'child.DATE_CREATE') . ", " . $this->sqlHelper->getIsNullFunction('child.CREATED_BY', 0) . ", child.MODIFIED_BY, child.ID, child.ID, child.IBLOCK_ID FROM b_iblock_section child INNER JOIN b_iblock_section sec ON child.LEFT_MARGIN > sec.LEFT_MARGIN AND child.RIGHT_MARGIN < sec.RIGHT_MARGIN AND child.IBLOCK_ID = sec.IBLOCK_ID INNER JOIN b_disk_object obj ON (obj.ID = sec.ID AND obj.PARENT_ID is NULL) WHERE NOT EXISTS(SELECT 'x' FROM b_disk_object do WHERE do.ID=child.ID) "; } elseif($this->isOracle || $this->isMssql) { $sql = " INSERT INTO b_disk_object (ID, REAL_OBJECT_ID, NAME, TYPE, CODE, STORAGE_ID, PARENT_ID, CREATE_TIME, UPDATE_TIME, SYNC_UPDATE_TIME, CREATED_BY, UPDATED_BY, XML_ID, WEBDAV_SECTION_ID, WEBDAV_IBLOCK_ID) SELECT child.ID, child.ID, " . $this->getConcatFunction('child.NAME', "'_'", 'child.ID') . ", 2, (CASE WHEN child.XML_ID='CREATED_DOC_FOLDER' THEN 'FOR_CREATED_FILES' ELSE child.CODE END), obj.STORAGE_ID, child.IBLOCK_SECTION_ID, child.DATE_CREATE, " . $this->sqlHelper->getIsNullFunction('child.TIMESTAMP_X', 'child.DATE_CREATE') . ", " . $this->sqlHelper->getIsNullFunction('child.TIMESTAMP_X', 'child.DATE_CREATE') . ", " . $this->sqlHelper->getIsNullFunction('child.CREATED_BY', 0) . ", child.MODIFIED_BY, child.ID, child.ID, child.IBLOCK_ID FROM b_iblock_section child INNER JOIN b_iblock_section sec ON child.LEFT_MARGIN > sec.LEFT_MARGIN AND child.RIGHT_MARGIN < sec.RIGHT_MARGIN AND child.IBLOCK_ID = sec.IBLOCK_ID INNER JOIN b_disk_object obj ON (obj.ID = sec.ID AND obj.PARENT_ID is NULL) WHERE NOT EXISTS(SELECT 'x' FROM b_disk_object do WHERE do.ID=child.ID) "; } if($this->isMssql) { $this->connection->queryExecute('SET IDENTITY_INSERT b_disk_object ON'); } $this->connection->queryExecute($sql); if($this->isMssql) { $this->connection->queryExecute('SET IDENTITY_INSERT b_disk_object OFF'); } $this->setStepFinished(__METHOD__); } protected function moveElements() { if($this->isStepFinished(__METHOD__)) { return; } $sqlHelper = $this->sqlHelper; $iblocksType2 = $iblocksType1 = array(); foreach($this->getLibraryIblocks() as $iblock) { if($iblock['VERSION'] == 2) { $iblocksType2[$iblock['ID']] = $iblock; } else { $iblocksType1[$iblock['ID']] = $iblock; } } unset($iblock); if($iblocksType2) { $propsByIblockId = array(); $propsIblock2 = $this->connection->query(" SELECT prop.* FROM b_iblock_property prop INNER JOIN b_iblock iblock ON prop.IBLOCK_ID = iblock.ID WHERE iblock.IBLOCK_TYPE_ID = 'library' AND iblock.VERSION = 2 AND prop.VERSION = 2 AND prop.CODE IN ('WEBDAV_SIZE', 'FILE', 'WEBDAV_VERSION') ")->fetchAll(); foreach($propsIblock2 as $prop) { $propsByIblockId[$prop['IBLOCK_ID']][] = $prop; } unset($prop); foreach($propsByIblockId as $iblockId => $props) { $joinTable = 'b_iblock_element_prop_s' . $iblockId; $columnForFileId = $columnForSize = 'null'; $columnForVersion = '1'; foreach($props as $prop) { switch($prop['CODE']) { case 'WEBDAV_SIZE': $columnForSize = 'PROPERTY_' . $prop['ID']; break; case 'FILE': $columnForFileId = 'PROPERTY_' . $prop['ID']; break; case 'WEBDAV_VERSION': $columnForVersion = 'PROPERTY_' . $prop['ID']; break; } } unset($prop); if($this->isMysql) { $sql = " INSERT IGNORE INTO b_disk_object (FILE_ID, SIZE, GLOBAL_CONTENT_VERSION, NAME, TYPE, CODE, STORAGE_ID, PARENT_ID, CREATE_TIME, UPDATE_TIME, SYNC_UPDATE_TIME, CREATED_BY, UPDATED_BY, XML_ID, WEBDAV_ELEMENT_ID, WEBDAV_IBLOCK_ID) SELECT {$columnForFileId}, {$columnForSize}, {$columnForVersion}, child.NAME, 3, null, parent.STORAGE_ID, child.IBLOCK_SECTION_ID, child.DATE_CREATE, " . $sqlHelper->getIsNullFunction('child.TIMESTAMP_X', 'child.DATE_CREATE') . ", " . $sqlHelper->getIsNullFunction('child.TIMESTAMP_X', 'child.DATE_CREATE') . ", " . $sqlHelper->getIsNullFunction('child.CREATED_BY', 0) . ", child.MODIFIED_BY, child.ID, child.ID, child.IBLOCK_ID FROM b_iblock_element child INNER JOIN b_disk_object parent ON child.IBLOCK_SECTION_ID = parent.ID AND parent.TYPE = 2 INNER JOIN {$joinTable} props ON props.IBLOCK_ELEMENT_ID = child.ID "; } elseif($this->isOracle || $this->isMssql) { $sql = " INSERT INTO b_disk_object (FILE_ID, " . $this->sqlHelper->quote('SIZE') . ", GLOBAL_CONTENT_VERSION, NAME, TYPE, CODE, STORAGE_ID, PARENT_ID, CREATE_TIME, UPDATE_TIME, SYNC_UPDATE_TIME, CREATED_BY, UPDATED_BY, XML_ID, WEBDAV_ELEMENT_ID, WEBDAV_IBLOCK_ID) SELECT {$columnForFileId}, {$columnForSize}, {$columnForVersion}, child.NAME, 3, null, parent.STORAGE_ID, child.IBLOCK_SECTION_ID, child.DATE_CREATE, " . $sqlHelper->getIsNullFunction('child.TIMESTAMP_X', 'child.DATE_CREATE') . ", " . $sqlHelper->getIsNullFunction('child.TIMESTAMP_X', 'child.DATE_CREATE') . ", " . $sqlHelper->getIsNullFunction('child.CREATED_BY', 0) . ", child.MODIFIED_BY, child.ID, child.ID, child.IBLOCK_ID FROM b_iblock_element child INNER JOIN b_disk_object parent ON child.IBLOCK_SECTION_ID = parent.ID AND parent.TYPE = 2 INNER JOIN {$joinTable} props ON props.IBLOCK_ELEMENT_ID = child.ID WHERE NOT EXISTS(SELECT 'x' FROM b_disk_object do WHERE do.NAME=child.NAME AND do.PARENT_ID = child.IBLOCK_SECTION_ID AND child.IBLOCK_SECTION_ID IS NOT NULL) "; } $this->connection->queryExecute($sql); $this->connection->queryExecute(" INSERT INTO b_disk_object (FILE_ID, " . $this->sqlHelper->quote('SIZE') . ", GLOBAL_CONTENT_VERSION, NAME, TYPE, CODE, STORAGE_ID, PARENT_ID, CREATE_TIME, UPDATE_TIME, SYNC_UPDATE_TIME, CREATED_BY, UPDATED_BY, XML_ID, WEBDAV_ELEMENT_ID, WEBDAV_IBLOCK_ID) SELECT {$columnForFileId}, {$columnForSize}, {$columnForVersion}, " . $this->getConcatFunction('child.ID', 'child.NAME') . ", 3, null, parent.STORAGE_ID, child.IBLOCK_SECTION_ID, child.DATE_CREATE, " . $sqlHelper->getIsNullFunction('child.TIMESTAMP_X', 'child.DATE_CREATE') . ", " . $sqlHelper->getIsNullFunction('child.TIMESTAMP_X', 'child.DATE_CREATE') . ", " . $sqlHelper->getIsNullFunction('child.CREATED_BY', 0) . ", child.MODIFIED_BY, child.ID, child.ID, child.IBLOCK_ID FROM b_iblock_element child INNER JOIN b_disk_object parent ON child.IBLOCK_SECTION_ID = parent.ID AND parent.TYPE = 2 INNER JOIN {$joinTable} props ON props.IBLOCK_ELEMENT_ID = child.ID WHERE NOT EXISTS(SELECT 'x' FROM b_disk_object do WHERE do.WEBDAV_ELEMENT_ID=child.ID) "); } unset($props); } if($iblocksType1) { $whereIgnoreIblocks = ' '; $conditionIgnoreIblocks = ' '; if($iblocksType2) { $whereIgnoreIblocks = ' WHERE child.IBLOCK_ID IN (' . implode(', ', array_keys($iblocksType1)) . ') '; $conditionIgnoreIblocks = ' AND child.IBLOCK_ID IN (' . implode(', ', array_keys($iblocksType1)) . ') '; } if($this->isMysql) { $sql = " INSERT IGNORE INTO b_disk_object (FILE_ID, SIZE, GLOBAL_CONTENT_VERSION, NAME, TYPE, CODE, STORAGE_ID, PARENT_ID, CREATE_TIME, UPDATE_TIME, SYNC_UPDATE_TIME, CREATED_BY, UPDATED_BY, XML_ID, WEBDAV_ELEMENT_ID, WEBDAV_IBLOCK_ID) SELECT PROP_FILE_EL.VALUE, PROP_SIZE_EL.VALUE, " . $this->connection->getSqlHelper()->getIsNullFunction('PPROP_VERSION_G_EL.VALUE', 1) . ", child.NAME, 3, null, parent.STORAGE_ID, child.IBLOCK_SECTION_ID, child.DATE_CREATE, " . $sqlHelper->getIsNullFunction('child.TIMESTAMP_X', 'child.DATE_CREATE') . ", " . $sqlHelper->getIsNullFunction('child.TIMESTAMP_X', 'child.DATE_CREATE') . ", " . $sqlHelper->getIsNullFunction('child.CREATED_BY', 0) . ", child.MODIFIED_BY, child.ID, child.ID, child.IBLOCK_ID FROM b_iblock_element child INNER JOIN b_disk_object parent ON child.IBLOCK_SECTION_ID = parent.ID AND parent.TYPE = 2 INNER JOIN b_iblock_property PROP_SIZE ON PROP_SIZE.IBLOCK_ID = child.IBLOCK_ID AND PROP_SIZE.CODE = 'WEBDAV_SIZE' INNER JOIN b_iblock_element_property PROP_SIZE_EL ON PROP_SIZE_EL.IBLOCK_PROPERTY_ID = PROP_SIZE.ID AND PROP_SIZE_EL.IBLOCK_ELEMENT_ID = child.ID INNER JOIN b_iblock_property PROP_FILE ON PROP_FILE.IBLOCK_ID = child.IBLOCK_ID AND PROP_FILE.CODE = 'FILE' INNER JOIN b_iblock_element_property PROP_FILE_EL ON PROP_FILE_EL.IBLOCK_PROPERTY_ID = PROP_FILE.ID AND PROP_FILE_EL.IBLOCK_ELEMENT_ID = child.ID LEFT JOIN b_iblock_property PROP_VERSION_G ON PROP_VERSION_G.IBLOCK_ID = child.IBLOCK_ID AND PROP_VERSION_G.CODE = 'WEBDAV_VERSION' LEFT JOIN b_iblock_element_property PPROP_VERSION_G_EL ON PPROP_VERSION_G_EL.IBLOCK_PROPERTY_ID = PROP_VERSION_G.ID AND PPROP_VERSION_G_EL.IBLOCK_ELEMENT_ID = child.ID {$whereIgnoreIblocks} "; } elseif($this->isOracle || $this->isMssql) { $sql = " INSERT INTO b_disk_object (FILE_ID, " . $this->sqlHelper->quote('SIZE') . ", GLOBAL_CONTENT_VERSION, NAME, TYPE, CODE, STORAGE_ID, PARENT_ID, CREATE_TIME, UPDATE_TIME, SYNC_UPDATE_TIME, CREATED_BY, UPDATED_BY, XML_ID, WEBDAV_ELEMENT_ID, WEBDAV_IBLOCK_ID) SELECT PROP_FILE_EL.VALUE, PROP_SIZE_EL.VALUE, " . $this->connection->getSqlHelper()->getIsNullFunction('PPROP_VERSION_G_EL.VALUE', 1) . ", child.NAME, 3, null, parent.STORAGE_ID, child.IBLOCK_SECTION_ID, child.DATE_CREATE, " . $sqlHelper->getIsNullFunction('child.TIMESTAMP_X', 'child.DATE_CREATE') . ", " . $sqlHelper->getIsNullFunction('child.TIMESTAMP_X', 'child.DATE_CREATE') . ", " . $sqlHelper->getIsNullFunction('child.CREATED_BY', 0) . ", child.MODIFIED_BY, child.ID, child.ID, child.IBLOCK_ID FROM b_iblock_element child INNER JOIN b_disk_object parent ON child.IBLOCK_SECTION_ID = parent.ID AND parent.TYPE = 2 INNER JOIN b_iblock_property PROP_SIZE ON PROP_SIZE.IBLOCK_ID = child.IBLOCK_ID AND PROP_SIZE.CODE = 'WEBDAV_SIZE' INNER JOIN b_iblock_element_property PROP_SIZE_EL ON PROP_SIZE_EL.IBLOCK_PROPERTY_ID = PROP_SIZE.ID AND PROP_SIZE_EL.IBLOCK_ELEMENT_ID = child.ID INNER JOIN b_iblock_property PROP_FILE ON PROP_FILE.IBLOCK_ID = child.IBLOCK_ID AND PROP_FILE.CODE = 'FILE' INNER JOIN b_iblock_element_property PROP_FILE_EL ON PROP_FILE_EL.IBLOCK_PROPERTY_ID = PROP_FILE.ID AND PROP_FILE_EL.IBLOCK_ELEMENT_ID = child.ID LEFT JOIN b_iblock_property PROP_VERSION_G ON PROP_VERSION_G.IBLOCK_ID = child.IBLOCK_ID AND PROP_VERSION_G.CODE = 'WEBDAV_VERSION' LEFT JOIN b_iblock_element_property PPROP_VERSION_G_EL ON PPROP_VERSION_G_EL.IBLOCK_PROPERTY_ID = PROP_VERSION_G.ID AND PPROP_VERSION_G_EL.IBLOCK_ELEMENT_ID = child.ID WHERE NOT EXISTS(SELECT 'x' FROM b_disk_object do WHERE do.NAME=child.NAME AND do.PARENT_ID = child.IBLOCK_SECTION_ID AND child.IBLOCK_SECTION_ID IS NOT NULL) {$conditionIgnoreIblocks} "; } $this->connection->queryExecute($sql); $this->connection->queryExecute(" INSERT INTO b_disk_object (FILE_ID, " . $this->sqlHelper->quote('SIZE') . ", GLOBAL_CONTENT_VERSION, NAME, TYPE, CODE, STORAGE_ID, PARENT_ID, CREATE_TIME, UPDATE_TIME, SYNC_UPDATE_TIME, CREATED_BY, UPDATED_BY, XML_ID, WEBDAV_ELEMENT_ID, WEBDAV_IBLOCK_ID) SELECT PROP_FILE_EL.VALUE, PROP_SIZE_EL.VALUE, " . $this->connection->getSqlHelper()->getIsNullFunction('PPROP_VERSION_G_EL.VALUE', 1) . ", " . $this->getConcatFunction('child.ID', 'child.NAME') . ", 3, null, parent.STORAGE_ID, child.IBLOCK_SECTION_ID, child.DATE_CREATE, " . $sqlHelper->getIsNullFunction('child.TIMESTAMP_X', 'child.DATE_CREATE') . ", " . $sqlHelper->getIsNullFunction('child.TIMESTAMP_X', 'child.DATE_CREATE') . ", " . $sqlHelper->getIsNullFunction('child.CREATED_BY', 0) . ", child.MODIFIED_BY, child.ID, child.ID, child.IBLOCK_ID FROM b_iblock_element child INNER JOIN b_disk_object parent ON child.IBLOCK_SECTION_ID = parent.ID AND parent.TYPE = 2 INNER JOIN b_iblock_property PROP_SIZE ON PROP_SIZE.IBLOCK_ID = child.IBLOCK_ID AND PROP_SIZE.CODE = 'WEBDAV_SIZE' INNER JOIN b_iblock_element_property PROP_SIZE_EL ON PROP_SIZE_EL.IBLOCK_PROPERTY_ID = PROP_SIZE.ID AND PROP_SIZE_EL.IBLOCK_ELEMENT_ID = child.ID INNER JOIN b_iblock_property PROP_FILE ON PROP_FILE.IBLOCK_ID = child.IBLOCK_ID AND PROP_FILE.CODE = 'FILE' INNER JOIN b_iblock_element_property PROP_FILE_EL ON PROP_FILE_EL.IBLOCK_PROPERTY_ID = PROP_FILE.ID AND PROP_FILE_EL.IBLOCK_ELEMENT_ID = child.ID LEFT JOIN b_iblock_property PROP_VERSION_G ON PROP_VERSION_G.IBLOCK_ID = child.IBLOCK_ID AND PROP_VERSION_G.CODE = 'WEBDAV_VERSION' LEFT JOIN b_iblock_element_property PPROP_VERSION_G_EL ON PPROP_VERSION_G_EL.IBLOCK_PROPERTY_ID = PROP_VERSION_G.ID AND PPROP_VERSION_G_EL.IBLOCK_ELEMENT_ID = child.ID WHERE NOT EXISTS(SELECT 'x' FROM b_disk_object do WHERE do.WEBDAV_ELEMENT_ID=child.ID) {$conditionIgnoreIblocks} "); } $this->setStepFinished(__METHOD__); $this->abortIfNeeded(true); } protected function setSymbolicLinks() { if($this->isStepFinished(__METHOD__)) { return; } //We know ID folders (b_disk_object) equal Id b_iblock_section if($this->isMysql) { $sql = " UPDATE b_disk_object obj_link INNER JOIN b_webdav_folder_invite old ON obj_link.ID = old.LINK_SECTION_ID AND obj_link.WEBDAV_SECTION_ID IS NOT NULL SET obj_link.REAL_OBJECT_ID = old.SECTION_ID WHERE old.IS_APPROVED = 1 AND old.IS_DELETED = 0 AND old.LINK_SECTION_ID IS NOT NULL "; } elseif($this->isOracle || $this->isMssql) { $sql = " UPDATE b_disk_object SET REAL_OBJECT_ID = ( SELECT OLD.SECTION_ID FROM b_disk_object obj_link INNER JOIN b_webdav_folder_invite OLD ON obj_link.ID = OLD.LINK_SECTION_ID AND obj_link.WEBDAV_SECTION_ID IS NOT NULL WHERE b_disk_object.ID = obj_link.ID AND OLD.IS_APPROVED = 1 AND OLD.IS_DELETED = 0 AND OLD.LINK_SECTION_ID IS NOT NULL ) WHERE EXISTS((SELECT OLD.SECTION_ID FROM b_disk_object obj_link INNER JOIN b_webdav_folder_invite OLD ON obj_link.ID = OLD.LINK_SECTION_ID AND obj_link.WEBDAV_SECTION_ID IS NOT NULL WHERE b_disk_object.ID = obj_link.ID AND OLD.IS_APPROVED = 1 AND OLD.IS_DELETED = 0 AND OLD.LINK_SECTION_ID IS NOT NULL )) "; } $this->connection->queryExecute($sql); if($this->isMysql) { $sql = " UPDATE b_disk_object obj_link INNER JOIN ( SELECT t1.ID FROM b_disk_object t1 LEFT JOIN b_disk_object t2 ON t2.ID = t1.REAL_OBJECT_ID WHERE t2.ID IS NULL ) bad_link ON obj_link.ID = bad_link.ID SET obj_link.REAL_OBJECT_ID = obj_link.ID "; } elseif($this->isOracle || $this->isMssql) { $sql = " UPDATE b_disk_object SET REAL_OBJECT_ID = (SELECT obj_link.ID FROM b_disk_object obj_link, (SELECT ID FROM b_disk_object l WHERE l.REAL_OBJECT_ID IS NOT NULL AND NOT EXISTS(SELECT 'x' FROM b_disk_object o WHERE o.ID = l.REAL_OBJECT_ID)) bad_link WHERE obj_link.ID = bad_link.ID AND b_disk_object.ID = obj_link.ID ) WHERE EXISTS(SELECT obj_link.ID FROM b_disk_object obj_link, (SELECT ID FROM b_disk_object l WHERE l.REAL_OBJECT_ID IS NOT NULL AND NOT EXISTS(SELECT 'x' FROM b_disk_object o WHERE o.ID = l.REAL_OBJECT_ID)) bad_link WHERE obj_link.ID = bad_link.ID AND b_disk_object.ID = obj_link.ID ) "; } $this->connection->queryExecute($sql); $this->setStepFinished(__METHOD__); } protected function moveSharings() { if($this->isStepFinished(__METHOD__)) { return; } $sqlHelper = $this->connection->getSqlHelper(); //we migrate only approved sharing $approved = SharingTable::STATUS_IS_APPROVED; $type = SharingTable::TYPE_TO_USER; //We know ID folders (b_disk_object) equal Id b_iblock_section $this->connection->queryExecute(" INSERT INTO b_disk_sharing (PARENT_ID, CREATED_BY, FROM_ENTITY, TO_ENTITY, LINK_STORAGE_ID, LINK_OBJECT_ID, REAL_OBJECT_ID, REAL_STORAGE_ID, DESCRIPTION, CAN_FORWARD, STATUS, TYPE, TASK_NAME) SELECT null, old.USER_ID, " . $this->getConcatFunction("'U'", 'old.USER_ID') . ", " . $this->getConcatFunction("'U'", 'old.INVITE_USER_ID') . ", obj_link.STORAGE_ID, obj_link.ID, obj_real.ID, obj_real.STORAGE_ID, old.DESCRIPTION, 0, {$approved}, {$type}, 'disk_access_read' from b_webdav_folder_invite old INNER JOIN b_disk_object obj_real ON obj_real.ID = old.SECTION_ID AND obj_real.WEBDAV_SECTION_ID IS NOT NULL INNER JOIN b_disk_object obj_link ON obj_link.ID = old.LINK_SECTION_ID AND obj_link.WEBDAV_SECTION_ID IS NOT NULL WHERE old.IS_APPROVED = 1 AND old.IS_DELETED = 0 AND old.LINK_SECTION_ID IS NOT NULL "); $this->setStepFinished(__METHOD__); } protected function moveExternalLinks() { if($this->isStepFinished(__METHOD__)) { return; } if($this->isMysql) { $sql = " INSERT INTO b_disk_external_link (OBJECT_ID, VERSION_ID, HASH, PASSWORD, SALT, DEATH_TIME, DESCRIPTION, DOWNLOAD_COUNT, TYPE, CREATE_TIME, CREATED_BY) SELECT obj.ID, null, old_ext.HASH, old_ext.PASSWORD, old_ext.SALT, IF(old_ext.LIFETIME - old_ext.CREATION_DATE <> 315360000, FROM_UNIXTIME(old_ext.LIFETIME), null), old_ext.DESCRIPTION, old_ext.DOWNLOAD_COUNT, 3, FROM_UNIXTIME(old_ext.CREATION_DATE), old_ext.USER_ID FROM b_webdav_ext_links old_ext INNER JOIN b_disk_object obj ON old_ext.ELEMENT_ID = obj.WEBDAV_ELEMENT_ID AND obj.WEBDAV_ELEMENT_ID IS NOT NULL "; } elseif($this->isOracle) { $sql = " INSERT INTO b_disk_external_link (OBJECT_ID, VERSION_ID, HASH, PASSWORD, SALT, DEATH_TIME, DESCRIPTION, DOWNLOAD_COUNT, TYPE, CREATE_TIME, CREATED_BY) SELECT obj.ID, null, old_ext.HASH, old_ext.PASSWORD, old_ext.SALT, (CASE WHEN old_ext.LIFETIME - old_ext.CREATION_DATE <> 315360000 THEN to_char( to_date('01011970','ddmmyyyy') + 1/24/60/60 * old_ext.LIFETIME, 'dd-mon-yyyy hh24:mi:ss') ELSE null END), old_ext.DESCRIPTION, old_ext.DOWNLOAD_COUNT, 3, to_char( to_date('01011970','ddmmyyyy') + 1/24/60/60 * old_ext.CREATION_DATE, 'dd-mon-yyyy hh24:mi:ss'), old_ext.USER_ID FROM b_webdav_ext_links old_ext INNER JOIN b_disk_object obj ON old_ext.ELEMENT_ID = obj.WEBDAV_ELEMENT_ID AND obj.WEBDAV_ELEMENT_ID IS NOT NULL "; } elseif($this->isMssql) { $sql = " INSERT INTO b_disk_external_link (OBJECT_ID, VERSION_ID, HASH, PASSWORD, SALT, DEATH_TIME, DESCRIPTION, DOWNLOAD_COUNT, TYPE, CREATE_TIME, CREATED_BY) SELECT obj.ID, null, old_ext.HASH, old_ext.PASSWORD, old_ext.SALT, (CASE WHEN old_ext.LIFETIME - old_ext.CREATION_DATE <> 315360000 THEN dateadd(s, old_ext.LIFETIME, '19700101 05:00:00:000') ELSE null END), old_ext.DESCRIPTION, old_ext.DOWNLOAD_COUNT, 3, dateadd(s, old_ext.CREATION_DATE, '19700101 05:00:00:000'), old_ext.USER_ID FROM b_webdav_ext_links old_ext INNER JOIN b_disk_object obj ON old_ext.ELEMENT_ID = obj.WEBDAV_ELEMENT_ID AND obj.WEBDAV_ELEMENT_ID IS NOT NULL "; } $this->connection->queryExecute($sql); $this->setStepFinished(__METHOD__); } protected function migrateOptions() { if($this->isStepFinished(__METHOD__)) { return array(0, 0); } $successCount = $failedCount = 0; Option::set( 'disk', 'disk_allow_autoconnect_shared_objects', Option::get('webdav', 'webdav_allow_autoconnect_share_group_folder', 'Y') ); Option::set( 'disk', 'disk_allow_create_file_by_cloud', Option::get('webdav', 'webdav_allow_ext_doc_services_global', 'Y') ); $this->setStepFinished(__METHOD__); return array($successCount, $failedCount); } protected function storeConvertedUserFieldId($id) { COption::SetOptionString( 'disk', '~migrateUf', $id ); } protected function getLastConvertedUserFieldId() { return COption::getOptionString( 'disk', '~migrateUf', 0 ); } protected function storeConvertedUserFieldRowId($ufId, $id) { COption::SetOptionString( 'disk', '~migrateUfRow' . $ufId, $id ); } protected function getLastConvertedUserFieldRowId($ufId) { return COption::getOptionString( 'disk', '~migrateUfRow' . $ufId, 0 ); } protected function moveWebdavElement() { $this->abortIfNeeded(); if($this->isStepFinished(__METHOD__)) { return array(0, 0); } $sqlHelper = $this->connection->getSqlHelper(); $successCount = $failedCount = 0; $this->log(array( 'Start move uf webdav element', )); $userFieldManager = Driver::getInstance()->getUserFieldManager(); $connection = Application::getInstance()->getConnection(); $userTypeId = $connection->getSqlHelper()->forSql('webdav_element'); $lastId = $this->getLastConvertedUserFieldId(); $result = $connection->query("SELECT * from b_user_field WHERE USER_TYPE_ID = '{$userTypeId}' AND ID > {$lastId} ORDER BY ID ASC"); while($userFieldRow = $result->fetch()) { $this->abortIfNeeded(); $entityName = $userFieldRow['ENTITY_ID']; if($userFieldRow['MULTIPLE'] == 'Y') { list($connectorClass, $moduleId) = $userFieldManager->getConnectorDataByEntityType($userFieldRow['ENTITY_ID']); $tableNameUf = "b_utm_".strtolower($entityName); $tableNameSingleUf = "b_uts_".strtolower($entityName); if($entityName == 'SONET_LOG') { if($this->isMssql) { $this->connection->queryExecute(" SELECT * INTO b_disk_utm_sonet_log_crm FROM (SELECT so.* FROM {$tableNameUf} so INNER JOIN b_sonet_log log ON log.ID = so.VALUE_ID WHERE so.FIELD_ID = {$userFieldRow['ID']} AND log.EVENT_ID in ('crm_activity_add', 'crm_lead_message', 'crm_contact_message', 'crm_company_message', 'crm_deal_message', 'crm_activity_message', 'crm_invoice_message')) tmp "); } else { $this->connection->queryExecute(" CREATE TABLE b_disk_utm_sonet_log_crm AS SELECT so.* FROM {$tableNameUf} so INNER JOIN b_sonet_log log ON log.ID = so.VALUE_ID WHERE so.FIELD_ID = {$userFieldRow['ID']} AND log.EVENT_ID in ('crm_activity_add', 'crm_lead_message', 'crm_contact_message', 'crm_company_message', 'crm_deal_message', 'crm_activity_message', 'crm_invoice_message') "); } $tableNameUf = 'b_disk_utm_sonet_log_crm'; $this->connection->query("CREATE INDEX IX_UTM_TMP_1 on {$tableNameUf}(FIELD_ID, VALUE_INT)"); } if($entityName == 'SONET_COMMENT') { if($this->isMssql) { $this->connection->queryExecute(" SELECT * INTO b_disk_utm_sonet_comment_crm FROM (SELECT so.* FROM {$tableNameUf} so INNER JOIN b_sonet_log_comment logc ON logc.ID = so.VALUE_ID WHERE so.FIELD_ID = {$userFieldRow['ID']} AND logc.EVENT_ID in ('crm_lead_message_comment', 'crm_contact_message_comment', 'crm_company_message_comment', 'crm_deal_message_comment', 'crm_activity_message_comment', 'crm_invoice_message_comment', 'crm_lead_add_comment', 'crm_contact_add_comment', 'crm_company_add_comment', 'crm_deal_add_comment', 'crm_activity_add_comment', 'crm_invoice_add_comment', 'crm_lead_progress_comment', 'crm_contact_progress_comment', 'crm_company_progress_comment', 'crm_deal_progress_comment', 'crm_activity_progress_comment', 'crm_invoice_progress_comment', 'crm_lead_denomination_comment', 'crm_contact_denomination_comment', 'crm_company_denomination_comment', 'crm_deal_denomination_comment', 'crm_activity_denomination_comment', 'crm_invoice_denomination_comment', 'crm_lead_client_comment', 'crm_contact_client_comment', 'crm_company_client_comment', 'crm_deal_client_comment', 'crm_activity_client_comment', 'crm_invoice_client_comment', 'crm_lead_owner_comment', 'crm_contact_owner_comment', 'crm_company_owner_comment', 'crm_deal_owner_comment', 'crm_activity_owner_comment', 'crm_invoice_owner_comment', 'crm_lead_custom_comment', 'crm_contact_custom_comment', 'crm_company_custom_comment', 'crm_deal_custom_comment', 'crm_activity_custom_comment', 'crm_invoice_custom_comment', 'crm_lead_responsible_comment', 'crm_contact_responsible_comment', 'crm_company_responsible_comment', 'crm_deal_responsible_comment', 'crm_activity_responsible_comment', 'crm_invoice_responsible_comment')) tmp "); } else { $this->connection->queryExecute(" CREATE TABLE b_disk_utm_sonet_comment_crm AS SELECT so.* FROM {$tableNameUf} so INNER JOIN b_sonet_log_comment logc ON logc.ID = so.VALUE_ID WHERE so.FIELD_ID = {$userFieldRow['ID']} AND logc.EVENT_ID in ('crm_lead_message_comment', 'crm_contact_message_comment', 'crm_company_message_comment', 'crm_deal_message_comment', 'crm_activity_message_comment', 'crm_invoice_message_comment', 'crm_lead_add_comment', 'crm_contact_add_comment', 'crm_company_add_comment', 'crm_deal_add_comment', 'crm_activity_add_comment', 'crm_invoice_add_comment', 'crm_lead_progress_comment', 'crm_contact_progress_comment', 'crm_company_progress_comment', 'crm_deal_progress_comment', 'crm_activity_progress_comment', 'crm_invoice_progress_comment', 'crm_lead_denomination_comment', 'crm_contact_denomination_comment', 'crm_company_denomination_comment', 'crm_deal_denomination_comment', 'crm_activity_denomination_comment', 'crm_invoice_denomination_comment', 'crm_lead_client_comment', 'crm_contact_client_comment', 'crm_company_client_comment', 'crm_deal_client_comment', 'crm_activity_client_comment', 'crm_invoice_client_comment', 'crm_lead_owner_comment', 'crm_contact_owner_comment', 'crm_company_owner_comment', 'crm_deal_owner_comment', 'crm_activity_owner_comment', 'crm_invoice_owner_comment', 'crm_lead_custom_comment', 'crm_contact_custom_comment', 'crm_company_custom_comment', 'crm_deal_custom_comment', 'crm_activity_custom_comment', 'crm_invoice_custom_comment', 'crm_lead_responsible_comment', 'crm_contact_responsible_comment', 'crm_company_responsible_comment', 'crm_deal_responsible_comment', 'crm_activity_responsible_comment', 'crm_invoice_responsible_comment') "); } $tableNameUf = 'b_disk_utm_sonet_comment_crm'; $this->connection->query("CREATE INDEX IX_UTM_TMP_21 on {$tableNameUf}(FIELD_ID, VALUE_INT)"); } $moduleId = $sqlHelper->forSql($moduleId); $connectorClass = $sqlHelper->forSql($connectorClass); //create new attached objects from old uf values $this->connection->queryExecute(" INSERT INTO b_disk_attached_object (OBJECT_ID, VERSION_ID, IS_EDITABLE, MODULE_ID, ENTITY_TYPE, ENTITY_ID, CREATE_TIME, CREATED_BY) SELECT obj.ID, null, 2, '{$moduleId}', '{$connectorClass}', uf.VALUE_ID, " . $this->sqlHelper->getCurrentDateTimeFunction() . ", 0 FROM {$tableNameUf} uf INNER JOIN b_disk_object obj ON obj.WEBDAV_ELEMENT_ID = uf.VALUE_INT AND uf.FIELD_ID = {$userFieldRow['ID']} AND obj.WEBDAV_ELEMENT_ID IS NOT NULL "); //replace old values new attached id (above sql) if($this->isMysql) { $sql = " UPDATE {$tableNameUf} uf INNER JOIN b_disk_object obj ON uf.VALUE_INT = obj.WEBDAV_ELEMENT_ID AND obj.WEBDAV_ELEMENT_ID IS NOT NULL INNER JOIN b_disk_attached_object attach ON attach.OBJECT_ID = obj.ID AND attach.ENTITY_ID = uf.VALUE_ID AND attach.ENTITY_TYPE = '{$connectorClass}' AND attach.MODULE_ID = '{$moduleId}' SET uf.VALUE_INT = attach.ID WHERE uf.FIELD_ID = {$userFieldRow['ID']} "; } elseif($this->isOracle || $this->isMssql) { $sql = " UPDATE {$tableNameUf} SET VALUE_INT = (SELECT attach.ID FROM {$tableNameUf} uf INNER JOIN b_disk_object obj ON uf.VALUE_INT = obj.WEBDAV_ELEMENT_ID AND obj.WEBDAV_ELEMENT_ID IS NOT NULL INNER JOIN b_disk_attached_object attach ON attach.OBJECT_ID = obj.ID AND attach.ENTITY_ID = uf.VALUE_ID AND attach.ENTITY_TYPE = '{$connectorClass}' AND attach.MODULE_ID = '{$moduleId}' WHERE {$tableNameUf}.VALUE_ID = uf.VALUE_ID AND uf.FIELD_ID = {$userFieldRow['ID']} ) WHERE EXISTS (SELECT attach.ID FROM {$tableNameUf} uf INNER JOIN b_disk_object obj ON uf.VALUE_INT = obj.WEBDAV_ELEMENT_ID AND obj.WEBDAV_ELEMENT_ID IS NOT NULL INNER JOIN b_disk_attached_object attach ON attach.OBJECT_ID = obj.ID AND attach.ENTITY_ID = uf.VALUE_ID AND attach.ENTITY_TYPE = '{$connectorClass}' AND attach.MODULE_ID = '{$moduleId}' WHERE {$tableNameUf}.VALUE_ID = uf.VALUE_ID AND uf.FIELD_ID = {$userFieldRow['ID']} ) "; } $this->connection->queryExecute($sql); //Done. But we don't forget to recalc b_uts_ where we should be serialized data ^( if($entityName != 'SONET_LOG' && $entityName != 'SONET_COMMENT') { $this->connection->queryExecute("UPDATE b_user_field SET USER_TYPE_ID = 'disk_file' WHERE ID = {$userFieldRow['ID']}"); if($this->isMssql) { $this->connection->queryExecute("UPDATE {$tableNameSingleUf} SET {$userFieldRow['FIELD_NAME']} = CAST(VALUE_ID AS VARCHAR(255))"); } else { $this->connection->queryExecute("UPDATE {$tableNameSingleUf} SET {$userFieldRow['FIELD_NAME']} = VALUE_ID"); } } } else { list($connectorClass, $moduleId) = $userFieldManager->getConnectorDataByEntityType($userFieldRow['ENTITY_ID']); $tableNameSingleUf = "b_uts_".strtolower($entityName); $moduleId = $sqlHelper->forSql($moduleId); $connectorClass = $sqlHelper->forSql($connectorClass); //create new attached objects from old uf values $this->connection->queryExecute(" INSERT INTO b_disk_attached_object (OBJECT_ID, VERSION_ID, IS_EDITABLE, MODULE_ID, ENTITY_TYPE, ENTITY_ID, CREATE_TIME, CREATED_BY) SELECT obj.ID, null, 2, '{$moduleId}', '{$connectorClass}', uf.VALUE_ID, " . $this->sqlHelper->getCurrentDateTimeFunction() . ", 0 FROM {$tableNameSingleUf} uf INNER JOIN b_disk_object obj ON obj.WEBDAV_ELEMENT_ID = uf.{$userFieldRow['FIELD_NAME']} AND obj.WEBDAV_ELEMENT_ID IS NOT NULL "); //replace old values new attached id (above sql) if($this->isMysql) { $sql = " UPDATE {$tableNameSingleUf} uf INNER JOIN b_disk_object obj ON uf.{$userFieldRow['FIELD_NAME']} = obj.WEBDAV_ELEMENT_ID AND obj.WEBDAV_ELEMENT_ID IS NOT NULL INNER JOIN b_disk_attached_object attach ON attach.OBJECT_ID = obj.ID AND attach.ENTITY_ID = uf.VALUE_ID AND attach.ENTITY_TYPE = '{$connectorClass}' AND attach.MODULE_ID = '{$moduleId}' SET uf.{$userFieldRow['FIELD_NAME']} = attach.ID "; } elseif($this->isOracle || $this->isMssql) { $sql = " UPDATE {$tableNameSingleUf} SET {$userFieldRow['FIELD_NAME']} = (SELECT attach.ID FROM {$tableNameSingleUf} uf INNER JOIN b_disk_object obj ON uf.{$userFieldRow['FIELD_NAME']} = obj.WEBDAV_ELEMENT_ID AND obj.WEBDAV_ELEMENT_ID IS NOT NULL INNER JOIN b_disk_attached_object attach ON attach.OBJECT_ID = obj.ID AND attach.ENTITY_ID = uf.VALUE_ID AND attach.ENTITY_TYPE = '{$connectorClass}' AND attach.MODULE_ID = '{$moduleId}' WHERE {$tableNameSingleUf}.VALUE_ID = uf.VALUE_ID ) WHERE EXISTS (SELECT attach.ID FROM {$tableNameSingleUf} uf INNER JOIN b_disk_object obj ON uf.{$userFieldRow['FIELD_NAME']} = obj.WEBDAV_ELEMENT_ID AND obj.WEBDAV_ELEMENT_ID IS NOT NULL INNER JOIN b_disk_attached_object attach ON attach.OBJECT_ID = obj.ID AND attach.ENTITY_ID = uf.VALUE_ID AND attach.ENTITY_TYPE = '{$connectorClass}' AND attach.MODULE_ID = '{$moduleId}' WHERE {$tableNameSingleUf}.VALUE_ID = uf.VALUE_ID ) "; } $this->connection->queryExecute($sql); $this->connection->queryExecute("UPDATE b_user_field SET USER_TYPE_ID = 'disk_file' WHERE ID = {$userFieldRow['ID']}"); } $this->storeConvertedUserFieldId($userFieldRow['ID']); } $this->setStepFinished(__METHOD__); $this->log(array( 'Finish move uf webdav element', )); //we store 0, and use this options in @migrateWebdavElement@ $this->storeConvertedUserFieldId(0); return array($successCount, $failedCount); } protected function migrateWebdavElementInSocnet() { $this->abortIfNeeded(); if($this->isStepFinished(__METHOD__)) { return array(0, 0); } $successCount = $failedCount = 0; $this->log(array( 'Start move uf webdav element sonet', )); $connection = Application::getInstance()->getConnection(); $userTypeId = $connection->getSqlHelper()->forSql('webdav_element'); $lastId = $this->getLastConvertedUserFieldId(); $result = $connection->query("SELECT * from b_user_field WHERE USER_TYPE_ID = '{$userTypeId}' AND ID > {$lastId} AND ENTITY_ID IN ('SONET_COMMENT', 'SONET_LOG') ORDER BY ID ASC"); while($userFieldRow = $result->fetch()) { $this->abortIfNeeded(); if($userFieldRow['ENTITY_ID'] == 'SONET_LOG') { if($userFieldRow['MULTIPLE'] == 'Y') { $tableNameUf = "b_utm_sonet_log"; $tableNameSingleUf = "b_uts_sonet_log"; $this->connection->queryExecute(" DELETE FROM {$tableNameUf} WHERE FIELD_ID = {$userFieldRow['ID']} "); foreach(array( 'tasks' => 'tasks_task', 'blog_post' => 'blog_post', 'blog_post_important' => 'blog_post', 'calendar' => 'calendar_event', 'forum' => 'forum_message', ) as $eventId => $connectedEntityName) { $tableNameUfConnected = "b_utm_".strtolower($connectedEntityName); $eventId = $this->sqlHelper->forSql($eventId); if(!$this->connection->isTableExists($tableNameUfConnected)) { continue; } $this->connection->queryExecute(" INSERT INTO {$tableNameUf} (VALUE_ID, FIELD_ID, VALUE_INT) SELECT log.ID, {$userFieldRow['ID']}, origuf.VALUE_INT FROM b_sonet_log log INNER JOIN {$tableNameUfConnected} origuf ON origuf.VALUE_ID = log.SOURCE_ID WHERE " . ($this->isOracle? '' : " log.SOURCE_ID <> '' AND ") . " log.SOURCE_ID IS NOT NULL AND log.EVENT_ID = '{$eventId}' "); } $this->connection->queryExecute(" INSERT INTO {$tableNameUf} (VALUE_ID, FIELD_ID, VALUE_INT) SELECT VALUE_ID, FIELD_ID, VALUE_INT FROM b_disk_utm_sonet_log_crm "); $this->connection->queryExecute("UPDATE b_user_field SET USER_TYPE_ID = 'disk_file' WHERE ID = {$userFieldRow['ID']}"); if($this->isMssql) { $this->connection->queryExecute("UPDATE {$tableNameSingleUf} SET {$userFieldRow['FIELD_NAME']} = CAST(VALUE_ID AS VARCHAR(255))"); } else { $this->connection->queryExecute("UPDATE {$tableNameSingleUf} SET {$userFieldRow['FIELD_NAME']} = VALUE_ID"); } $this->storeConvertedUserFieldId($userFieldRow['ID']); } } elseif($userFieldRow['ENTITY_ID'] == 'SONET_COMMENT') { if($userFieldRow['MULTIPLE'] == 'Y') { $tableNameUf = "b_utm_sonet_comment"; $tableNameSingleUf = "b_uts_sonet_comment"; $this->connection->queryExecute(" DELETE FROM {$tableNameUf} WHERE FIELD_ID = {$userFieldRow['ID']} "); foreach(array( 'blog_comment' => 'blog_comment', 'calendar_comment' => 'forum_message', 'forum' => 'forum_message', 'idea_comment' => 'blog_comment', 'news_comment' => 'forum_message', 'photo_comment' => 'forum_message', 'report_comment' => 'forum_message', 'tasks_comment' => 'forum_message', 'wiki_comment' => 'forum_message', ) as $eventId => $connectedEntityName) { $tableNameUfConnected = "b_utm_".strtolower($connectedEntityName); $eventId = $this->sqlHelper->forSql($eventId); if(!$this->connection->isTableExists($tableNameUfConnected)) { continue; } $this->connection->queryExecute(" INSERT INTO {$tableNameUf} (VALUE_ID, FIELD_ID, VALUE_INT) SELECT log.ID, {$userFieldRow['ID']}, origuf.VALUE_INT FROM b_sonet_log_comment log INNER JOIN {$tableNameUfConnected} origuf ON origuf.VALUE_ID = log.SOURCE_ID WHERE " . ($this->isOracle? '' : " log.SOURCE_ID <> '' AND ") . " log.SOURCE_ID IS NOT NULL AND log.EVENT_ID = '{$eventId}' "); } $this->connection->queryExecute(" INSERT INTO {$tableNameUf} (VALUE_ID, FIELD_ID, VALUE_INT) SELECT VALUE_ID, FIELD_ID, VALUE_INT FROM b_disk_utm_sonet_comment_crm "); $this->connection->queryExecute("UPDATE b_user_field SET USER_TYPE_ID = 'disk_file' WHERE ID = {$userFieldRow['ID']}"); if($this->isMssql) { $this->connection->queryExecute("UPDATE {$tableNameSingleUf} SET {$userFieldRow['FIELD_NAME']} = CAST(VALUE_ID AS VARCHAR(255))"); } else { $this->connection->queryExecute("UPDATE {$tableNameSingleUf} SET {$userFieldRow['FIELD_NAME']} = VALUE_ID"); } $this->storeConvertedUserFieldId($userFieldRow['ID']); } } $this->storeConvertedUserFieldId($userFieldRow['ID']); } $this->setStepFinished(__METHOD__); $this->log(array( 'Finish move uf webdav element sonet', )); //we store 0, and use this options in @migrateWebdavElement@ $this->storeConvertedUserFieldId(0); return array($successCount, $failedCount); } private function getLastVersionByElementId($elementId) { $elementId = (int)$elementId; $version = $this->connection->query(" SELECT MAX(v.ID) LAST_VERSION, MAX(v.OBJECT_ID) OBJECT_ID FROM b_disk_version v INNER JOIN b_disk_object obj ON obj.ID = v.OBJECT_ID WHERE obj.WEBDAV_ELEMENT_ID = {$elementId} ")->fetch(); return $version? array($version['LAST_VERSION'], $version['OBJECT_ID']) : null; } private function getLastVersionByBpId($bpId) { $bpId = (int)$bpId; $version = $this->connection->query(" SELECT v.ID LAST_VERSION, v.OBJECT_ID OBJECT_ID FROM b_disk_version v WHERE v.BP_VERSION_ID = {$bpId} ")->fetch(); return $version? array($version['LAST_VERSION'], $version['OBJECT_ID']) : null; } protected function migrateWebdavElementHistory() { $this->abortIfNeeded(); if($this->isStepFinished(__METHOD__)) { return; } $userFieldManager = Driver::getInstance()->getUserFieldManager(); $connection = $this->connection; $rsData = CUserTypeEntity::GetList(array(), array( "ENTITY_ID" => "BLOG_COMMENT", "XML_ID" => "UF_BLOG_COMMENT_FH", )); if(!$rsData->fetch()) { $this->setStepFinished(__METHOD__); $this->log(array( 'Could not find UF_BLOG_COMMENT_FH in entity BLOG_COMMENT', )); return; } unset($rsData); if(!$connection->isTableExists('b_uts_blog_comment') || !$connection->getTableField('b_uts_blog_comment', 'UF_BLOG_COMMENT_FH')) { $this->setStepFinished(__METHOD__); $this->log(array( 'b_uts_blog_comment does not exist or column UF_BLOG_COMMENT_FH does not exist.', )); return; } unset($rsData); list($connectorClass, $moduleId) = $userFieldManager->getConnectorDataByEntityType('BLOG_COMMENT'); $lastId = $this->getStorageId(); $result = $connection->query("SELECT * from b_uts_blog_comment WHERE VALUE_ID > {$lastId} AND UF_BLOG_COMMENT_FH <> '' ORDER BY VALUE_ID ASC"); while($userFieldRow = $result->fetch()) { $this->abortIfNeeded(); $dataFromValue = CUserTypeWebdavElementHistory::getDataFromValue($userFieldRow['UF_BLOG_COMMENT_FH']); if(!$dataFromValue) { $this->storeStorageId($userFieldRow['VALUE_ID']); continue; } $dataFromValue = $dataFromValue[0]; //this is head version if(empty($dataFromValue['v'])) { list($newVersionId, $objectId) = $this->getLastVersionByElementId($dataFromValue['id']); if(!$newVersionId || !$objectId) { $this->storeStorageId($userFieldRow['VALUE_ID']); $this->log(array( 'Could not find migrate Head Version from disk. Skip.', $userFieldRow, )); continue; } $errorCollection = new ErrorCollection(); $attachedData = array( 'MODULE_ID' => $moduleId, 'OBJECT_ID' => $objectId, 'VERSION_ID' => $newVersionId, 'ENTITY_ID' => $userFieldRow['VALUE_ID'], 'ENTITY_TYPE' => $connectorClass, 'IS_EDITABLE' => 2, ); $attachedModel = AttachedObject::add($attachedData, $errorCollection); if(!$attachedModel || $errorCollection->hasErrors()) { $this->storeStorageId($userFieldRow['VALUE_ID']); $this->log(array( 'Could not created attached object', )); continue; } $connection->queryExecute("UPDATE b_uts_blog_comment SET UF_BLOG_COMMENT_FH = '{$attachedModel->getId()}' WHERE VALUE_ID = {$userFieldRow['VALUE_ID']}"); $this->storeStorageId($userFieldRow['VALUE_ID']); continue; } //this is specific version of file else { list($newVersionId, $objectId) = $this->getLastVersionByBpId($dataFromValue['v']); if(!$newVersionId || !$objectId) { $this->storeStorageId($userFieldRow['VALUE_ID']); $this->log(array( 'Could not find migrate Version from disk. Skip.', $userFieldRow, )); continue; } $errorCollection = new ErrorCollection(); $attachedData = array( 'MODULE_ID' => $moduleId, 'OBJECT_ID' => $objectId, 'VERSION_ID' => $newVersionId, 'ENTITY_ID' => $userFieldRow['VALUE_ID'], 'ENTITY_TYPE' => $connectorClass, 'IS_EDITABLE' => 2, ); $attachedModel = AttachedObject::add($attachedData, $errorCollection); if(!$attachedModel || $errorCollection->hasErrors()) { $this->storeStorageId($userFieldRow['VALUE_ID']); $this->log(array( 'Could not created attached object', $userFieldRow, )); continue; } $connection->queryExecute("UPDATE b_uts_blog_comment SET UF_BLOG_COMMENT_FH = '{$attachedModel->getId()}' WHERE VALUE_ID = {$userFieldRow['VALUE_ID']}"); $this->storeStorageId($userFieldRow['VALUE_ID']); continue; } } $connection->queryExecute("UPDATE b_user_field SET USER_TYPE_ID = 'disk_version' WHERE ENTITY_ID = 'BLOG_COMMENT' AND XML_ID = 'UF_BLOG_COMMENT_FH'"); $this->storeStorageId(0); $this->setStepFinished(__METHOD__); return; } protected function migrateDataCommonStorages() { if($this->isStepFinished(__METHOD__)) { return array(0, 0); } $lastId = $this->getLastIblockId(); if($this->isOracle && $lastId == 0) { //we support 10g : ( $maxId = $this->connection->queryScalar('SELECT MAX(ID) MAX FROM b_disk_object'); $maxId++; $seqId = $this->connection->query('SELECT sq_b_disk_object.NEXTVAL NEXTVAL FROM DUAL')->fetch(); $seqId = $seqId['NEXTVAL']; $diffId = $maxId - $seqId; if($diffId > 0) { $this->connection->queryExecute("ALTER SEQUENCE sq_b_disk_object INCREMENT BY {$diffId}"); $this->connection->queryExecute("SELECT sq_b_disk_object.NEXTVAL NEXTVAL FROM DUAL"); $this->connection->queryExecute("ALTER SEQUENCE sq_b_disk_object INCREMENT BY 1"); } } foreach($this->getIblockIdsWithCommonFiles() as $iblock) { if($lastId > $iblock['ID']) { continue; } $this->abortIfNeeded(); $this->log(array( __METHOD__, 'start', $iblock['ID'], )); $iblockId = (int)$iblock['ID']; $sqlHelper = $this->connection->getSqlHelper(); $name = $sqlHelper->forSql($iblock['NAME']); $proxyType = $sqlHelper->forSql(ProxyType\Common::className()); $storageRow = $this->connection->query("SELECT * FROM b_disk_storage WHERE XML_ID = '{$iblockId}' AND ENTITY_TYPE = '{$proxyType}'")->fetch(); if(!$storageRow) { $this->log(array( __METHOD__, 'Error. Could not find storage by XML_ID', $iblock['ID'], "WHERE XML_ID = '{$iblockId}' AND ENTITY_TYPE = '{$proxyType}'", )); $this->storeIblockId($iblock['ID']); continue; } $storageId = $storageRow['ID']; $this->connection->queryExecute(" INSERT INTO b_disk_object (NAME, TYPE, CODE, STORAGE_ID, PARENT_ID, CREATE_TIME, UPDATE_TIME, SYNC_UPDATE_TIME, WEBDAV_IBLOCK_ID) SELECT '{$name}', 2, null, {$storageId}, null, ib.TIMESTAMP_X, ib.TIMESTAMP_X, ib.TIMESTAMP_X, ib.ID FROM b_iblock ib WHERE ib.ID = {$iblockId} "); $rootObjectId = null; if($this->isMysql || $this->isMssql) { $rootObjectId = (int)$this->connection->getInsertedId(); } elseif($this->isOracle) { $rootObjectId = $this->connection->queryScalar('SELECT MAX(ID) MAX FROM b_disk_object'); } if(!$rootObjectId) { $this->log(array( __METHOD__, 'Error. Could not insert root object', array( $name, $storageId, $iblockId, ) )); $this->storeIblockId($iblock['ID']); continue; } if($this->isMysql) { $sql = " UPDATE b_disk_object do, ( SELECT NAME, MIN(ID) ID, COUNT(*) C FROM b_disk_object WHERE STORAGE_ID = {$storageId} AND PARENT_ID IS NULL AND ID <> {$rootObjectId} GROUP BY NAME HAVING C>1 ) dbl SET do.NAME = " . $this->getConcatFunction('do.NAME', 'do.ID') . " WHERE do.STORAGE_ID = {$storageId} AND do.PARENT_ID IS NULL AND do.ID <> {$rootObjectId} AND do.ID > dbl.ID AND do.NAME=dbl.NAME "; } elseif($this->isOracle || $this->isMssql) { $sql = " UPDATE b_disk_object SET NAME = ( SELECT " . $this->getConcatFunction('do.NAME', 'do.ID') . " FROM b_disk_object do, ( SELECT NAME, MIN(ID) ID, COUNT(*) C FROM b_disk_object WHERE STORAGE_ID = {$storageId} AND PARENT_ID IS NULL AND ID <> {$rootObjectId} GROUP BY NAME HAVING COUNT(*)>1 ) dbl WHERE do.STORAGE_ID = {$storageId} AND do.PARENT_ID IS NULL AND do.ID <> {$rootObjectId} AND do.ID > dbl.ID AND do.NAME=dbl.NAME AND b_disk_object.ID = do.ID ) WHERE EXISTS ( SELECT " . $this->getConcatFunction('do.NAME', 'do.ID') . " FROM b_disk_object do, ( SELECT NAME, MIN(ID) ID, COUNT(*) C FROM b_disk_object WHERE STORAGE_ID = {$storageId} AND PARENT_ID IS NULL AND ID <> {$rootObjectId} GROUP BY NAME HAVING COUNT(*)>1 ) dbl WHERE do.STORAGE_ID = {$storageId} AND do.PARENT_ID IS NULL AND do.ID <> {$rootObjectId} AND do.ID > dbl.ID AND do.NAME=dbl.NAME AND b_disk_object.ID = do.ID ) "; } $this->connection->queryExecute($sql); $this->connection->queryExecute(" UPDATE b_disk_object SET PARENT_ID = {$rootObjectId} WHERE STORAGE_ID = {$storageId} AND PARENT_ID IS NULL AND ID <> {$rootObjectId} "); $this->connection->queryExecute(" UPDATE b_disk_storage SET ROOT_OBJECT_ID = {$rootObjectId} WHERE ID = {$storageId} "); $this->moveCommonElements($storageId, $rootObjectId, $iblock); if($this->runWorkWithBizproc) { $classDocument = $this->sqlHelper->forSql(\Bitrix\Disk\BizProcDocumentCompatible::className()); if($this->isMssql || $this->isMysql) { $this->connection->queryExecute(" INSERT INTO b_bp_workflow_template (MODULE_ID, ENTITY, DOCUMENT_TYPE, AUTO_EXECUTE, NAME, DESCRIPTION, TEMPLATE, PARAMETERS, VARIABLES, MODIFIED, USER_ID, SYSTEM_CODE, ACTIVE) SELECT 'disk', '{$classDocument}', 'STORAGE_{$storageId}', AUTO_EXECUTE, NAME, DESCRIPTION, TEMPLATE, PARAMETERS, VARIABLES, MODIFIED, USER_ID, SYSTEM_CODE, ACTIVE FROM b_bp_workflow_template WHERE MODULE_ID = 'webdav' AND ENTITY = 'CIBlockDocumentWebdav' AND DOCUMENT_TYPE = 'iblock_{$iblock['ID']}' "); } elseif($this->isOracle) { $this->connection->queryExecute(" INSERT INTO b_bp_workflow_template (ID, MODULE_ID, ENTITY, DOCUMENT_TYPE, AUTO_EXECUTE, NAME, DESCRIPTION, TEMPLATE, PARAMETERS, VARIABLES, MODIFIED, USER_ID, SYSTEM_CODE, ACTIVE) SELECT SQ_B_BP_WORKFLOW_TEMPLATE.nextval, 'disk', '{$classDocument}', 'STORAGE_{$storageId}', AUTO_EXECUTE, NAME, DESCRIPTION, TEMPLATE, PARAMETERS, VARIABLES, MODIFIED, USER_ID, SYSTEM_CODE, ACTIVE FROM b_bp_workflow_template WHERE MODULE_ID = 'webdav' AND ENTITY = 'CIBlockDocumentWebdav' AND DOCUMENT_TYPE = 'iblock_{$iblock['ID']}' "); } } $this->log(array( __METHOD__, 'finish', $iblock['ID'], )); $this->storeIblockId($iblock['ID']); } $this->storeIblockId(0); $this->setStepFinished(__METHOD__); } protected function moveStructureCommonStorages() { if($this->isStepFinished(__METHOD__)) { return array(0, 0); } $storageIdToIblock = array(); $lastId = $this->getLastIblockId(); foreach($this->getIblockIdsWithCommonFiles() as $iblock) { if($lastId > $iblock['ID']) { continue; } $this->abortIfNeeded(); $this->log(array( __METHOD__, 'start', $iblock['ID'], )); $iblockId = (int)$iblock['ID']; $sqlHelper = $this->connection->getSqlHelper(); $name = $sqlHelper->forSql($iblock['NAME']); $siteId = $sqlHelper->forSql($iblock['LID']); $proxyType = $sqlHelper->forSql(ProxyType\Common::className()); $entityId = $sqlHelper->forSql($iblock['CODE'] == 'shared_files' ? 'shared_files_s1' : ($iblock['CODE']?:$iblock['ID'])); if(empty($entityId)) { $entityId = 'iblock' . $iblockId; } $potentialNonUnique = $this->connection->query("SELECT ID FROM b_disk_storage WHERE ENTITY_TYPE='{$proxyType}' AND ENTITY_ID='{$entityId}'")->fetch(); if($potentialNonUnique) { $entityId = $entityId . $iblockId; } $miscData = $sqlHelper->forSql(serialize(array( 'BASE_URL' => $iblock['LIST_PAGE_URL'], 'BIZPROC_ENABLED' => $iblock['BIZPROC'] == 'Y', ))); $this->connection->queryExecute(" INSERT INTO b_disk_storage (NAME, MODULE_ID, ENTITY_TYPE, ENTITY_ID, ENTITY_MISC_DATA, ROOT_OBJECT_ID, USE_INTERNAL_RIGHTS, SITE_ID, XML_ID) VALUES ('{$name}', 'disk', '{$proxyType}', '{$entityId}', '$miscData', null, 1, '{$siteId}', '{$iblockId}') "); $storageId = null; if($this->isMysql || $this->isMssql) { $storageId = (int)$this->connection->getInsertedId(); } elseif($this->isOracle) { $storageId = $this->connection->queryScalar('SELECT MAX(ID) MAX FROM b_disk_storage'); } if(!$storageId) { $this->log(array( __METHOD__, 'Error. Could not insert storage', " INSERT INTO b_disk_storage (NAME, MODULE_ID, ENTITY_TYPE, ENTITY_ID, ENTITY_MISC_DATA, ROOT_OBJECT_ID, USE_INTERNAL_RIGHTS, SITE_ID, XML_ID) VALUES ('{$name}', 'disk', '{$proxyType}', '{$entityId}', '$miscData', null, 1, '{$siteId}', '{$iblockId}') ", array( "('{$name}', 'disk', '{$proxyType}', '{$entityId}', '$miscData', null, 1, '{$siteId}', '{$iblockId}')", ) )); $this->storeIblockId($iblock['ID']); continue; } $storageIdToIblock[$storageId] = $iblock; //I know: child.IBLOCK_SECTION_ID can be NULL. But it is possible - unique key (NAME, PARENT_ID) if($this->isMysql) { $sql = " INSERT IGNORE INTO b_disk_object (ID, REAL_OBJECT_ID, NAME, TYPE, CODE, STORAGE_ID, PARENT_ID, CREATE_TIME, UPDATE_TIME, SYNC_UPDATE_TIME, CREATED_BY, UPDATED_BY, XML_ID, WEBDAV_SECTION_ID, WEBDAV_IBLOCK_ID) SELECT child.ID, child.ID, child.NAME, 2, child.CODE, {$storageId}, child.IBLOCK_SECTION_ID, child.DATE_CREATE, " . $this->sqlHelper->getIsNullFunction('child.TIMESTAMP_X', 'child.DATE_CREATE') . ", " . $this->sqlHelper->getIsNullFunction('child.TIMESTAMP_X', 'child.DATE_CREATE') . ", " . $this->sqlHelper->getIsNullFunction('child.CREATED_BY', 0) . ", child.MODIFIED_BY, child.ID, child.ID, child.IBLOCK_ID FROM b_iblock_section child WHERE child.IBLOCK_ID = {$iblockId} "; } elseif($this->isOracle || $this->isMssql) { $sql = " INSERT INTO b_disk_object (ID, REAL_OBJECT_ID, NAME, TYPE, CODE, STORAGE_ID, PARENT_ID, CREATE_TIME, UPDATE_TIME, SYNC_UPDATE_TIME, CREATED_BY, UPDATED_BY, XML_ID, WEBDAV_SECTION_ID, WEBDAV_IBLOCK_ID) SELECT child.ID, child.ID, child.NAME, 2, child.CODE, {$storageId}, child.IBLOCK_SECTION_ID, child.DATE_CREATE, " . $this->sqlHelper->getIsNullFunction('child.TIMESTAMP_X', 'child.DATE_CREATE') . ", " . $this->sqlHelper->getIsNullFunction('child.TIMESTAMP_X', 'child.DATE_CREATE') . ", " . $this->sqlHelper->getIsNullFunction('child.CREATED_BY', 0) . ", child.MODIFIED_BY, child.ID, child.ID, child.IBLOCK_ID FROM b_iblock_section child WHERE child.IBLOCK_ID = {$iblockId} AND NOT EXISTS(SELECT 'x' FROM b_disk_object WHERE NAME = child.NAME AND PARENT_ID = child.IBLOCK_SECTION_ID AND child.IBLOCK_SECTION_ID IS NOT NULL) "; } if($this->isMssql) { $this->connection->queryExecute('SET IDENTITY_INSERT b_disk_object ON'); } $this->connection->queryExecute($sql); $this->connection->queryExecute(" INSERT INTO b_disk_object (ID, REAL_OBJECT_ID, NAME, TYPE, CODE, STORAGE_ID, PARENT_ID, CREATE_TIME, UPDATE_TIME, SYNC_UPDATE_TIME, CREATED_BY, UPDATED_BY, XML_ID, WEBDAV_SECTION_ID, WEBDAV_IBLOCK_ID) SELECT child.ID, child.ID, " . $this->getConcatFunction('child.NAME', 'child.ID') . ", 2, child.CODE, {$storageId}, child.IBLOCK_SECTION_ID, child.DATE_CREATE, " . $this->sqlHelper->getIsNullFunction('child.TIMESTAMP_X', 'child.DATE_CREATE') . ", " . $this->sqlHelper->getIsNullFunction('child.TIMESTAMP_X', 'child.DATE_CREATE') . ", " . $this->sqlHelper->getIsNullFunction('child.CREATED_BY', 0) . ", child.MODIFIED_BY, child.ID, child.ID, child.IBLOCK_ID FROM b_iblock_section child WHERE child.IBLOCK_ID = {$iblockId} AND NOT EXISTS(SELECT 'x' FROM b_disk_object do WHERE do.ID=child.ID) "); if($this->isMssql) { $this->connection->queryExecute('SET IDENTITY_INSERT b_disk_object OFF'); } $this->log(array( __METHOD__, 'finish', $iblock['ID'], )); $this->storeIblockId($iblock['ID']); } unset($iblock); $this->storeIblockId(0); $this->setStepFinished(__METHOD__); } protected function storeConvertedExtLinkCreationDate($creationDate) { COption::SetOptionString( 'disk', '~migrateExtLinkCD', $creationDate ); } protected function getLastConvertedExtLinkCreationDate() { return COption::getOptionString( 'disk', '~migrateExtLinkCD', 0 ); } protected function convertBadNames() { if($this->isStepFinished(__METHOD__)) { return array(0, 0); } $sqlHelper = $this->connection->getSqlHelper(); if($this->isMysql) { $sql = " SELECT NAME, ID FROM b_disk_object WHERE NAME REGEXP CONCAT('[', x'01', '-', x'1F', '" . $sqlHelper->forSql(Bitrix\Main\IO\Path::INVALID_FILENAME_CHARS) . "]') "; } elseif($this->isOracle) { $sql = " SELECT NAME, ID FROM b_disk_object WHERE REGEXP_LIKE(NAME, '[" . $sqlHelper->forSql(Bitrix\Main\IO\Path::INVALID_FILENAME_CHARS) . "]') "; } elseif($this->isMssql) { $sql = " SELECT NAME, ID FROM b_disk_object WHERE PATINDEX('%[" . $sqlHelper->forSql(Bitrix\Main\IO\Path::INVALID_FILENAME_CHARS) . "]%', NAME) != 0 "; } $query = $this->connection->query($sql); while($query && $row = $query->fetch()) { try { $this->connection->queryExecute("UPDATE b_disk_object SET NAME='".$sqlHelper->forSql(\Bitrix\Disk\Ui\Text::correctFilename($row['NAME']))."' WHERE ID=".$row['ID']); } catch(Exception $e) { $this->connection->queryExecute("UPDATE b_disk_object SET NAME='".$sqlHelper->forSql(Bitrix\Main\IO\Path::randomizeInvalidFilename($row['NAME']))."' WHERE ID=".$row['ID']); } } $this->setStepFinished(__METHOD__); } protected function setRealObjectId() { if($this->isStepFinished(__METHOD__)) { return; } $this->connection->queryExecute(" UPDATE b_disk_object SET REAL_OBJECT_ID = ID WHERE REAL_OBJECT_ID IS NULL "); $this->setStepFinished(__METHOD__); } protected function migrateExternalLinks() { $this->abortIfNeeded(); if($this->isStepFinished(__METHOD__)) { return array(0, 0); } $successCount = $failedCount = 0; $this->log(array( 'Start migrate external links', )); $lastCreationDate = $this->getLastConvertedExtLinkCreationDate(); $connection = Application::getInstance()->getConnection(); $query = $connection->query(" SELECT * from b_webdav_ext_links ext WHERE ext.LINK_TYPE = 'M' AND ext.RESOURCE_TYPE = 'IBLOCK' AND ext.CREATION_DATE > {$lastCreationDate} AND (ext.ELEMENT_ID IS NULL OR ext.ELEMENT_ID = 0) ORDER BY ext.CREATION_DATE "); while($query && $extLinkRow = $query->fetch()) { $this->abortIfNeeded(); $extLinkData = $this->prepareDataFromOldExtLink($extLinkRow); if(empty($extLinkRow['ROOT_SECTION_ID']) && !empty($extLinkRow['URL'])) { $this->log(array( 'Migrate simple ext.link from common storage (without symbolic link)' )); $success = true; $pathItems = explode('/', ltrim($extLinkRow['URL'], '/')); $nameOfElement = array_pop($pathItems); $prevSectionId = 0; $prevIblockId = $extLinkRow['IBLOCK_ID']; foreach($pathItems as $path) { $pathFilter = array( '=NAME' => $path, 'IBLOCK_ID' => $prevIblockId, 'SECTION_ID' => $prevSectionId, ); $section = CIBlockSection::getList(array(), $pathFilter, false, array('ID', 'IBLOCK_ID',))->fetch(); if(!$section) { $success = false; break; } $prevSectionId = $section['ID']; $prevIblockId = $section['IBLOCK_ID']; } unset($path); if(!$success) { $this->log(array( 'Could not migrate ext.link (resolve path)', $extLinkRow, )); $this->storeConvertedExtLinkCreationDate($extLinkRow['CREATION_DATE']); continue; } $targetElement = CIBlockElement::getList(array(), array( '=NAME' => $nameOfElement, 'IBLOCK_ID' => $prevIblockId, 'SECTION_ID' => $prevSectionId ), false, false, array('ID',))->fetch(); if(!$targetElement || empty($targetElement['ID'])) { $this->log(array( 'Could not migrate ext.link (find iblockElement)', $extLinkRow, )); $this->storeConvertedExtLinkCreationDate($extLinkRow['CREATION_DATE']); continue; } $targetElement['ID'] = (int)$targetElement['ID']; $result = $this->connection->query("SELECT ID FROM b_disk_object WHERE WEBDAV_ELEMENT_ID = {$targetElement['ID']}")->fetch(); if(!$result || empty($result['ID'])) { $this->log(array( 'Could not migrate ext.link (find b_disk_object)', $extLinkRow, )); $this->storeConvertedExtLinkCreationDate($extLinkRow['CREATION_DATE']); continue; } $extLinkData['OBJECT_ID'] = $result['ID']; } elseif(!empty($extLinkRow['ROOT_SECTION_ID']) && !empty($extLinkRow['URL'])) { $this->log(array( 'Migrate ext.link from user storage (may contains symbolic link)' )); $success = true; $pathItems = explode('/', ltrim($extLinkRow['URL'], '/')); $nameOfElement = array_pop($pathItems); $prevSectionId = $extLinkRow['ROOT_SECTION_ID']; $prevIblockId = $extLinkRow['IBLOCK_ID']; foreach($pathItems as $path) { $pathFilter = array( '=NAME' => $path, 'IBLOCK_ID' => $prevIblockId, 'SECTION_ID' => $prevSectionId, ); $section = CIBlockSection::getList(array(), $pathFilter, false, array('ID', 'IBLOCK_ID', 'UF_LINK_IBLOCK_ID', 'UF_LINK_SECTION_ID'))->fetch(); if(!$section) { $success = false; break; } $prevSectionId = empty($section['UF_LINK_SECTION_ID'])? $section['ID'] : $section['UF_LINK_SECTION_ID']; $prevIblockId = empty($section['UF_LINK_IBLOCK_ID'])? $section['IBLOCK_ID'] : $section['UF_LINK_IBLOCK_ID']; } unset($path); if(!$success) { $this->log(array( 'Could not migrate ext.link (resolve symbolic path)', $extLinkRow, )); $this->storeConvertedExtLinkCreationDate($extLinkRow['CREATION_DATE']); continue; } $targetElement = CIBlockElement::getList(array(), array( '=NAME' => $nameOfElement, 'IBLOCK_ID' => $prevIblockId, 'SECTION_ID' => $prevSectionId ), false, false, array('ID',))->fetch(); if(!$targetElement || empty($targetElement['ID'])) { $this->log(array( 'Could not migrate ext.link (find iblockElement)', $extLinkRow, )); $this->storeConvertedExtLinkCreationDate($extLinkRow['CREATION_DATE']); continue; } $targetElement['ID'] = (int)$targetElement['ID']; $result = $this->connection->query("SELECT ID FROM b_disk_object WHERE WEBDAV_ELEMENT_ID = {$targetElement['ID']}")->fetch(); if(!$result || empty($result['ID'])) { $this->log(array( 'Could not migrate ext.link (find b_disk_object)', $extLinkRow, )); $this->storeConvertedExtLinkCreationDate($extLinkRow['CREATION_DATE']); continue; } $extLinkData['OBJECT_ID'] = $result['ID']; } $result = ExternalLinkTable::add($extLinkData); if(!$result->isSuccess()) { $this->log(array( 'Could not add new ext.link', $extLinkData, $result->getErrors(), )); $this->storeConvertedExtLinkCreationDate($extLinkRow['CREATION_DATE']); continue; } $this->log(array( 'Success attempt', $result->getId(), )); $this->storeConvertedExtLinkCreationDate($extLinkRow['CREATION_DATE']); } $this->setStepFinished(__METHOD__); $this->log(array( 'Finish migrate external links', )); return array($successCount, $failedCount); } protected function prepareDataFromOldExtLink(array $extLinkRow) { $extLinkData = array( 'OBJECT_ID' => !empty($extLinkRow['DISK_ID'])? $extLinkRow['DISK_ID'] : null, 'CREATED_BY' => $extLinkRow['USER_ID'], 'HASH' => substr($extLinkRow['HASH'], 0, 32), 'DESCRIPTION' => $extLinkRow['DESCRIPTION'], 'DOWNLOAD_COUNT' => $extLinkRow['DOWNLOAD_COUNT'], 'TYPE' => ExternalLinkTable::TYPE_MANUAL, 'CREATE_TIME' => DateTime::createFromTimestamp($extLinkRow['CREATION_DATE']), ); //157680000 = 5*365*24*60*60 if($extLinkRow['LIFETIME'] - time() < 157680000) { //limited life $extLinkData['DEATH_TIME'] = DateTime::createFromTimestamp($extLinkRow['LIFETIME']); } if(!empty($extLinkRow['PASSWORD']) && !empty($extLinkRow['SALT'])) { $extLinkData['PASSWORD'] = $extLinkRow['PASSWORD']; $extLinkData['SALT'] = $extLinkRow['SALT']; return $extLinkData; } return $extLinkData; } protected function upDbHelpers() { if(!$this->connection->getTableField('b_disk_object', 'WEBDAV_ELEMENT_ID')) { $this->connection->queryExecute("ALTER TABLE b_disk_object ADD WEBDAV_ELEMENT_ID INT"); } if(!$this->connection->getTableField('b_disk_object', 'WEBDAV_SECTION_ID')) { $this->connection->queryExecute("ALTER TABLE b_disk_object ADD WEBDAV_SECTION_ID INT"); } if(!$this->connection->getTableField('b_disk_object', 'WEBDAV_IBLOCK_ID')) { $this->connection->queryExecute("ALTER TABLE b_disk_object ADD WEBDAV_IBLOCK_ID INT"); } if(!$this->connection->getTableField('b_disk_version', 'BP_VERSION_ID')) { $this->connection->queryExecute("ALTER TABLE b_disk_version ADD BP_VERSION_ID INT"); } try { $this->connection->createIndex('b_disk_storage', 'IX_TMP_DISK_S_1', 'ROOT_OBJECT_ID'); $this->connection->createIndex('b_disk_object', 'IX_TMP_DISK_E_2', 'WEBDAV_ELEMENT_ID'); $this->connection->createIndex('b_disk_object', 'IX_TMP_DISK_S_2', 'WEBDAV_SECTION_ID'); $this->connection->createIndex('b_disk_object', 'IX_TMP_DISK_IIS_2', 'WEBDAV_IBLOCK_ID'); } catch(Exception $e) { } } protected function downDbHelpers() { /* $this->connection->queryExecute("DROP INDEX IX_TMP_DISK_S_1 on b_disk_storage"); $this->connection->queryExecute("DROP INDEX IX_TMP_DISK_E_2 on b_disk_object"); $this->connection->queryExecute("DROP INDEX IX_TMP_DISK_S_2 on b_disk_object"); $this->connection->queryExecute("DROP INDEX IX_TMP_DISK_IIS_2 on b_disk_object"); $this->connection->queryExecute("ALTER TABLE b_disk_object DROP COLUMN WEBDAV_ELEMENT_ID"); $this->connection->queryExecute("ALTER TABLE b_disk_object DROP COLUMN WEBDAV_IBLOCK_ID"); $this->connection->queryExecute("ALTER TABLE b_disk_object DROP COLUMN WEBDAV_SECTION_ID"); $this->connection->queryExecute("ALTER TABLE b_disk_version DROP COLUMN BP_VERSION_ID"); */ } private function detectMigrationAfterDeletingModule() { $hasOption = $this->connection->query("SELECT * FROM b_option WHERE MODULE_ID='disk'")->fetch(); $hasObject = $this->connection->query("SELECT * FROM b_disk_object")->fetch(); return !$hasOption && $hasObject; } public function run() { if($this->isStepFinished(__METHOD__)) { return self::STATUS_FINISH; } define('DISK_MIGRATE_MODE', true); $this->checkRequired(); if(\Bitrix\Disk\Configuration::isSuccessfullyConverted()) { return self::STATUS_FINISH; } if(!Option::get('disk', 'process_converted', false)) { try { $this->downDbHelpers(); } catch(Exception $e){} $this->upDbHelpers(); if($this->detectMigrationAfterDeletingModule()) { $this->processFinallyActions(); return self::STATUS_FINISH; } $this->registerHandlerToBlockIblock(); Option::set( 'disk', 'successfully_converted', false ); Option::set( 'disk', 'process_converted', 'Y' ); Option::set( 'webdav', 'successfully_converted', false ); Option::set( 'webdav', 'process_converted', 'Y' ); } $this->runResorting(); $this->migrateOptions(); $this->abortIfNeeded(); $this->moveUsers(); $this->abortIfNeeded(); $this->moveGroup(); $this->abortIfNeeded(); $this->moveSections(); $this->abortIfNeeded(); $this->moveNonUniqueSections(); $this->abortIfNeeded(); $this->moveStructureCommonStorages(); $this->abortIfNeeded(); $this->migrateDataCommonStorages(); $this->abortIfNeeded(); $this->moveSpecificXml(); $this->abortIfNeeded(); $this->moveElements(); $this->abortIfNeeded(); $this->setSymbolicLinks(); $this->abortIfNeeded(); $this->moveExternalLinks(); $this->abortIfNeeded(); $this->moveSharings(); $this->abortIfNeeded(); $this->migrateExternalLinks(); $this->abortIfNeeded(); self::RUN_STEPS_WITH_MODIFY_DATA && $this->moveWebdavElement(); $this->abortIfNeeded(); self::RUN_STEPS_WITH_MODIFY_DATA && $this->migrateWebdavElementInSocnet(); $this->abortIfNeeded(); $this->fillSelfObjectPath(); $this->abortIfNeeded(); $this->fillObjectPath(); $this->abortIfNeeded(); $this->migrateMetaFolders(); $this->abortIfNeeded(); //head self::RUN_STEPS_WITH_MODIFY_DATA && $this->migrateUfHead(); $this->abortIfNeeded(); $this->migrateTrashFiles(); $this->abortIfNeeded(); $this->migrateTrashFolders(); $this->abortIfNeeded(); $this->deleteTrashFolders(); $this->abortIfNeeded(); $this->fillObjectRights(); $this->abortIfNeeded(); $this->deletePairNegativeRights(); $this->abortIfNeeded(); !$this->publishDocs && $this->recalcRightsOnUnPublishObject(); $this->abortIfNeeded(); $this->migrateVersion(); $this->abortIfNeeded(); $this->migrateHeadVersion(); $this->abortIfNeeded(); $this->convertBadNames(); $this->setRealObjectId(); $this->abortIfNeeded(); $this->generateEmptyUserStorages(); $this->abortIfNeeded(); $this->markPendingObjectAsDeleted(); $this->abortIfNeeded(); $this->repairStorageId(); $this->abortIfNeeded(); self::RUN_STEPS_WITH_MODIFY_DATA && $this->migrateWebdavElementHistory(); $this->abortIfNeeded(); self::RUN_STEPS_WITH_MODIFY_DATA && $this->migrateCrmData(); $this->abortIfNeeded(); self::RUN_STEPS_WITH_MODIFY_DATA && $this->migrateSearchData(); $this->abortIfNeeded(); self::RUN_STEPS_WITH_MODIFY_DATA && $this->disableIndexIblocks(); $this->abortIfNeeded(); $this->addMissedGroupStorages(); $this->downDbHelpers(); //patch links in public files if (!ModuleManager::isModuleInstalled('bitrix24')) { $extranetSiteId = (ModuleManager::isModuleInstalled("extranet") ? Option::get("extranet", "extranet_site") : false); $rsSite = SiteTable::getList(); while ($arSite = $rsSite->Fetch()) { $folder = "company"; if ( $extranetSiteId && $arSite["LID"] == $extranetSiteId ) $folder = "contacts"; $siteDocRoot = (strlen($arSite["DOC_ROOT"]) > 0 ? $arSite["DOC_ROOT"] : $_SERVER["DOCUMENT_ROOT"]); $siteDir = (strlen($arSite["DIR"]) > 0 ? $arSite["DIR"] : "/"); $filePath = $siteDocRoot.$siteDir.'.left.menu_ext.php'; $fp = null; if(file_exists($filePath)) { $fp = fopen($filePath, 'r'); } if ( $fp !== false && $fp !== null ) { $fileContents = fread($fp, filesize($filePath)); fclose($fp); preg_match('/'.$folder.'\/personal\/user\/\"\.\$USER_ID\.\"\/files\/lib\//si', $fileContents, $matches); if (!empty($matches[0])) { $fileContentsNew = str_replace( $folder.'/personal/user/".$USER_ID."/files/lib/', $folder.'/personal/user/".$USER_ID."/disk/path/', $fileContents ); if ($fileContentsNew != $fileContents) { $fp = fopen($filePath, 'w'); fwrite($fp, $fileContentsNew); fclose($fp); } } } } //clean cached inline img (for resize with signature) $cache = new CPHPCache; $cache->CleanDir("/blog/comment"); $cache->CleanDir("/blog/socnet_post"); $cache->CleanDir("/sonet/log"); if(defined("BX_COMP_MANAGED_CACHE")) { global $CACHE_MANAGER; $CACHE_MANAGER->CleanDir("b_user_field"); } } if(defined("BX_COMP_MANAGED_CACHE")) { //clean left menu. global $CACHE_MANAGER; $CACHE_MANAGER->clearByTag('sonet_group'); } $this->processFinallyActions(); $this->setStepFinished(__METHOD__); return self::STATUS_FINISH; } protected function generateEmptyUserStorages() { if($this->isStepFinished(__METHOD__)) { return; } $proxyType = $this->sqlHelper->forSql(ProxyType\User::className()); $result = $this->connection->query(" SELECT u.ID FROM b_user u WHERE NOT EXISTS(SELECT 'x' FROM b_disk_storage s WHERE u.ID=s.ENTITY_ID AND s.ENTITY_TYPE='{$proxyType}') "); while($user = $result->fetch()) { Driver::getInstance()->addUserStorage($user['ID']); } // /* if($this->getIblockWithUserFiles() as $iblock) { INSERT INTO b_disk_storage() SELECT ID, FROM b_user WHERE NOT EXISTS(SELECT 'x' FROM b_disk_storage WHERE u.ID=st.ENTITY_ID) INSERT INTO b_disk_object() SELECT FROM b_disk_storage WHERE INSERT INTO b_disk_path() SELECT FROM INSERT INTO b_disk_right() SELECT FROM INSERT INTO b_disk_simple_right() SELECT FROM } */ $this->setStepFinished(__METHOD__); } protected function fillObjectPath() { if($this->isStepFinished(__METHOD__)) { return; } $maxInnerJoinDepth = 32; $currentDepth = $this->getStorageId(); $emptyInsert = false; while($currentDepth < $maxInnerJoinDepth && !$emptyInsert) { $this->abortIfNeeded(); $query = " INSERT INTO b_disk_object_path (OBJECT_ID, PARENT_ID, DEPTH_LEVEL) SELECT b.ID, t.ID, " . ($currentDepth+1) . " FROM b_disk_object t "; $finalQuery = $query; for($i = 0;$i < $currentDepth;$i++) { $finalQuery .= " INNER JOIN b_disk_object t" . ($i+1) . " ON t" . ($i?: '') . ".ID=t" . ($i+1) . ".PARENT_ID "; } $lastJoin = " INNER JOIN b_disk_object b ON t" . ($currentDepth?:'' ) . ".ID=b.PARENT_ID "; $finalQuery = $finalQuery .$lastJoin; $this->connection->queryExecute($finalQuery); $emptyInsert = $this->connection->getAffectedRowsCount() <= 0; $currentDepth++; $this->storeStorageId($currentDepth); } //reset. Will be in future. Coming soon. $this->storeStorageId(0); $this->storeFillPathParentId(0); $this->setStepFinished(__METHOD__); } protected function moveSpecificXml() { if($this->isStepFinished(__METHOD__)) { return; } $type = $this->sqlHelper->forSql(ProxyType\Common::className()); if($this->isMysql) { $sql = " UPDATE b_disk_object obj INNER JOIN b_iblock_section sec ON sec.ID = obj.WEBDAV_ELEMENT_ID INNER JOIN b_disk_storage st ON st.ID = obj.STORAGE_ID SET obj.XML_ID = sec.XML_ID, obj.CODE = sec.XML_ID WHERE st.MODULE_ID = 'disk' AND st.ENTITY_TYPE = '{$type}' AND sec.XML_ID in ('CRM_CALL_RECORDS', 'CRM_EMAIL_ATTACHMENTS', 'VI_CALLS') "; } elseif($this->isOracle || $this->isMssql) { $sql = " UPDATE b_disk_object SET XML_ID = (SELECT sec.XML_ID FROM b_disk_object obj INNER JOIN b_iblock_section sec ON sec.ID = obj.WEBDAV_ELEMENT_ID INNER JOIN b_disk_storage st ON st.ID = obj.STORAGE_ID WHERE st.MODULE_ID = 'disk' AND st.ENTITY_TYPE = '{$type}' AND sec.XML_ID in ('CRM_CALL_RECORDS', 'CRM_EMAIL_ATTACHMENTS', 'VI_CALLS') AND b_disk_object.ID = obj.ID ), CODE = (SELECT sec.XML_ID FROM b_disk_object obj INNER JOIN b_iblock_section sec ON sec.ID = obj.WEBDAV_ELEMENT_ID INNER JOIN b_disk_storage st ON st.ID = obj.STORAGE_ID WHERE st.MODULE_ID = 'disk' AND st.ENTITY_TYPE = '{$type}' AND sec.XML_ID in ('CRM_CALL_RECORDS', 'CRM_EMAIL_ATTACHMENTS', 'VI_CALLS') AND b_disk_object.ID = obj.ID ) WHERE EXISTS (SELECT sec.XML_ID FROM b_disk_object obj INNER JOIN b_iblock_section sec ON sec.ID = obj.WEBDAV_ELEMENT_ID INNER JOIN b_disk_storage st ON st.ID = obj.STORAGE_ID WHERE st.MODULE_ID = 'disk' AND st.ENTITY_TYPE = '{$type}' AND sec.XML_ID in ('CRM_CALL_RECORDS', 'CRM_EMAIL_ATTACHMENTS', 'VI_CALLS') AND b_disk_object.ID = obj.ID ) "; } $this->connection->queryExecute($sql); $this->setStepFinished(__METHOD__); } protected function migrateCrmData() { if($this->isStepFinished(__METHOD__)) { return; } //CCrmActivityStorageType::Webdav 2 //CCrmActivityStorageType::Disk 3 if(!$this->connection->isTableExists('b_crm_act')) { $this->setStepFinished(__METHOD__); return; } if($this->isMysql) { $sql = " UPDATE b_crm_act_elem crm INNER JOIN b_disk_object obj ON obj.WEBDAV_ELEMENT_ID = crm.ELEMENT_ID and crm.STORAGE_TYPE_ID = 2 SET crm.ELEMENT_ID = obj.ID, crm.STORAGE_TYPE_ID = 3 "; } elseif($this->isOracle || $this->isMssql) { $sql = " UPDATE b_crm_act_elem SET STORAGE_TYPE_ID = 3, ELEMENT_ID = (SELECT obj.ID FROM b_crm_act_elem crm INNER JOIN b_disk_object obj ON obj.WEBDAV_ELEMENT_ID = crm.ELEMENT_ID and crm.STORAGE_TYPE_ID = 2 WHERE b_crm_act_elem.ACTIVITY_ID = crm.ACTIVITY_ID AND b_crm_act_elem.STORAGE_TYPE_ID = crm.STORAGE_TYPE_ID AND b_crm_act_elem.ELEMENT_ID = crm.ELEMENT_ID ) WHERE EXISTS (SELECT obj.ID FROM b_crm_act_elem crm INNER JOIN b_disk_object obj ON obj.WEBDAV_ELEMENT_ID = crm.ELEMENT_ID and crm.STORAGE_TYPE_ID = 2 WHERE b_crm_act_elem.ACTIVITY_ID = crm.ACTIVITY_ID AND b_crm_act_elem.STORAGE_TYPE_ID = crm.STORAGE_TYPE_ID AND b_crm_act_elem.ELEMENT_ID = crm.ELEMENT_ID ) "; } $this->connection->queryExecute($sql); if($this->isMssql) { $this->connection->queryExecute(" UPDATE b_crm_act SET STORAGE_ELEMENT_IDS = CAST(ID as VARCHAR(255)), STORAGE_TYPE_ID = 3 WHERE STORAGE_TYPE_ID = 2 "); } else { $this->connection->queryExecute(" UPDATE b_crm_act SET STORAGE_ELEMENT_IDS = ID, STORAGE_TYPE_ID = 3 WHERE STORAGE_TYPE_ID = 2 "); } if($this->isMysql) { $sql = " UPDATE b_crm_quote_elem crm INNER JOIN b_disk_object obj ON obj.WEBDAV_ELEMENT_ID = crm.ELEMENT_ID and crm.STORAGE_TYPE_ID = 2 SET crm.ELEMENT_ID = obj.ID, crm.STORAGE_TYPE_ID = 3 "; } elseif($this->isOracle || $this->isMssql) { $sql = " UPDATE b_crm_quote_elem SET STORAGE_TYPE_ID = 3, ELEMENT_ID = (SELECT obj.ID FROM b_crm_quote_elem crm INNER JOIN b_disk_object obj ON obj.WEBDAV_ELEMENT_ID = crm.ELEMENT_ID and crm.STORAGE_TYPE_ID = 2 WHERE b_crm_quote_elem.QUOTE_ID = crm.QUOTE_ID AND b_crm_quote_elem.STORAGE_TYPE_ID = crm.STORAGE_TYPE_ID AND b_crm_quote_elem.ELEMENT_ID = crm.ELEMENT_ID ) WHERE EXISTS (SELECT obj.ID FROM b_crm_quote_elem crm INNER JOIN b_disk_object obj ON obj.WEBDAV_ELEMENT_ID = crm.ELEMENT_ID and crm.STORAGE_TYPE_ID = 2 WHERE b_crm_quote_elem.QUOTE_ID = crm.QUOTE_ID AND b_crm_quote_elem.STORAGE_TYPE_ID = crm.STORAGE_TYPE_ID AND b_crm_quote_elem.ELEMENT_ID = crm.ELEMENT_ID ) "; } $this->connection->queryExecute($sql); if($this->isMssql) { $this->connection->queryExecute(" UPDATE b_crm_quote SET STORAGE_ELEMENT_IDS = CAST(ID as VARCHAR(255)), STORAGE_TYPE_ID = 3 WHERE STORAGE_TYPE_ID = 2 "); } else { $this->connection->queryExecute(" UPDATE b_crm_quote SET STORAGE_ELEMENT_IDS = ID, STORAGE_TYPE_ID = 3 WHERE STORAGE_TYPE_ID = 2 "); } $this->setStepFinished(__METHOD__); } protected function migrateSearchData() { if($this->isStepFinished(__METHOD__)) { return; } global $DB; $newScheme = $DB->Query('SELECT ENTITY_TYPE_ID FROM b_search_content WHERE 1=0', true); if($newScheme) { $this->migrateSearchDataNewScheme(); } else { $this->migrateSearchDataOldScheme(); } $this->setStepFinished(__METHOD__); } private function migrateSearchDataOldScheme() { $this->connection->queryExecute(" UPDATE b_search_content_site SET URL = '' WHERE SEARCH_CONTENT_ID IN (SELECT c.ID FROM b_search_content c INNER JOIN b_disk_object d ON c.ITEM_ID = d.WEBDAV_ELEMENT_ID WHERE c.PARAM1 = 'library') "); $this->connection->queryExecute(" DELETE FROM b_search_content_param WHERE SEARCH_CONTENT_ID IN (SELECT c.ID FROM b_search_content c INNER JOIN b_disk_object d ON c.ITEM_ID = d.WEBDAV_ELEMENT_ID WHERE c.PARAM1 = 'library') "); /* SELECT c.ID as SEARCH_CONTENT_ID, d.ID, d.STORAGE_ID, d.PARENT_ID FROM b_search_content c INNER JOIN b_disk_object d ON c.ITEM_ID = d.WEBDAV_ELEMENT_ID WHERE c.PARAM1 = 'library' AND c.MODULE_ID='iblock' AND ENTITY_TYPE_ID='IBLOCK_ELEMENT' */ if($this->isMysql) { $sql = " UPDATE IGNORE b_search_content c INNER JOIN b_disk_object d ON c.ITEM_ID = d.WEBDAV_ELEMENT_ID SET c.MODULE_ID = 'disk', c.ITEM_ID = " . $this->getConcatFunction("'FILE_'", 'd.ID') . ", c.URL = " . $this->getConcatFunction("'=ID='", 'd.ID') . ", c.PARAM1 = d.STORAGE_ID, c.PARAM2 = d.PARENT_ID WHERE c.PARAM1 = 'library' "; } elseif($this->isOracle) { $sql = " UPDATE b_search_content c SET c.MODULE_ID = 'disk', c.ITEM_ID = (SELECT " . $this->getConcatFunction("'FILE_'", 'd.ID') . " FROM b_search_content cc INNER JOIN b_disk_object d ON cc.ITEM_ID = TO_CHAR(d.WEBDAV_ELEMENT_ID) WHERE cc.ID = c.ID AND c.PARAM1 = 'library'), c.URL = (SELECT " . $this->getConcatFunction("'=ID='", 'd.ID') . " FROM b_search_content cc INNER JOIN b_disk_object d ON cc.ITEM_ID = TO_CHAR(d.WEBDAV_ELEMENT_ID) WHERE cc.ID = c.ID AND c.PARAM1 = 'library'), c.PARAM1 = (SELECT d.STORAGE_ID FROM b_search_content cc INNER JOIN b_disk_object d ON cc.ITEM_ID = TO_CHAR(d.WEBDAV_ELEMENT_ID) WHERE cc.ID = c.ID AND c.PARAM1 = 'library'), c.PARAM2 = (SELECT d.PARENT_ID FROM b_search_content cc INNER JOIN b_disk_object d ON cc.ITEM_ID = TO_CHAR(d.WEBDAV_ELEMENT_ID) WHERE cc.ID = c.ID AND c.PARAM1 = 'library') WHERE c.PARAM1 = 'library' AND EXISTS (SELECT d.PARENT_ID FROM b_search_content cc INNER JOIN b_disk_object d ON cc.ITEM_ID = TO_CHAR(d.WEBDAV_ELEMENT_ID) WHERE cc.ID = c.ID AND c.PARAM1 = 'library') "; } elseif($this->isMssql) { $sql = " UPDATE b_search_content SET MODULE_ID = 'disk', ITEM_ID = (SELECT " . $this->getConcatFunction("'FILE_'", 'd.ID') . " FROM b_search_content cc INNER JOIN b_disk_object d ON cc.ITEM_ID = CAST(d.WEBDAV_ELEMENT_ID as VARCHAR(255)) WHERE cc.ID = b_search_content.ID AND b_search_content.PARAM1 = 'library'), URL = (SELECT " . $this->getConcatFunction("'=ID='", 'd.ID') . " FROM b_search_content cc INNER JOIN b_disk_object d ON cc.ITEM_ID = CAST(d.WEBDAV_ELEMENT_ID as VARCHAR(255)) WHERE cc.ID = b_search_content.ID AND b_search_content.PARAM1 = 'library'), PARAM1 = (SELECT d.STORAGE_ID FROM b_search_content cc INNER JOIN b_disk_object d ON cc.ITEM_ID = CAST(d.WEBDAV_ELEMENT_ID as VARCHAR(255)) WHERE cc.ID = b_search_content.ID AND b_search_content.PARAM1 = 'library'), PARAM2 = (SELECT d.PARENT_ID FROM b_search_content cc INNER JOIN b_disk_object d ON cc.ITEM_ID = CAST(d.WEBDAV_ELEMENT_ID as VARCHAR(255)) WHERE cc.ID = b_search_content.ID AND b_search_content.PARAM1 = 'library') WHERE PARAM1 = 'library' AND EXISTS (SELECT d.PARENT_ID FROM b_search_content cc INNER JOIN b_disk_object d ON cc.ITEM_ID = CAST(d.WEBDAV_ELEMENT_ID as VARCHAR(255)) WHERE cc.ID = b_search_content.ID AND b_search_content.PARAM1 = 'library') "; } $this->connection->queryExecute($sql); } private function migrateSearchDataNewScheme() { $this->connection->queryExecute(" UPDATE b_search_content_site SET URL = '' WHERE SEARCH_CONTENT_ID IN (SELECT c.ID FROM b_search_content c INNER JOIN b_disk_object d ON c.ITEM_ID = d.WEBDAV_ELEMENT_ID WHERE c.PARAM1 = 'library' AND c.ENTITY_TYPE_ID='IBLOCK_ELEMENT') "); $this->connection->queryExecute(" DELETE FROM b_search_content_param WHERE SEARCH_CONTENT_ID IN (SELECT c.ID FROM b_search_content c INNER JOIN b_disk_object d ON c.ITEM_ID = d.WEBDAV_ELEMENT_ID WHERE c.PARAM1 = 'library' AND c.ENTITY_TYPE_ID='IBLOCK_ELEMENT') "); /* SELECT c.ID as SEARCH_CONTENT_ID, d.ID, d.STORAGE_ID, d.PARENT_ID FROM b_search_content c INNER JOIN b_disk_object d ON c.ITEM_ID = d.WEBDAV_ELEMENT_ID WHERE c.PARAM1 = 'library' AND c.MODULE_ID='iblock' AND ENTITY_TYPE_ID='IBLOCK_ELEMENT' */ if($this->isMysql) { $sql = " UPDATE IGNORE b_search_content c INNER JOIN b_disk_object d ON c.ITEM_ID = d.WEBDAV_ELEMENT_ID SET c.MODULE_ID = 'disk', c.ITEM_ID = " . $this->getConcatFunction("'FILE_'", 'd.ID') . ", c.ENTITY_TYPE_ID = '', c.ENTITY_ID = '', c.URL = " . $this->getConcatFunction("'=ID='", 'd.ID') . ", c.PARAM1 = d.STORAGE_ID, c.PARAM2 = d.PARENT_ID WHERE c.PARAM1 = 'library' AND c.ENTITY_TYPE_ID='IBLOCK_ELEMENT' "; } elseif($this->isOracle) { $sql = " UPDATE b_search_content c SET c.MODULE_ID = 'disk', c.ITEM_ID = (SELECT " . $this->getConcatFunction("'FILE_'", 'd.ID') . " FROM b_search_content cc INNER JOIN b_disk_object d ON cc.ITEM_ID = TO_CHAR(d.WEBDAV_ELEMENT_ID) WHERE cc.ID = c.ID AND c.PARAM1 = 'library' AND c.ENTITY_TYPE_ID='IBLOCK_ELEMENT'), c.ENTITY_TYPE_ID = '', c.ENTITY_ID = '', c.URL = (SELECT " . $this->getConcatFunction("'=ID='", 'd.ID') . " FROM b_search_content cc INNER JOIN b_disk_object d ON cc.ITEM_ID = TO_CHAR(d.WEBDAV_ELEMENT_ID) WHERE cc.ID = c.ID AND c.PARAM1 = 'library' AND c.ENTITY_TYPE_ID='IBLOCK_ELEMENT'), c.PARAM1 = (SELECT d.STORAGE_ID FROM b_search_content cc INNER JOIN b_disk_object d ON cc.ITEM_ID = TO_CHAR(d.WEBDAV_ELEMENT_ID) WHERE cc.ID = c.ID AND c.PARAM1 = 'library' AND c.ENTITY_TYPE_ID='IBLOCK_ELEMENT'), c.PARAM2 = (SELECT d.PARENT_ID FROM b_search_content cc INNER JOIN b_disk_object d ON cc.ITEM_ID = TO_CHAR(d.WEBDAV_ELEMENT_ID) WHERE cc.ID = c.ID AND c.PARAM1 = 'library' AND c.ENTITY_TYPE_ID='IBLOCK_ELEMENT') WHERE c.PARAM1 = 'library' AND c.ENTITY_TYPE_ID='IBLOCK_ELEMENT' AND EXISTS (SELECT d.PARENT_ID FROM b_search_content cc INNER JOIN b_disk_object d ON cc.ITEM_ID = TO_CHAR(d.WEBDAV_ELEMENT_ID) WHERE cc.ID = c.ID AND c.PARAM1 = 'library' AND c.ENTITY_TYPE_ID='IBLOCK_ELEMENT') "; } elseif($this->isMssql) { $sql = " UPDATE b_search_content SET MODULE_ID = 'disk', ITEM_ID = (SELECT " . $this->getConcatFunction("'FILE_'", 'd.ID') . " FROM b_search_content cc INNER JOIN b_disk_object d ON cc.ITEM_ID = CAST(d.WEBDAV_ELEMENT_ID as VARCHAR(255)) WHERE cc.ID = b_search_content.ID AND b_search_content.PARAM1 = 'library' AND b_search_content.ENTITY_TYPE_ID='IBLOCK_ELEMENT'), ENTITY_TYPE_ID = '', ENTITY_ID = '', URL = (SELECT " . $this->getConcatFunction("'=ID='", 'd.ID') . " FROM b_search_content cc INNER JOIN b_disk_object d ON cc.ITEM_ID = CAST(d.WEBDAV_ELEMENT_ID as VARCHAR(255)) WHERE cc.ID = b_search_content.ID AND b_search_content.PARAM1 = 'library' AND b_search_content.ENTITY_TYPE_ID='IBLOCK_ELEMENT'), PARAM1 = (SELECT d.STORAGE_ID FROM b_search_content cc INNER JOIN b_disk_object d ON cc.ITEM_ID = CAST(d.WEBDAV_ELEMENT_ID as VARCHAR(255)) WHERE cc.ID = b_search_content.ID AND b_search_content.PARAM1 = 'library' AND b_search_content.ENTITY_TYPE_ID='IBLOCK_ELEMENT'), PARAM2 = (SELECT d.PARENT_ID FROM b_search_content cc INNER JOIN b_disk_object d ON cc.ITEM_ID = CAST(d.WEBDAV_ELEMENT_ID as VARCHAR(255)) WHERE cc.ID = b_search_content.ID AND b_search_content.PARAM1 = 'library' AND b_search_content.ENTITY_TYPE_ID='IBLOCK_ELEMENT') WHERE PARAM1 = 'library' AND ENTITY_TYPE_ID='IBLOCK_ELEMENT' AND EXISTS (SELECT d.PARENT_ID FROM b_search_content cc INNER JOIN b_disk_object d ON cc.ITEM_ID = CAST(d.WEBDAV_ELEMENT_ID as VARCHAR(255)) WHERE cc.ID = b_search_content.ID AND b_search_content.PARAM1 = 'library' AND b_search_content.ENTITY_TYPE_ID='IBLOCK_ELEMENT') "; } $this->connection->queryExecute($sql); } protected function disableIndexIblocks() { if($this->isStepFinished(__METHOD__)) { return; } $this->connection->queryExecute(" UPDATE b_iblock SET INDEX_ELEMENT = 'N', INDEX_SECTION = 'N' WHERE IBLOCK_TYPE_ID = 'library' "); $query = $this->connection->query(" SELECT ID FROM b_iblock WHERE IBLOCK_TYPE_ID = 'library' "); while($row = $query->fetch()) { if(!empty($row['ID'])) { CIBlock::CleanCache($row['ID']); } } $this->setStepFinished(__METHOD__); } protected function convertIblockTaskToDiskTask($taskId) { static $map = array(); if(isset($map[$taskId]) || array_key_exists($taskId, $map)) { return $map[$taskId]; } $iblockTask = $this->getIblockTaskById($taskId); if($iblockTask === null) { return self::COULD_NOT_FIND_IBLOCK_TASK; } switch($iblockTask['NAME']) { case 'iblock_read': case 'iblock_admin_read': return $this->getDiskTaskIdByName(RightsManager::TASK_READ); case 'iblock_limited_edit': case 'iblock_full_edit': return $this->getDiskTaskIdByName(RightsManager::TASK_EDIT); case 'iblock_admin_add': return $this->getDiskTaskIdByName(RightsManager::TASK_ADD); case 'iblock_full': return $this->getDiskTaskIdByName(RightsManager::TASK_FULL); } $iblockOperations = $this->getIblockOperationsByTask($taskId); if(empty($iblockOperations)) { $map[$taskId] = self::DENY_TASK; //deny task return $map[$taskId]; } $iblockOperationsMapped = array(); foreach($iblockOperations as $name) { $diskName = $this->mapRightOperation($name); if(is_array($diskName)) { foreach($diskName as $item) { $iblockOperationsMapped[$item] = $item; } unset($item); } elseif($diskName) { $iblockOperationsMapped[$diskName] = $diskName; } } unset($name); if(!$iblockOperationsMapped) { $this->log(array( "Could not map operations in task ({$taskId})", "Skip" )); return null; } $this->loadDiskTasks(); foreach($this->diskTasks as $diskTask) { $diskOperationsByTask = $this->getDiskOperationsByTask($diskTask['ID']); if(array_diff($iblockOperationsMapped, $diskOperationsByTask) === array() && array_diff($diskOperationsByTask, $iblockOperationsMapped) === array()) { $this->log(array( "Iblock task {$taskId} equals Disk task {$diskTask['ID']}", )); $map[$taskId] = $diskTask['ID']; return $map[$taskId]; } } unset($diskTask); $iblockTask = $this->getIblockTaskById($taskId); $taskFields = array( 'NAME' => substr($iblockTask['TITLE'], 0, 80) . ' (custom)', 'DESCRIPTION' => $iblockTask['DESC'], 'BINDING' => 'module', 'MODULE_ID' => Driver::INTERNAL_MODULE_ID, ); $this->log(array( "Attempt to create new task (clone from iblock task)", $taskFields, )); $newTaskId = CTask::add($taskFields); if(!$newTaskId) { $this->log(array( "Could not create new task ({$taskId})", $taskFields, )); return null; } $this->log(array( "Attempt to set operations to task {$newTaskId}", $iblockOperationsMapped, )); CTask::setOperations($newTaskId, $iblockOperationsMapped, true); $map[$taskId] = $newTaskId; return $map[$taskId]; } protected function loadDiskTasks() { if($this->diskTasks !== null) { return; } $this->diskTasks = array(); /** @noinspection PhpUndefinedClassInspection */ $query = \CTask::getList(array('ID' => 'asc'), array('MODULE_ID' => 'disk',)); while($task = $query->fetch()) { $this->diskTasks[$task['ID']] = $task; } return; } protected function getDiskTaskById($id) { $this->loadDiskTasks(); if(isset($this->diskTasks[$id])) { return $this->diskTasks[$id]; } return null; } public function getDiskTaskIdByName($name) { $this->loadDiskTasks(); foreach($this->diskTasks as $task) { if(isset($task['NAME']) && $task['NAME'] == $name) { return $task['ID']; } } unset($task); return null; } protected function getDiskOperationsByTask($taskId) { if(!isset($this->diskOperationsByTask[$taskId])) { /** @noinspection PhpDynamicAsStaticMethodCallInspection */ $this->diskOperationsByTask[$taskId] = \CTask::getOperations($taskId, true); } return $this->diskOperationsByTask[$taskId]; } protected function getIblockOperationsByTask($taskId) { if(!isset($this->iblockOperationsByTask[$taskId])) { /** @noinspection PhpDynamicAsStaticMethodCallInspection */ $this->iblockOperationsByTask[$taskId] = \CTask::getOperations($taskId, true); } return $this->iblockOperationsByTask[$taskId]; } protected function getIblockTaskById($id) { $this->loadIblockTasks(); if(isset($this->iblockTasks[$id])) { return $this->iblockTasks[$id]; } return null; } protected function loadIblockTasks() { if($this->iblockTasks !== null) { return; } $rs = CTask::GetList( array("LETTER"=>"asc"), array( "MODULE_ID" => "iblock", "BINDING" => "iblock", ) ); $this->iblockTasks = array(); while($row = $rs->fetch()) { $this->iblockTasks[$row["ID"]] = $row; } return; } protected function mapRightOperation($operationFromIblock) { $map = array( 'iblock_admin_display' => null, 'iblock_edit' => array(RightsManager::OP_EDIT, RightsManager::OP_SHARING), 'iblock_delete' => array(RightsManager::OP_DELETE, RightsManager::OP_DESTROY, RightsManager::OP_RESTORE), 'iblock_rights_edit' => array(RightsManager::OP_RIGHTS, RightsManager::OP_CREATE_WF, RightsManager::OP_SETTINGS), 'iblock_export' => null, 'section_read' => RightsManager::OP_READ, 'section_edit' => RightsManager::OP_EDIT, 'section_delete' => RightsManager::OP_DELETE, 'section_element_bind' => RightsManager::OP_ADD, 'section_section_bind' => RightsManager::OP_ADD, 'section_rights_edit' => array(RightsManager::OP_RIGHTS, RightsManager::OP_CREATE_WF, RightsManager::OP_SETTINGS), 'element_read' => RightsManager::OP_READ, 'element_edit' => RightsManager::OP_EDIT, 'element_edit_price' => null, 'element_delete' => RightsManager::OP_DELETE, 'element_edit_any_wf_status' => RightsManager::OP_EDIT, 'element_bizproc_start' => RightsManager::OP_START_BP, 'element_rights_edit' => RightsManager::OP_RIGHTS, ); return isset($map[$operationFromIblock])? $map[$operationFromIblock] : null; } protected function markPendingObjectAsDeleted() { if($this->isStepFinished(__METHOD__)) { return; } if($this->isMysql) { $sql = " UPDATE b_disk_object target_object INNER JOIN ( SELECT o.ID FROM b_disk_object o LEFT JOIN b_disk_object parent ON parent.ID = o.PARENT_ID WHERE parent.ID IS NULL AND o.PARENT_ID IS NOT NULL ) pseudo ON pseudo.ID = target_object.ID SET target_object.DELETED_TYPE = 22 "; } elseif($this->isOracle || $this->isMssql) { $sql = " UPDATE b_disk_object SET DELETED_TYPE = 22 where EXISTS( SELECT 'x' FROM b_disk_object child JOIN b_disk_object_path p ON p.OBJECT_ID = child.ID WHERE p.PARENT_ID IN (SELECT o.ID FROM b_disk_object o WHERE o.PARENT_ID IS NOT NULL AND NOT exists(SELECT * FROM b_disk_object WHERE o.PARENT_ID =ID)) AND child.ID = b_disk_object.ID ) "; } $this->connection->queryExecute($sql); $this->setStepFinished(__METHOD__); } protected function repairStorageId() { if($this->isStepFinished(__METHOD__)) { return; } if($this->isMysql) { $hasProblem = $this->connection->query(" SELECT object.STORAGE_ID, rootobj.STORAGE_ID FROM b_disk_object rootobj INNER JOIN b_disk_object_path path ON path.PARENT_ID = rootobj.ID INNER JOIN b_disk_object object ON object.ID = path.OBJECT_ID WHERE object.STORAGE_ID <> rootobj.STORAGE_ID AND rootobj.PARENT_ID IS NULL LIMIT 1 ")->fetch(); if($hasProblem) { $this->connection->queryExecute(" UPDATE b_disk_object rootobj INNER JOIN b_disk_object_path path ON path.PARENT_ID = rootobj.ID INNER JOIN b_disk_object object ON object.ID = path.OBJECT_ID SET object.STORAGE_ID = rootobj.STORAGE_ID WHERE object.STORAGE_ID <> rootobj.STORAGE_ID AND rootobj.PARENT_ID IS NULL "); } } $this->setStepFinished(__METHOD__); } protected function addMissedGroupStorages() { if($this->isStepFinished(__METHOD__)) { return; } $groupType = $this->sqlHelper->forSql(ProxyType\Group::className()); $lastId = $this->getLastIblockId(); $query = $this->connection->query(" SELECT g.ID FROM b_sonet_group g LEFT JOIN b_disk_storage st ON st.ENTITY_ID = g.ID AND st.ENTITY_TYPE = '{$groupType}' AND st.MODULE_ID = 'disk' WHERE st.ENTITY_ID IS NULL AND g.ID > {$lastId} ORDER BY g.ID ASC "); while($row = $query->fetch()) { \Bitrix\Disk\Driver::getInstance()->addGroupStorage($row['ID']); $this->storeIblockId($row['ID']); $this->abortIfNeeded(); } $this->storeIblockId(0); $this->setStepFinished(__METHOD__); } protected function deletePairNegativeRights() { if($this->isStepFinished(__METHOD__)) { return; } if($this->isMysql) { $this->connection->queryExecute(" DELETE plus, minus FROM b_disk_right plus INNER JOIN b_disk_right minus ON plus.OBJECT_ID = minus.OBJECT_ID AND plus.ACCESS_CODE = minus.ACCESS_CODE AND plus.TASK_ID = minus.TASK_ID WHERE minus.NEGATIVE = 1 AND plus.NEGATIVE = 0 "); } elseif($this->isMssql) { $this->connection->queryExecute(" DELETE plus FROM b_disk_right plus INNER JOIN b_disk_right minus ON plus.OBJECT_ID = minus.OBJECT_ID AND plus.ACCESS_CODE = minus.ACCESS_CODE AND plus.TASK_ID = minus.TASK_ID WHERE minus.NEGATIVE = 1 AND plus.NEGATIVE = 0 "); } elseif($this->isOracle) { $this->connection->queryExecute(' DELETE FROM (SELECT * FROM b_disk_right plus WHERE plus.NEGATIVE = 0 AND EXISTS(SELECT \'x\' FROM b_disk_right "minus" WHERE "minus".NEGATIVE = 1 AND plus.OBJECT_ID = "minus".OBJECT_ID AND plus.ACCESS_CODE = "minus".ACCESS_CODE AND plus.TASK_ID = "minus".TASK_ID) ) '); } $this->setStepFinished(__METHOD__); } protected function fillObjectRightsMoveElements() { if($this->isStepFinished(__METHOD__)) { return; } $this->connection->queryExecute(" INSERT INTO b_disk_right(OBJECT_ID, TASK_ID, ACCESS_CODE, DOMAIN, NEGATIVE) SELECT do.ID, r.TASK_ID, r.GROUP_CODE, '', 0 FROM b_iblock_right r INNER JOIN b_disk_object do ON r.ENTITY_ID = do.WEBDAV_ELEMENT_ID WHERE r.ENTITY_TYPE='element' AND do.TYPE=3 AND r.GROUP_CODE<>'SA' " ); $this->setStepFinished(__METHOD__); } protected function fillObjectRightsMoveSections() { if($this->isStepFinished(__METHOD__)) { return; } $this->connection->queryExecute(" INSERT INTO b_disk_right(OBJECT_ID, TASK_ID, ACCESS_CODE, DOMAIN, NEGATIVE) SELECT do.ID, r.TASK_ID, r.GROUP_CODE, '', 0 FROM b_iblock_right r INNER JOIN b_disk_object do ON r.ENTITY_ID = do.WEBDAV_SECTION_ID WHERE r.ENTITY_TYPE='section' AND do.TYPE=2 AND r.GROUP_CODE<>'SA' " ); $this->setStepFinished(__METHOD__); } protected function fillObjectRightsMoveIblocks() { if($this->isStepFinished(__METHOD__)) { return; } $this->connection->queryExecute(" INSERT INTO b_disk_right(OBJECT_ID, TASK_ID, ACCESS_CODE, DOMAIN, NEGATIVE) SELECT do.ID, r.TASK_ID, r.GROUP_CODE, '', 0 FROM b_iblock_right r INNER JOIN b_disk_object do ON r.ENTITY_ID = do.WEBDAV_IBLOCK_ID WHERE r.ENTITY_TYPE='iblock' AND do.TYPE=2 AND r.GROUP_CODE<>'SA' AND do.PARENT_ID IS NULL " ); $this->setStepFinished(__METHOD__); } protected function fillObjectRightsSetNegative() { if($this->isStepFinished(__METHOD__)) { return; } $lastId = $this->getLastIblockId(); $query = $this->connection->query("SELECT ID FROM b_disk_storage WHERE ID > {$lastId} ORDER BY ID ASC"); while($storageRow = $query->fetch()) { $storageId = $storageRow['ID']; $this->abortIfNeeded(); $this->connection->queryExecute(" INSERT INTO b_disk_right(OBJECT_ID, TASK_ID, ACCESS_CODE, DOMAIN, NEGATIVE) SELECT DISTINCT rchild.OBJECT_ID, rtop.TASK_ID, rtop.ACCESS_CODE, '', 1 FROM b_disk_right rtop INNER JOIN b_disk_object_path robj ON rtop.OBJECT_ID=robj.PARENT_ID AND robj.PARENT_ID<>robj.OBJECT_ID INNER JOIN b_disk_right rchild ON robj.OBJECT_ID=rchild.OBJECT_ID INNER JOIN b_disk_object object ON rtop.OBJECT_ID = object.ID WHERE rchild.ACCESS_CODE=rtop.ACCESS_CODE AND object.STORAGE_ID = {$storageId} " ); $this->storeIblockId($storageId); } $this->storeIblockId(0); $this->setStepFinished(__METHOD__); } protected function fillObjectSimpleRightsMoveSections() { if($this->isStepFinished(__METHOD__)) { return; } $this->connection->queryExecute(" INSERT INTO b_disk_simple_right(OBJECT_ID, ACCESS_CODE) SELECT do.ID, ir.GROUP_CODE FROM b_disk_object do INNER JOIN b_iblock i ON do.WEBDAV_IBLOCK_ID=i.ID INNER JOIN b_iblock_section_right sr ON sr.SECTION_ID=do.WEBDAV_SECTION_ID INNER JOIN b_iblock_right ir ON sr.RIGHT_ID=ir.ID AND ir.OP_SREAD='Y' WHERE do.TYPE=2 AND i.RIGHTS_MODE='E' " ); $this->setStepFinished(__METHOD__); } protected function fillObjectSimpleRightsMoveElements() { if($this->isStepFinished(__METHOD__)) { return; } $this->connection->queryExecute(" INSERT INTO b_disk_simple_right(OBJECT_ID, ACCESS_CODE) SELECT do.ID, ir.GROUP_CODE FROM b_disk_object do INNER JOIN b_iblock i ON do.WEBDAV_IBLOCK_ID=i.ID INNER JOIN b_iblock_element_right er ON er.ELEMENT_ID=do.WEBDAV_ELEMENT_ID INNER JOIN b_iblock_right ir ON er.RIGHT_ID=ir.ID AND ir.OP_EREAD='Y' WHERE do.TYPE=3 AND i.RIGHTS_MODE='E' " ); $this->setStepFinished(__METHOD__); } protected function fillObjectSimpleRightsMoveIblocks() { if($this->isStepFinished(__METHOD__)) { return; } //set simple rights on root of storage (type common) $proxyType = $this->sqlHelper->forSql(ProxyType\Common::className()); $this->connection->queryExecute(" INSERT INTO b_disk_simple_right(OBJECT_ID, ACCESS_CODE) SELECT do.ID, ir.GROUP_CODE FROM b_disk_object do INNER JOIN b_iblock i ON do.WEBDAV_IBLOCK_ID=i.ID INNER JOIN b_iblock_right ir ON ir.IBLOCK_ID = i.ID AND ir.ENTITY_TYPE = 'iblock' AND ir.ENTITY_ID = i.ID AND ir.OP_EREAD='Y' INNER JOIN b_disk_storage st ON st.ROOT_OBJECT_ID = do.ID WHERE i.RIGHTS_MODE='E' AND st.ENTITY_TYPE = '{$proxyType}' " ); $this->setStepFinished(__METHOD__); } protected function fillObjectMoveNonExtendedRights() { if($this->isStepFinished(__METHOD__)) { return; } $rightsManager = Driver::getInstance()->getRightsManager(); $caseStr = "CASE ig.PERMISSION WHEN 'R' THEN ".$rightsManager->getTaskIdByName(RightsManager::TASK_READ)." WHEN 'T' THEN ".$rightsManager->getTaskIdByName(RightsManager::TASK_ADD)." WHEN 'U' THEN ".$rightsManager->getTaskIdByName(RightsManager::TASK_EDIT)." WHEN 'W' THEN ".$rightsManager->getTaskIdByName(RightsManager::TASK_EDIT)." WHEN 'X' THEN ".$rightsManager->getTaskIdByName(RightsManager::TASK_FULL)." END"; $this->connection->queryExecute(" INSERT INTO b_disk_right(OBJECT_ID, ACCESS_CODE, TASK_ID, DOMAIN, NEGATIVE) SELECT do.ID, " . $this->getConcatFunction("'G'", 'ig.GROUP_ID') . ", $caseStr, '', 0 FROM b_disk_object do INNER JOIN b_iblock i ON do.WEBDAV_IBLOCK_ID=i.ID INNER JOIN b_iblock_group ig ON ig.IBLOCK_ID=i.ID WHERE do.WEBDAV_SECTION_ID IS NULL AND do.TYPE=2 AND do.PARENT_ID IS NULL AND ig.PERMISSION>='R' AND (i.RIGHTS_MODE<>'E' OR i.RIGHTS_MODE IS NULL) " ); $this->setStepFinished(__METHOD__); } protected function fillObjectMoveNonExtendedSimpleRights() { if($this->isStepFinished(__METHOD__)) { return; } $this->connection->queryExecute(" INSERT INTO b_disk_simple_right(OBJECT_ID, ACCESS_CODE) SELECT p.OBJECT_ID, " . $this->getConcatFunction("'G'", 'ig.GROUP_ID') . " FROM b_disk_object do INNER JOIN b_iblock i ON do.WEBDAV_IBLOCK_ID=i.ID INNER JOIN b_iblock_group ig ON ig.IBLOCK_ID=i.ID INNER JOIN b_disk_object_path p ON p.PARENT_ID=do.ID WHERE do.WEBDAV_SECTION_ID IS NULL AND do.TYPE=2 AND do.PARENT_ID IS NULL AND (i.RIGHTS_MODE<>'E' OR i.RIGHTS_MODE IS NULL) AND ig.PERMISSION>='R' " ); $this->setStepFinished(__METHOD__); } protected function fillObjectRightsMoveTasks() { if($this->isStepFinished(__METHOD__)) { return; } $defaultIblockPermissions = $defaultUserPermissions = array(); foreach($this->getIblockWithUserFiles() as $iblock) { $res = $this->connection->query(" SELECT r.TASK_ID, r.GROUP_CODE FROM b_iblock_right r WHERE r.ENTITY_TYPE='iblock' AND r.GROUP_CODE<>'SA' AND r.IBLOCK_ID=".$iblock['ID'] ); while($r = $res->fetch()) { $defaultIblockPermissions[$r['TASK_ID']] = $r; } break; } $lastId = $this->getLastIblockId(); $tasks = $this->connection->query("SELECT DISTINCT TASK_ID FROM b_disk_right")->fetchAll(); \Bitrix\Main\Type\Collection::sortByColumn($tasks, 'TASK_ID'); $defaultUserStorageRights = Option::get("disk", "default_user_storage_rights", array()); if(is_string($defaultUserStorageRights)) { $defaultUserStorageRights = unserialize($defaultUserStorageRights); } foreach($tasks as $row) { $taskId = $row['TASK_ID']; if($lastId > $taskId) { continue; } $this->abortIfNeeded(); $newTaskId = $this->convertIblockTaskToDiskTask($taskId); if($newTaskId === self::COULD_NOT_FIND_IBLOCK_TASK) { $this->storeIblockId($taskId); continue; } if(!$newTaskId) { throw new Exception("Couldn't convert task $taskId"); } if($newTaskId == self::DENY_TASK) { $this->connection->queryExecute("DELETE FROM b_disk_right WHERE TASK_ID={$taskId}"); } else { if($defaultIblockPermissions[$taskId]) { $defaultUserStorageRights[$newTaskId] = $defaultIblockPermissions[$taskId]['GROUP_CODE']; Option::set("disk", "default_user_storage_rights", serialize($defaultUserStorageRights)); } $this->connection->queryExecute("UPDATE b_disk_right SET TASK_ID={$newTaskId} WHERE TASK_ID={$taskId}"); } $this->storeIblockId($taskId); } unset($row); $this->storeIblockId(0); $this->setStepFinished(__METHOD__); } protected function fillObjectRights() { if($this->isStepFinished(__METHOD__)) { return; } $this->fillObjectRightsMoveElements(); $this->abortIfNeeded(); $this->fillObjectRightsMoveSections(); $this->abortIfNeeded(); $this->fillObjectRightsMoveIblocks(); $this->abortIfNeeded(); $this->fillObjectRightsSetNegative(); $this->abortIfNeeded(); $this->fillObjectRightsMoveTasks(); $this->abortIfNeeded(); $this->fillObjectSimpleRightsMoveSections(); $this->abortIfNeeded(); $this->fillObjectSimpleRightsMoveElements(); $this->abortIfNeeded(); $this->fillObjectSimpleRightsMoveIblocks(); $this->abortIfNeeded(); $this->fillObjectMoveNonExtendedRights(); $this->abortIfNeeded(); $this->fillObjectMoveNonExtendedSimpleRights(); $this->abortIfNeeded(); $this->setStepFinished(__METHOD__); } protected function storeFillPathParentId($id) { COption::SetOptionString( 'disk', '~migrateFillParent', $id ); } protected function getLastPathParentId() { return COption::getOptionString( 'disk', '~migrateFillParent', 0 ); } protected function storeStorageId($id) { COption::SetOptionString( 'disk', '~migrateFillStorage', $id ); } protected function getStorageId() { return COption::getOptionString( 'disk', '~migrateFillStorage', 0 ); } protected function storeIblockId($id) { COption::SetOptionString( 'disk', '~migrateIblockId', $id ); } protected function getLastIblockId() { return COption::getOptionString( 'disk', '~migrateIblockId', 0 ); } protected function fillSelfObjectPath() { if($this->isStepFinished(__METHOD__)) { return; } $this->connection->queryExecute("TRUNCATE TABLE b_disk_object_path"); //fill "self path" on elements $this->connection->queryExecute(" INSERT INTO b_disk_object_path (PARENT_ID, OBJECT_ID, DEPTH_LEVEL) SELECT ID, ID, 0 FROM b_disk_object "); $this->setStepFinished(__METHOD__); } protected function recalcRightsOnUnPublishObject() { if($this->isStepFinished(__METHOD__)) { return; } //delete simple right on files with WF_STATUS_ID = 2 if($this->isMysql || $this->isMssql) { $this->connection->queryExecute(" DELETE simple FROM b_disk_simple_right simple INNER JOIN b_disk_object obj ON obj.ID = simple.OBJECT_ID AND obj.TYPE=3 INNER JOIN b_iblock_element el ON obj.WEBDAV_ELEMENT_ID = el.ID WHERE el.WF_STATUS_ID = 2 AND NOT EXISTS(SELECT 'x' FROM b_disk_right r WHERE r.OBJECT_ID = obj.ID) "); } elseif($this->isOracle) { $this->connection->queryExecute(" DELETE FROM (SELECT simple.* FROM b_disk_simple_right simple INNER JOIN b_disk_object obj ON obj.ID = simple.OBJECT_ID AND obj.TYPE=3 INNER JOIN b_iblock_element el ON obj.WEBDAV_ELEMENT_ID = el.ID WHERE el.WF_STATUS_ID = 2 AND NOT EXISTS(SELECT 'x' FROM b_disk_right r WHERE r.OBJECT_ID = obj.ID)) "); } //insert simple rights on these unpublish files $this->connection->queryExecute(" INSERT INTO b_disk_simple_right (OBJECT_ID, ACCESS_CODE) SELECT obj.ID, 'CR' FROM b_iblock_element el INNER JOIN b_disk_object obj ON obj.WEBDAV_ELEMENT_ID = el.ID AND obj.TYPE=3 WHERE el.WF_STATUS_ID = 2 AND NOT EXISTS(SELECT 'x' FROM b_disk_right r WHERE r.OBJECT_ID = obj.ID) "); //now we set negative=1 to all rights above these files $this->connection->queryExecute(" INSERT INTO b_disk_right (OBJECT_ID, TASK_ID, ACCESS_CODE, DOMAIN, NEGATIVE) SELECT p.OBJECT_ID, r.TASK_ID, r.ACCESS_CODE, r.DOMAIN, 1 FROM b_disk_right r JOIN b_disk_object_path p ON p.PARENT_ID = r.OBJECT_ID WHERE p.OBJECT_ID IN (SELECT simple.OBJECT_ID FROM b_disk_simple_right simple INNER JOIN b_disk_object obj ON obj.ID = simple.OBJECT_ID INNER JOIN b_iblock_element el ON obj.WEBDAV_ELEMENT_ID = el.ID AND el.WF_STATUS_ID = 2 WHERE simple.ACCESS_CODE = 'CR') "); $taskId = Driver::getInstance()->getRightsManager()->getTaskIdByName(RightsManager::TASK_FULL); //now we set full access on these files for CR $this->connection->queryExecute(" INSERT INTO b_disk_right (OBJECT_ID, TASK_ID, ACCESS_CODE, NEGATIVE) SELECT simple.OBJECT_ID, {$taskId}, 'CR', 0 FROM b_disk_simple_right simple INNER JOIN b_disk_object obj ON obj.ID = simple.OBJECT_ID INNER JOIN b_iblock_element el ON obj.WEBDAV_ELEMENT_ID = el.ID AND el.WF_STATUS_ID = 2 WHERE simple.ACCESS_CODE = 'CR' "); $this->setStepFinished(__METHOD__); } protected function migrateVersion() { if(!$this->runWorkWithBizproc) { return; } if($this->isStepFinished(__METHOD__)) { return; } $uploadDir = COption::getOptionString("main", "upload_dir", "upload"); $isCloud = CModule::IncludeModule("clouds"); $useGZipCompressionOption = \Bitrix\Main\Config\Option::get("bizproc", "use_gzip_compression", ""); $isBitrix24 = IsModuleInstalled('bitrix24'); $bucket = null; if($isBitrix24 && $isCloud) { $bucket = new CCloudStorageBucket(1); $bucket->init(); } if($useGZipCompressionOption === "Y") { $this->useGZipCompression = true; } elseif($useGZipCompressionOption === "N") { $this->useGZipCompression = false; } else { $this->useGZipCompression = (function_exists("gzcompress") && ($GLOBALS["DB"]->type != "ORACLE" || !defined('BX_UTF'))); } $sqlHelper = $this->connection->getSqlHelper(); $lastId = $this->getStorageId(); $versionQuery = $this->connection->query(" SELECT obj.*, h.ID VERSION_ID, h.NAME VERSION_NAME, h.DOCUMENT VERSION_DOC, h.USER_ID VERSION_USER_ID, h.MODIFIED VERSION_MODIFIED FROM b_disk_object obj INNER JOIN b_bp_history h ON h.DOCUMENT_ID = obj.WEBDAV_ELEMENT_ID AND h.MODULE_ID = 'webdav' WHERE obj.TYPE = 3 AND h.ID > {$lastId} ORDER BY h.ID " ); while($version = $versionQuery->fetch()) { $this->abortIfNeeded(); if(strlen($version['VERSION_DOC']) > 0) { if($this->useGZipCompression) { $version['VERSION_DOC'] = gzuncompress($version['VERSION_DOC']); } $version['VERSION_DOC'] = unserialize($version['VERSION_DOC']); if(!is_array($version['VERSION_DOC'])) { $version['VERSION_DOC'] = array(); } } else { $version['VERSION_DOC'] = array(); } if(empty($version['VERSION_DOC']) || empty($version['VERSION_DOC']['PROPERTIES']['WEBDAV_VERSION']['VALUE']) || empty($version['VERSION_DOC']['PROPERTIES']['FILE']['VALUE'])) { $this->storeStorageId($version['VERSION_ID']); continue; } $version['VERSION_NAME'] = $sqlHelper->forSql($version['VERSION_NAME']); $version['VERSION_MODIFIED'] = $sqlHelper->getCharToDateFunction($version['VERSION_MODIFIED']->format("Y-m-d H:i:s")); $version['UPDATE_TIME'] = $sqlHelper->getCharToDateFunction($version['UPDATE_TIME']->format("Y-m-d H:i:s")); $fullPath = $version['VERSION_DOC']['PROPERTIES']['FILE']['VALUE']; $handlerId = ''; $filename = bx_basename($fullPath); if(substr($fullPath, 0, 4) == "http") { if(!$isCloud) { $this->storeStorageId($version['VERSION_ID']); continue; } if(!$isBitrix24) { $bucket = CCloudStorage::findBucketByFile($fullPath); if(!$bucket) { $this->storeStorageId($version['VERSION_ID']); continue; } } $handlerId = $bucket->ID; $subDir = trim(substr(getDirPath($fullPath), strlen($bucket->getFileSRC('/'))), '/'); $contentType = \Bitrix\Disk\TypeFile::getMimeTypeByFilename($filename); } else { $subDir = trim(substr(getDirPath($fullPath), strlen('/'. $uploadDir)), '/'); $contentType = $this->getContentType($fullPath, $filename); } $webdavSize = $version['VERSION_DOC']['PROPERTIES']['WEBDAV_SIZE']['VALUE']; if(empty($webdavSize)) { $webdavSize = 0; } $fileId = CFile::doInsert(array( 'HEIGHT' => 0, 'WIDTH' => 0, 'FILE_SIZE' => $webdavSize, 'CONTENT_TYPE' => $contentType, 'SUBDIR' => $subDir, 'FILE_NAME' => $filename, 'MODULE_ID' => Driver::INTERNAL_MODULE_ID, 'ORIGINAL_NAME' => $filename, 'DESCRIPTION' => '', 'HANDLER_ID' => $handlerId, 'EXTERNAL_ID' => md5(mt_rand()), )); if(!$fileId) { $this->storeStorageId($version['VERSION_ID']); continue; } $this->connection->queryExecute(" INSERT INTO b_disk_version (OBJECT_ID, FILE_ID, " . $this->sqlHelper->quote('SIZE') . ", NAME, CREATE_TIME, CREATED_BY, MISC_DATA, OBJECT_CREATE_TIME, OBJECT_CREATED_BY, OBJECT_UPDATE_TIME, OBJECT_UPDATED_BY, GLOBAL_CONTENT_VERSION, BP_VERSION_ID) VALUES ({$version['ID']}, {$fileId}, {$webdavSize}, '{$version['VERSION_NAME']}', {$version['VERSION_MODIFIED']}, {$version['VERSION_USER_ID']}, null, {$version['VERSION_MODIFIED']}, {$version['CREATED_BY']}, {$version['UPDATE_TIME']}, {$version['UPDATED_BY']}, {$version['VERSION_DOC']['PROPERTIES']['WEBDAV_VERSION']['VALUE']}, {$version['VERSION_ID']}) "); $this->storeStorageId($version['VERSION_ID']); } $this->abortIfNeeded(); $this->storeStorageId(0); $this->setStepFinished(__METHOD__); } private function getContentType($fullPath, $filename) { $contentType = 'application/octet-stream'; $file = new IO\File($fullPath); if($file->isExists()) { $contentType = CFile::getContentType($file->getPhysicalPath(), true); } else { try { $contentType = CFile::getContentType($_SERVER["DOCUMENT_ROOT"] . $fullPath); } catch(Exception $e) {} } return \Bitrix\Disk\TypeFile::normalizeMimeType($contentType, $filename); } protected function migrateHeadVersion() { if($this->isStepFinished(__METHOD__)) { return; } $this->connection->queryExecute(" INSERT INTO b_disk_version (OBJECT_ID, FILE_ID, " . $this->sqlHelper->quote('SIZE') . ", NAME, CREATE_TIME, CREATED_BY, MISC_DATA, OBJECT_CREATE_TIME, OBJECT_CREATED_BY, OBJECT_UPDATE_TIME, OBJECT_UPDATED_BY, GLOBAL_CONTENT_VERSION) SELECT obj.ID, obj.FILE_ID, " . $this->sqlHelper->quote('obj.SIZE') . ", obj.NAME, obj.UPDATE_TIME, obj.UPDATED_BY, null, obj.CREATE_TIME, obj.CREATED_BY, obj.UPDATE_TIME, obj.UPDATED_BY, obj.GLOBAL_CONTENT_VERSION FROM b_disk_object obj WHERE obj.TYPE=3 "); $this->setStepFinished(__METHOD__); } protected function deleteTrashFolders() { if($this->isStepFinished(__METHOD__)) { return; } if($this->isMysql || $this->isMssql) { $sql = " DELETE p FROM b_disk_object_path p INNER JOIN b_disk_object trash ON trash.ID=p.OBJECT_ID WHERE trash.NAME = '.Trash' "; } elseif($this->isOracle) { $sql = " DELETE FROM (SELECT p.* FROM b_disk_object_path p INNER JOIN b_disk_object trash ON trash.ID=p.OBJECT_ID WHERE trash.NAME = '.Trash') "; } $this->connection->queryExecute($sql); $this->connection->queryExecute(" DELETE FROM b_disk_object WHERE NAME = '.Trash' "); $this->setStepFinished(__METHOD__); } protected function migrateTrashFiles() { if($this->isStepFinished(__METHOD__)) { return; } $lastId = $this->getStorageId(); //first migrate folder from trash $trashQuery = $this->connection->query(" SELECT obj.*, s.ROOT_OBJECT_ID ROOT_OBJECT_ID, PROP_INFO_EL.VALUE WEBDAV_INFO FROM b_disk_object obj INNER JOIN b_disk_storage s ON s.ID = obj.STORAGE_ID INNER JOIN b_disk_object trash ON trash.ID = obj.PARENT_ID AND trash.PARENT_ID = s.ROOT_OBJECT_ID INNER JOIN b_iblock_property PROP_WEBDAV_INFO ON PROP_WEBDAV_INFO.IBLOCK_ID = obj.WEBDAV_IBLOCK_ID AND PROP_WEBDAV_INFO.CODE = 'WEBDAV_INFO' INNER JOIN b_iblock_element_property PROP_INFO_EL ON PROP_INFO_EL.IBLOCK_PROPERTY_ID = PROP_WEBDAV_INFO.ID AND PROP_INFO_EL.IBLOCK_ELEMENT_ID = obj.WEBDAV_ELEMENT_ID WHERE obj.TYPE=3 AND trash.NAME = '.Trash' AND obj.ID > {$lastId} ORDER BY obj.ID " ); while($trashChild = $trashQuery->fetch()) { $this->abortIfNeeded(); $undeletePath = $this->getElementTrashPath($trashChild); if(empty($undeletePath)) { $this->log(array( "Skip item {$trashChild['ID']} from .Trash", "Empty WEBDAV_INFO", )); $this->storeStorageId($trashChild['ID']); continue; } $undeletePath = trim($undeletePath, '/'); $filter = array( 'TYPE' => \Bitrix\Disk\Internals\ObjectTable::TYPE_FOLDER, 'STORAGE_ID' => $trashChild['STORAGE_ID'], 'PARENT_ID' => $trashChild['ROOT_OBJECT_ID'], ); $mustCreatePathPieces = array(); $undeletePathPieces = explode('/', $undeletePath); $parentId = $filter['PARENT_ID']; $parentDeletedType = null; $filename = array_pop($undeletePathPieces); foreach($undeletePathPieces as $i => $pieceOfPath) { $filter['NAME'] = $this->sqlHelper->forSql($pieceOfPath); $folder = $this->connection->query(" SELECT ID, NAME, REAL_OBJECT_ID, STORAGE_ID, PARENT_ID, DELETED_TYPE FROM b_disk_object obj WHERE obj.PARENT_ID = {$filter['PARENT_ID']} AND obj.STORAGE_ID = {$filter['STORAGE_ID']} AND obj.TYPE = {$filter['TYPE']} AND obj.NAME = '{$filter['NAME']}' ")->fetch(); if($folder) { $filter['PARENT_ID'] = $parentId = $folder['ID']; if(!empty($folder['DELETED_TYPE'])) { $parentDeletedType = $folder['DELETED_TYPE']; } continue; } if(!$folder) { $this->log(array( "Folder with name {$pieceOfPath} does not exist", )); $mustCreatePathPieces = array_slice($undeletePathPieces, $i); break; } } unset($pieceOfPath); if($parentId) { $success = true; /** @var Folder $parentFolder */ $parentFolder = Folder::loadById($parentId); $folderData = array( 'CREATE_TIME' => $trashChild['CREATE_TIME'], 'UPDATE_TIME' => $trashChild['UPDATE_TIME'], 'CREATED_BY' => $trashChild['CREATED_BY'], 'UPDATED_BY' => $trashChild['UPDATED_BY'], ); foreach($mustCreatePathPieces as $i => $pieceOfPath) { $deletedType = FolderTable::DELETED_TYPE_CHILD; if($i == 0 && !$parentDeletedType) { $deletedType = FolderTable::DELETED_TYPE_ROOT; } $folderData['NAME'] = Text::correctFilename($pieceOfPath); if($deletedType == FolderTable::DELETED_TYPE_ROOT) { $folderData['NAME'] = self::appendTrashCanSuffix($folderData['NAME']); } $folder = $parentFolder->addSubFolder($folderData, array(), true); if(!$folder) { $this->log(array( "Skip item {$trashChild['ID']} from .Trash", "Could not create subfolder {$folderData['NAME']}", )); $this->storeStorageId($trashChild['ID']); $success = false; break; } $updateResult = FolderTable::update($folder->getId(), array( 'DELETED_TYPE' => $deletedType, 'DELETE_TIME' => $folder->getUpdateTime(), 'DELETED_BY' => $folder->getUpdatedBy(), )); if(!$updateResult->isSuccess()) { $this->log(array( "Skip item {$trashChild['ID']} from .Trash", "Could not markDeleted subfolder {$folder->getId()}", )); $this->storeStorageId($trashChild['ID']); $success = false; break; } $parentFolder = $folder; } unset($pieceOfPath, $folder, $undeletePath); if($success) { //move trashChild into new folder if($this->isMysql || $this->isMssql) { $this->connection->queryExecute(" DELETE a FROM b_disk_object_path a JOIN b_disk_object_path d ON a.OBJECT_ID = d.OBJECT_ID LEFT JOIN b_disk_object_path x ON x.PARENT_ID = d.PARENT_ID AND x.OBJECT_ID = a.PARENT_ID WHERE d.PARENT_ID = {$trashChild['ID']} AND x.PARENT_ID IS NULL; "); } elseif($this->isOracle) { $this->connection->queryExecute(" DELETE FROM b_disk_object_path WHERE ID IN (SELECT a.ID FROM b_disk_object_path a JOIN b_disk_object_path d ON a.OBJECT_ID = d.OBJECT_ID LEFT JOIN b_disk_object_path x ON x.PARENT_ID = d.PARENT_ID AND x.OBJECT_ID = a.PARENT_ID WHERE d.PARENT_ID = {$trashChild['ID']} AND x.PARENT_ID IS NULL) "); } $this->connection->queryExecute(" INSERT INTO b_disk_object_path (PARENT_ID, OBJECT_ID, DEPTH_LEVEL) SELECT stree.PARENT_ID, subtree.OBJECT_ID, stree.DEPTH_LEVEL+subtree.DEPTH_LEVEL+1 FROM b_disk_object_path stree INNER JOIN b_disk_object_path subtree ON subtree.PARENT_ID = {$trashChild['ID']} AND stree.OBJECT_ID = {$parentFolder->getId()} "); $deletedType = FolderTable::DELETED_TYPE_CHILD; if(!$mustCreatePathPieces) { $deletedType = FolderTable::DELETED_TYPE_ROOT; } $newName = Text::correctFilename($filename); if($deletedType == FolderTable::DELETED_TYPE_ROOT) { $newName = self::appendTrashCanSuffix($newName); } $newName = $this->sqlHelper->forSql($newName); $this->connection->queryExecute(" UPDATE b_disk_object SET NAME='{$newName}', PARENT_ID = {$parentFolder->getId()}, DELETED_TYPE = {$deletedType}, DELETED_BY=UPDATED_BY, DELETE_TIME=UPDATE_TIME WHERE ID={$trashChild['ID']} AND STORAGE_ID={$trashChild['STORAGE_ID']} "); $this->connection->queryExecute(" INSERT IGNORE INTO b_disk_deleted_log_v2 (STORAGE_ID, OBJECT_ID, TYPE, USER_ID, CREATE_TIME) VALUES ({$trashChild['STORAGE_ID']}, {$trashChild['ID']}, {$trashChild['TYPE']}, {$trashChild['UPDATED_BY']}, " . $this->sqlHelper->getCurrentDateTimeFunction() . ") "); $this->storeStorageId($trashChild['ID']); } } $this->storeStorageId($trashChild['ID']); } $this->abortIfNeeded(); $this->storeStorageId(0); $this->setStepFinished(__METHOD__); } public static function appendTrashCanSuffix($string, $suffix = null) { // if($suffix === null) // { // // 14 length // $suffix = str_pad(time(), 11, '0', STR_PAD_LEFT) . chr(rand(97, 122)) . chr(rand(97, 122)) . chr(rand(97, 122)); // } // else // { $suffix = str_pad(strtr(microtime(true), array('.' => '')), 14, chr(rand(97, 122)), STR_PAD_LEFT); // } return $string . 'i' . $suffix . 'i'; } protected function migrateTrashFolders() { if($this->isStepFinished(__METHOD__)) { return; } $lastId = $this->getStorageId(); //first migrate folder from trash $trashQuery = $this->connection->query(" SELECT obj.*, s.ROOT_OBJECT_ID ROOT_OBJECT_ID, secta.DESCRIPTION DESCRIPTION FROM b_disk_object obj INNER JOIN b_disk_storage s ON s.ID = obj.STORAGE_ID INNER JOIN b_disk_object trash ON trash.ID = obj.PARENT_ID AND trash.PARENT_ID = s.ROOT_OBJECT_ID INNER JOIN b_iblock_section secta ON secta.ID = obj.ID WHERE obj.TYPE=2 AND trash.NAME = '.Trash' AND obj.ID > {$lastId} ORDER BY obj.ID " ); while($trashChild = $trashQuery->fetch()) { $this->abortIfNeeded(); $undeletePath = $this->getSectionInTrash($trashChild); if(empty($undeletePath)) { $this->log(array( "Skip item {$trashChild['ID']} from .Trash", "Empty WEBDAV_INFO (DESCRIPTION)", )); $this->storeStorageId($trashChild['ID']); continue; } $undeletePath = trim($undeletePath, '/'); $filter = array( 'TYPE' => \Bitrix\Disk\Internals\ObjectTable::TYPE_FOLDER, 'STORAGE_ID' => $trashChild['STORAGE_ID'], 'PARENT_ID' => $trashChild['ROOT_OBJECT_ID'], ); $mustCreatePathPieces = array(); $undeletePathPieces = explode('/', $undeletePath); $parentId = $filter['PARENT_ID']; $parentDeletedType = null; $filename = array_pop($undeletePathPieces); foreach($undeletePathPieces as $i => $pieceOfPath) { $filter['NAME'] = $this->sqlHelper->forSql($pieceOfPath); $folder = $this->connection->query(" SELECT ID, NAME, REAL_OBJECT_ID, STORAGE_ID, PARENT_ID, DELETED_TYPE FROM b_disk_object obj WHERE obj.PARENT_ID = {$filter['PARENT_ID']} AND obj.STORAGE_ID = {$filter['STORAGE_ID']} AND obj.TYPE = {$filter['TYPE']} AND obj.NAME = '{$filter['NAME']}' ")->fetch(); if($folder) { $filter['PARENT_ID'] = $parentId = $folder['ID']; if(!empty($folder['DELETED_TYPE'])) { $parentDeletedType = $folder['DELETED_TYPE']; } continue; } if(!$folder) { $this->log(array( "Folder with name {$pieceOfPath} does not exist", )); $mustCreatePathPieces = array_slice($undeletePathPieces, $i); break; } } unset($pieceOfPath); if($parentId) { $success = true; /** @var Folder $parentFolder */ $parentFolder = Folder::loadById($parentId); $folderData = array( 'CREATE_TIME' => $trashChild['CREATE_TIME'], 'UPDATE_TIME' => $trashChild['UPDATE_TIME'], 'CREATED_BY' => $trashChild['CREATED_BY'], 'UPDATED_BY' => $trashChild['UPDATED_BY'], ); foreach($mustCreatePathPieces as $i => $pieceOfPath) { $deletedType = FolderTable::DELETED_TYPE_CHILD; if($i == 0 && !$parentDeletedType) { $deletedType = FolderTable::DELETED_TYPE_ROOT; } $folderData['NAME'] = Text::correctFilename($pieceOfPath); if($deletedType == FolderTable::DELETED_TYPE_ROOT) { $folderData['NAME'] = self::appendTrashCanSuffix($folderData['NAME']); } $folder = $parentFolder->addSubFolder($folderData, array(), true); if(!$folder) { $this->log(array( "Skip item {$trashChild['ID']} from .Trash", "Could not create subfolder {$folderData['NAME']}", )); $this->storeStorageId($trashChild['ID']); $success = false; break; } $updateResult = FolderTable::update($folder->getId(), array( 'DELETED_TYPE' => $deletedType, 'DELETE_TIME' => $folder->getUpdateTime(), 'DELETED_BY' => $folder->getUpdatedBy(), )); if(!$updateResult->isSuccess()) { $this->log(array( "Skip item {$trashChild['ID']} from .Trash", "Could not markDeleted subfolder {$folder->getId()}", )); $this->storeStorageId($trashChild['ID']); $success = false; break; } $parentFolder = $folder; } unset($pieceOfPath, $folder, $undeletePath); if($success) { //move trashChild into new folder if($this->isMysql || $this->isMssql) { $this->connection->queryExecute(" DELETE a FROM b_disk_object_path a JOIN b_disk_object_path d ON a.OBJECT_ID = d.OBJECT_ID LEFT JOIN b_disk_object_path x ON x.PARENT_ID = d.PARENT_ID AND x.OBJECT_ID = a.PARENT_ID WHERE d.PARENT_ID = {$trashChild['ID']} AND x.PARENT_ID IS NULL; "); } elseif($this->isOracle) { $this->connection->queryExecute(" DELETE FROM b_disk_object_path WHERE ID IN (SELECT a.ID FROM b_disk_object_path a JOIN b_disk_object_path d ON a.OBJECT_ID = d.OBJECT_ID LEFT JOIN b_disk_object_path x ON x.PARENT_ID = d.PARENT_ID AND x.OBJECT_ID = a.PARENT_ID WHERE d.PARENT_ID = {$trashChild['ID']} AND x.PARENT_ID IS NULL) "); } $this->connection->queryExecute(" INSERT INTO b_disk_object_path (PARENT_ID, OBJECT_ID, DEPTH_LEVEL) SELECT stree.PARENT_ID, subtree.OBJECT_ID, stree.DEPTH_LEVEL+subtree.DEPTH_LEVEL+1 FROM b_disk_object_path stree INNER JOIN b_disk_object_path subtree ON subtree.PARENT_ID = {$trashChild['ID']} AND stree.OBJECT_ID = {$parentFolder->getId()} "); //update all objects under trashChild (DELETED_TYPE) $deletedType = FolderTable::DELETED_TYPE_CHILD; if($this->isMysql) { $sql = " UPDATE b_disk_object obj INNER JOIN b_disk_object_path p ON obj.ID = p.OBJECT_ID SET obj.DELETED_TYPE = {$deletedType}, obj.DELETED_BY=obj.UPDATED_BY, obj.DELETE_TIME=obj.UPDATE_TIME WHERE p.PARENT_ID = {$trashChild['ID']} "; } elseif($this->isOracle || $this->isMssql) { $sql = " UPDATE b_disk_object SET DELETED_TYPE = {$deletedType}, DELETED_BY=(SELECT obj.UPDATED_BY FROM b_disk_object obj INNER JOIN b_disk_object_path p ON obj.ID = p.OBJECT_ID WHERE p.PARENT_ID = {$trashChild['ID']} and obj.ID = b_disk_object.ID), DELETE_TIME=(SELECT obj.UPDATE_TIME FROM b_disk_object obj INNER JOIN b_disk_object_path p ON obj.ID = p.OBJECT_ID WHERE p.PARENT_ID = {$trashChild['ID']} and obj.ID = b_disk_object.ID) WHERE EXISTS((SELECT 'x' FROM b_disk_object obj INNER JOIN b_disk_object_path p ON obj.ID = p.OBJECT_ID WHERE p.PARENT_ID = {$trashChild['ID']} and obj.ID = b_disk_object.ID)) "; } $this->connection->queryExecute($sql); $deletedType = FolderTable::DELETED_TYPE_ROOT; $newName = $this->sqlHelper->forSql(self::appendTrashCanSuffix(Text::correctFilename($filename))); $this->connection->queryExecute(" UPDATE b_disk_object SET NAME='{$newName}', PARENT_ID = {$parentFolder->getId()}, DELETED_TYPE = {$deletedType}, DELETED_BY=UPDATED_BY, DELETE_TIME=UPDATE_TIME WHERE ID={$trashChild['ID']} AND STORAGE_ID={$trashChild['STORAGE_ID']} "); $this->connection->queryExecute(" INSERT IGNORE INTO b_disk_deleted_log_v2 (STORAGE_ID, OBJECT_ID, TYPE, USER_ID, CREATE_TIME) SELECT {$trashChild['STORAGE_ID']}, p.OBJECT_ID, obj.TYPE, obj.UPDATED_BY, " . $this->sqlHelper->getCurrentDateTimeFunction() . " FROM b_disk_object obj INNER JOIN b_disk_object_path p ON obj.ID = p.OBJECT_ID WHERE p.PARENT_ID = {$trashChild['ID']} "); $this->storeStorageId($trashChild['ID']); } } $this->storeStorageId($trashChild['ID']); } $this->abortIfNeeded(); $this->storeStorageId(0); $this->setStepFinished(__METHOD__); } protected function getSectionInTrash(array $section) { if(empty($section["DESCRIPTION"]) || !is_string($section["DESCRIPTION"])) { return false; } $props = @unserialize($section["DESCRIPTION"]); if(empty($props['PROPS']['BX:']['UNDELETE']) || !is_string($props['PROPS']['BX:']['UNDELETE'])) { return false; } return $props['PROPS']['BX:']['UNDELETE']; } protected function getElementTrashPath(array $element) { if(empty($element["WEBDAV_INFO"]) || !is_string($element["WEBDAV_INFO"])) { return false; } $props = @unserialize($element["WEBDAV_INFO"]); if(empty($props['PROPS']['BX:']['UNDELETE']) || !is_string($props['PROPS']['BX:']['UNDELETE'])) { return false; } return $props['PROPS']['BX:']['UNDELETE']; } protected function migrateUfHead() { if($this->isStepFinished(__METHOD__)) { return; } $sqlHelper = $this->connection->getSqlHelper(); $proxyType = $sqlHelper->forSql(ProxyType\Common::className()); $lastId = $this->getStorageId(); $storageQuery = $this->connection->query(" SELECT secta.IBLOCK_ID IBLOCK_ID, s.ID STORAGE_ID FROM b_disk_storage s INNER JOIN b_disk_object root ON root.ID = s.ROOT_OBJECT_ID INNER JOIN b_iblock_section secta ON root.WEBDAV_SECTION_ID = secta.ID WHERE s.ENTITY_TYPE <> '{$proxyType}' AND s.MODULE_ID = 'disk' AND s.ID > {$lastId} ORDER BY s.ID "); while($storage = $storageQuery->fetch()) { $this->abortIfNeeded(); $this->migrateCustomUf("IBLOCK_{$storage['IBLOCK_ID']}_SECTION", "DISK_FOLDER_{$storage['STORAGE_ID']}"); $this->migrateCustomUf("IBLOCK_{$storage['IBLOCK_ID']}_FILE", "DISK_FILE_{$storage['STORAGE_ID']}"); // migrate property value to new uf $this->migrateCustomElementProperties($storage['IBLOCK_ID'], "DISK_FILE_{$storage['STORAGE_ID']}"); $this->storeStorageId($storage['STORAGE_ID']); } $this->abortIfNeeded(); //common $storageQuery = $this->connection->query(" SELECT s.XML_ID IBLOCK_ID, s.ID STORAGE_ID FROM b_disk_storage s WHERE s.ENTITY_TYPE = '{$proxyType}' AND s.MODULE_ID = 'disk' "); while($storage = $storageQuery->fetch()) { $this->migrateCustomUf("IBLOCK_{$storage['IBLOCK_ID']}_SECTION", "DISK_FOLDER_{$storage['STORAGE_ID']}"); $this->migrateCustomUf("IBLOCK_{$storage['IBLOCK_ID']}_FILE", "DISK_FILE_{$storage['STORAGE_ID']}"); // migrate property value to new uf $this->migrateCustomElementProperties($storage['IBLOCK_ID'], "DISK_FILE_{$storage['STORAGE_ID']}"); } $this->storeStorageId(0); $this->setStepFinished(__METHOD__); } protected function migrateCustomUf($oldName, $newName) { global $DB; $arUserFieldQuery = CUserTypeEntity::GetList(array(), array("ENTITY_ID"=> $oldName)); if(!$arUserFieldQuery) { return; } $blackList = array( 'UF_LINK_SECTION_ID' => true, 'UF_LINK_IBLOCK_ID' => true, 'UF_LINK_CAN_FORWARD' => true, 'UF_LINK_RSECTION_ID' => true, 'UF_USE_DOC_PREVIEW' => true, 'UF_USE_EXT_SERVICES' => true, 'UF_USE_BP' => true, ); $oldTableNameUf = "b_utm_".strtolower($oldName); $oldTableNameSingleUf = "b_uts_".strtolower($oldName); $newTableNameUf = "b_utm_".strtolower($newName); $newTableNameSingleUf = "b_uts_".strtolower($newName); $isFolder = strpos($newName, 'FILE') === false; $externalColumn = $isFolder? 'WEBDAV_SECTION_ID' : 'WEBDAV_ELEMENT_ID'; $columns = array(); while($arUserField = $arUserFieldQuery->fetch()) { if(isset($blackList[$arUserField['FIELD_NAME']])) { continue; } $enumValueInfos = array(); $rs = $DB->Query("SELECT * FROM b_user_field_lang WHERE USER_FIELD_ID = ".intval($arUserField['ID']), false, "FILE: ".__FILE__."<br>LINE: ".__LINE__); while($ar = $rs->Fetch()) { foreach(array("EDIT_FORM_LABEL", "LIST_COLUMN_LABEL", "LIST_FILTER_LABEL", "ERROR_MESSAGE", "HELP_MESSAGE") as $label) { $arUserField[$label][$ar["LANGUAGE_ID"]] = $ar[$label]; } } if($arUserField['USER_TYPE_ID'] == 'enumeration') { $dbRes = CUserFieldEnum::GetList(array(), array('USER_FIELD_ID' => $arUserField['ID'])); $key = 0; while($valueData = $dbRes->Fetch()) { $enumValueInfos['n'.$key] = array( 'VALUE' => $valueData['VALUE'], 'XML_ID' => $valueData['XML_ID'], 'DEF' => $valueData['DEF'], 'SORT' => $valueData['SORT'], ); $key++; } } $arUserField['ENTITY_ID'] = $newName; $CAllUserTypeEntity = new CUserTypeEntity(); unset($arUserField['ID']); $id = $CAllUserTypeEntity->add($arUserField); if($id) { $id = (int)$id; $oldId = (int)$arUserField['ID']; $columns[] = $arUserField['FIELD_NAME']; if($arUserField['MULTIPLE'] == 'Y') { if($isFolder) {//id section == id folders $this->connection->queryExecute(" INSERT INTO {$newTableNameUf} (VALUE_ID, FIELD_ID, VALUE, VALUE_INT, VALUE_DOUBLE, VALUE_DATE) SELECT obj.ID, {$id}, VALUE, VALUE_INT, VALUE_DOUBLE, VALUE_DATE FROM {$oldTableNameUf} WHERE FIELD_ID = {$oldId} "); } else { $this->connection->queryExecute(" INSERT INTO {$newTableNameUf} (VALUE_ID, FIELD_ID, VALUE, VALUE_INT, VALUE_DOUBLE, VALUE_DATE) SELECT obj.ID, {$id}, VALUE, VALUE_INT, VALUE_DOUBLE, VALUE_DATE FROM {$oldTableNameUf} INNER JOIN b_disk_object obj ON obj.{$externalColumn} = {$oldTableNameUf}.VALUE_ID WHERE FIELD_ID = {$oldId} "); } } } if($id && $enumValueInfos) { $obEnum = new CUserFieldEnum(); $res = $obEnum->SetEnumValues($id, $enumValueInfos); } if(!$id) { $this->log(array( 'Could not add userType', $arUserField )); } } if($columns) { if($isFolder) {//id section == id folders $this->connection->queryExecute(" INSERT INTO {$newTableNameSingleUf} (VALUE_ID, " . implode(',', $columns) . ") SELECT VALUE_ID, " . implode(',', $columns) . " FROM {$oldTableNameSingleUf} "); } else { $this->connection->queryExecute(" INSERT INTO {$newTableNameSingleUf} (VALUE_ID, " . implode(',', $columns) . ") SELECT obj.ID, " . implode(',', $columns) . " FROM {$oldTableNameSingleUf} INNER JOIN b_disk_object obj ON obj.{$externalColumn} = {$oldTableNameSingleUf}.VALUE_ID "); } } } protected function migrateCustomElementProperties($iblockId, $entityNewName) { $iblockId = (int)$iblockId; $VERSION = \CIBlockElement::GetIBVersion($iblockId); if($VERSION==2) { $strTable = "b_iblock_element_prop_m".$iblockId; } else { $strTable = "b_iblock_element_property"; } $tableNameUf = "b_utm_".strtolower($entityNewName); $tableNameSingleUf = "b_uts_".strtolower($entityNewName); $sqlHelper = $this->connection->getSqlHelper(); $listElementAll = array(); $objectQuery = $this->connection->query(" SELECT obj.ID, prop.VALUE, prop.IBLOCK_PROPERTY_ID FROM b_disk_object obj INNER JOIN {$strTable} prop ON obj.WEBDAV_ELEMENT_ID = prop.IBLOCK_ELEMENT_ID WHERE obj.WEBDAV_IBLOCK_ID = {$iblockId} AND obj.TYPE = 3 "); while($listObject = $objectQuery->fetch()) { $listElementAll[$listObject['ID']][$listObject['IBLOCK_PROPERTY_ID']]['FIELD_VALUE'][] = $listObject['VALUE']; } $listElement = array(); foreach($this->getIblockProperties($iblockId) as $prop) { $propId = $prop['ID']; $mappedUfType = $this->mapTypeElementPropertyToUfType($prop); if(!$mappedUfType) { $this->log(array( 'Unknown property of element', $prop, )); continue; } $userTypeEntity = new \CUserTypeEntity(); $symbolicName = empty($prop['CODE'])? $propId : strtoupper($prop['CODE']); $xmlId = empty($prop['CODE'])? $propId : $prop['CODE']; $fieldName = substr('UF_' . $symbolicName, 0, 20); if($mappedUfType == 'iblock_section' || $mappedUfType == 'iblock_element') { $settingsArray = array( 'IBLOCK_ID' => $prop['LINK_IBLOCK_ID'], 'DISPLAY' => 'LIST' ); } else { $settingsArray = array(); } $id = $userTypeEntity->add(array( 'ENTITY_ID' => $entityNewName, 'FIELD_NAME' => $fieldName, 'USER_TYPE_ID' => $mappedUfType, 'XML_ID' => 'PROPERTY_' . $xmlId, 'MULTIPLE' => $prop['MULTIPLE'], 'MANDATORY' => $prop['IS_REQUIRED'], 'SHOW_FILTER' => 'N', 'SHOW_IN_LIST' => null, 'EDIT_IN_LIST' => null, 'IS_SEARCHABLE' => $prop['SEARCHABLE'], 'SETTINGS' => $settingsArray, 'EDIT_FORM_LABEL' => array( 'en' => $prop['NAME'], 'ru' => $prop['NAME'], 'de' => $prop['NAME'], ) )); if($id) { if($mappedUfType == 'enumeration') { $i = 0; $enumValues = array(); $queryEnum = \CIBlockPropertyEnum::getlist(array("SORT" => "ASC", "VALUE" => "ASC"), array('PROPERTY_ID' => $propId)); while($queryEnum && $rowEnum = $queryEnum->fetch()) { $enumValues['n' . $i] = array( 'SORT' => $rowEnum['SORT'], 'VALUE' => $rowEnum['VALUE'], 'XML_ID' => $rowEnum['XML_ID'], 'DEF' => $rowEnum['DEF'], ); $i++; } $userTypeEnum = new \CUserFieldEnum(); $userTypeEnum->setEnumValues($id, $enumValues); } foreach($listElementAll as $newId => $propArray) { if(array_key_exists($propId, $propArray)) { $listElement[$newId][$propId]['FIELD_VALUE'] = $listElementAll[$newId][$propId]['FIELD_VALUE']; $listElement[$newId][$propId]['FIELD_NAME'] = $fieldName; if($prop['MULTIPLE'] == 'Y') { $listElement[$newId][$propId]['FIELD_ID'] = $id; $listElement[$newId][$propId]['PROPERTY_TYPE'] = $mappedUfType; } } } } } if(!empty($listElement)) { foreach($listElement as $newId => $propArray) { $fieldArray = array(); $valueArray = array(); foreach($propArray as $prop) { $fieldArray[] = $prop['FIELD_NAME']; if(count($prop['FIELD_VALUE']) > 1) { $valueArray[] = "'".$sqlHelper->forSql(serialize($prop['FIELD_VALUE']))."'"; foreach($prop['FIELD_VALUE'] as $utmValue) { if($prop['PROPERTY_TYPE'] == 'integer') { $utmValue = (int)$utmValue; $this->connection->queryExecute(" INSERT INTO {$tableNameUf} (VALUE_ID, FIELD_ID, VALUE_INT) VALUES ({$newId}, {$prop['FIELD_ID']}, {$utmValue}) "); } else { $utmValueStr = "'".$sqlHelper->forSql($utmValue)."'"; $this->connection->queryExecute(" INSERT INTO {$tableNameUf} (VALUE_ID, FIELD_ID, VALUE) VALUES ({$newId}, {$prop['FIELD_ID']}, {$utmValueStr}) "); } } } else { $valueArray[] = "'".$sqlHelper->forSql($prop['FIELD_VALUE'][0])."'"; } } if(!empty($fieldArray)) { if($this->isMysql) { $sql = " INSERT IGNORE INTO {$tableNameSingleUf} (VALUE_ID, " . implode(', ', $fieldArray) . ") VALUES ({$newId}, " . implode(', ', $valueArray) . ") "; } elseif($this->isOracle) { $sql = " INSERT INTO {$tableNameSingleUf} (VALUE_ID, " . implode(', ', $fieldArray) . ") SELECT {$newId}, " . implode(', ', $valueArray) . " FROM dual WHERE NOT EXISTS(SELECT 'x' FROM {$tableNameSingleUf} WHERE VALUE_ID = {$newId}) "; } elseif($this->isMssql) { $sql = " INSERT INTO {$tableNameSingleUf} (VALUE_ID, " . implode(', ', $fieldArray) . ") SELECT * FROM (SELECT {$newId}, " . implode(', ', $valueArray) . ") AS tmp WHERE NOT EXISTS(SELECT 'x' FROM {$tableNameSingleUf} WHERE VALUE_ID = {$newId}) "; } $this->connection->queryExecute($sql); } } } } protected function getIblockProperties($iblockId) { static $iblockProps = array(); if(isset($iblockProps[$iblockId])) { return $iblockProps[$iblockId]; } $iblockProps[$iblockId] = array(); $queryProps = \CIBlockProperty::GetList(array( "SORT" => "ASC", "NAME" => "ASC" ), array( "ACTIVE" => "Y", "IBLOCK_ID" => $iblockId )); $blackList = array( self::UF_DISK_FILE_ID => true, self::UF_DISK_FILE_STATUS => true, 'FORUM_TOPIC_ID' => true, 'FORUM_MESSAGE_CNT' => true, 'WEBDAV_VERSION' => true, 'WEBDAV_SIZE' => true, 'WEBDAV_INFO' => true, 'FILE' => true, ); while($prop = $queryProps->fetch()) { if(!empty($prop['CODE']) && isset($blackList[$prop['CODE']])) { continue; } $iblockProps[$iblockId][] = $prop; } return $iblockProps[$iblockId]; } protected function mapTypeElementPropertyToUfType(array $prop) { $prop['PROPERTY_TYPE'] = strtoupper($prop['PROPERTY_TYPE']); switch($prop['PROPERTY_TYPE']) { case 'N': return 'integer'; case 'S': return 'string'; case 'L': return 'enumeration'; case 'F': return 'file'; case 'G': return 'iblock_section'; case 'E': return 'iblock_element'; } return null; } protected function migrateMetaFolders() { if($this->isStepFinished(__METHOD__)) { return; } $sqlHelper = $this->connection->getSqlHelper(); $code = $sqlHelper->forSql(Folder::CODE_FOR_SAVED_FILES); $proxyType = $sqlHelper->forSql(Bitrix\Disk\ProxyType\User::className()); $names = array(); foreach($this->getNamesSavedSection() as $name) { $names[] = "'" . $sqlHelper->forSql($name) . "'"; } unset($name); if($this->isMysql) { $sql = " UPDATE b_disk_object obj INNER JOIN b_disk_storage s ON s.ROOT_OBJECT_ID = obj.PARENT_ID AND s.MODULE_ID = 'disk' AND s.ENTITY_TYPE = '{$proxyType}' SET obj.CODE = '{$code}' WHERE obj.NAME IN (" . implode(', ', $names) . ") "; } elseif($this->isOracle || $this->isMssql) { $sql = " UPDATE b_disk_object SET CODE = '{$code}' WHERE NAME IN (" . implode(', ', $names) . ") AND EXISTS (SELECT 'x' FROM b_disk_storage s WHERE s.ROOT_OBJECT_ID = PARENT_ID AND s.MODULE_ID = 'disk' AND s.ENTITY_TYPE = '{$proxyType}') "; } $this->connection->queryExecute($sql); $code = $sqlHelper->forSql(Folder::CODE_FOR_UPLOADED_FILES); $names = array(); foreach($this->getNamesDroppedSection() as $name) { $names[] = "'" . $sqlHelper->forSql($name) . "'"; } unset($name); $names[] = "'" . $sqlHelper->forSql('.Dropped') . "'"; Loc::loadLanguageFile($_SERVER['DOCUMENT_ROOT'] . '/bitrix/modules/disk/lib/storage.php'); $newNameDropped = $sqlHelper->forSql(Loc::getMessage('DISK_STORAGE_NAME_FOR_FOLDER_WITH_UPLOADED_FILES')); //in group we had .Dropped if($this->isMysql) { $sql = " UPDATE b_disk_object obj INNER JOIN b_disk_storage s ON s.ROOT_OBJECT_ID = obj.PARENT_ID AND s.MODULE_ID = 'disk' SET obj.CODE = '{$code}' WHERE obj.NAME IN (" . implode(', ', $names) . ") "; } elseif($this->isOracle || $this->isMssql) { $sql = " UPDATE b_disk_object SET CODE = '{$code}' WHERE NAME IN (" . implode(', ', $names) . ") AND EXISTS (SELECT 'x' FROM b_disk_storage s WHERE s.ROOT_OBJECT_ID = PARENT_ID AND s.MODULE_ID = 'disk') "; } $this->connection->queryExecute($sql); if($this->isMysql) { $sql = " UPDATE b_disk_object obj INNER JOIN b_disk_storage s ON s.ROOT_OBJECT_ID = obj.PARENT_ID AND s.MODULE_ID = 'disk' AND s.ENTITY_TYPE = '{$proxyType}' SET obj.NAME = '{$newNameDropped}_1' WHERE obj.NAME = '{$newNameDropped}' "; } elseif($this->isOracle || $this->isMssql) { $sql = " UPDATE b_disk_object SET NAME = '{$newNameDropped}_1' WHERE NAME = '{$newNameDropped}' AND EXISTS (SELECT 'x' FROM b_disk_storage s WHERE s.ROOT_OBJECT_ID = PARENT_ID AND s.MODULE_ID = 'disk' AND s.ENTITY_TYPE = '{$proxyType}') "; } $this->connection->queryExecute($sql); if($this->isMysql) { $sql = " UPDATE b_disk_object obj INNER JOIN b_disk_storage s ON s.ROOT_OBJECT_ID = obj.PARENT_ID AND s.MODULE_ID = 'disk' AND s.ENTITY_TYPE = '{$proxyType}' SET obj.NAME = '{$newNameDropped}' WHERE obj.NAME = '" . $sqlHelper->forSql('.Dropped') . "' AND obj.CODE = '{$code}' "; } elseif($this->isOracle || $this->isMssql) { $sql = " UPDATE b_disk_object SET NAME = '{$newNameDropped}' WHERE NAME = '" . $sqlHelper->forSql('.Dropped') . "' AND CODE = '{$code}' AND EXISTS (SELECT 'x' FROM b_disk_storage s WHERE s.ROOT_OBJECT_ID = PARENT_ID AND s.MODULE_ID = 'disk' AND s.ENTITY_TYPE = '{$proxyType}') "; } $this->connection->queryExecute($sql); $this->setStepFinished(__METHOD__); } protected function getLanguageList() { static $l = null; if($l !== null) { return $l; } $rsLanguage = CLanguage::GetList($by, $order, array()); while($arLanguage = $rsLanguage->fetch()) { $l[] = $arLanguage; } return $l; } protected function getNamesDroppedSection() { static $array = null; if($array !== null) { return $array; } $names = array(); foreach($this->getLanguageList() as $lang) { \Bitrix\Main\Localization\Loc::loadLanguageFile($_SERVER['DOCUMENT_ROOT'] . '/bitrix/modules/webdav/classes/general.php', $lang["LID"]); $names[$lang["LID"]] = \Bitrix\Main\Localization\Loc::getMessage('WD_DOWNLOADED', null, $lang["LID"]); } unset($lang); return $names; } protected function getNamesSavedSection() { static $array = null; if($array !== null) { return $array; } $names = array(); foreach($this->getLanguageList() as $lang) { \Bitrix\Main\Localization\Loc::loadLanguageFile($_SERVER['DOCUMENT_ROOT'] . '/bitrix/modules/webdav/classes/general.php', $lang["LID"]); $names[$lang["LID"]] = \Bitrix\Main\Localization\Loc::getMessage('WD_SAVED', null, $lang["LID"]); } unset($lang); return $names; } protected function moveUsers() { if($this->isStepFinished(__METHOD__)) { return; } $lastId = $this->getLastIblockId(); foreach($this->getIblockWithUserFiles() as $iblock) { if($lastId > $iblock['ID']) { continue; } $this->abortIfNeeded(); $this->moveUserStorageFromIblock($iblock); $this->storeIblockId($iblock['ID']); } unset($iblock); $this->storeIblockId(0); $this->setStepFinished(__METHOD__); } protected function moveGroup() { if($this->isStepFinished(__METHOD__)) { return; } $lastId = $this->getLastIblockId(); foreach($this->getIblockIdsWithGroupFiles() as $iblock) { if($lastId > $iblock['ID']) { continue; } $this->abortIfNeeded(); $this->moveGroupStorageFromIblock($iblock); $this->storeIblockId($iblock['ID']); } unset($iblock); $this->storeIblockId(0); $this->setStepFinished(__METHOD__); } private function processFinallyActions() { Option::set( 'disk', 'disk_revision_api', \Bitrix\Disk\Configuration::REVISION_API ); Option::set( 'disk', 'successfully_converted', 'Y' ); Option::set( 'disk', 'process_converted', false ); Option::set( 'webdav', 'successfully_converted', 'Y' ); Option::set( 'webdav', 'process_converted', false ); CAdminNotify::deleteByTag('disk_migrate_from_webdav'); UnRegisterModuleDependences("main", "OnBeforeProlog", "main", "", "", 99, "/modules/webdav/prolog_before.php"); // before statistics UnRegisterModuleDependences("search", "BeforeIndex", "webdav", "CRatingsComponentsWebDav", "BeforeIndex"); UnRegisterModuleDependences("main", "OnEventLogGetAuditTypes", "webdav", "CEventWebDav", "GetAuditTypes"); UnRegisterModuleDependences("main", "OnEventLogGetAuditHandlers", "webdav", "CEventWebDav", "MakeWebDavObject"); UnRegisterModuleDependences("bizproc", "OnAddToHistory", "webdav", "CIBlockDocumentWebdav", "OnAddToHistory"); UnRegisterModuleDependences("socialnetwork", "OnFillSocNetAllowedSubscribeEntityTypes", "webdav", "CWebDavSocNetEvent", "OnFillSocNetAllowedSubscribeEntityTypes"); UnRegisterModuleDependences("socialnetwork", "OnFillSocNetLogEvents", "webdav", "CWebDavSocNetEvent", "OnFillSocNetLogEvents"); UnRegisterModuleDependences("iblock", "OnAfterIBlockElementDelete", "webdav", "CIBlockDocumentWebdav", "OnAfterIBlockElementDelete"); UnRegisterModuleDependences('socialnetwork', 'OnSocNetFeaturesAdd', 'webdav', 'CIBlockWebdavSocnet', 'OnSocNetFeaturesAdd'); UnRegisterModuleDependences('socialnetwork', 'OnSocNetFeaturesUpdate', 'webdav', 'CIBlockWebdavSocnet', 'OnSocNetFeaturesUpdate'); UnRegisterModuleDependences('socialnetwork', 'OnSocNetFeatures', 'webdav', 'CIBlockWebdavSocnet', 'OnSocNetFeatures'); UnRegisterModuleDependences('socialnetwork', 'OnSocNetUserToGroupAdd', 'webdav', 'CIBlockWebdavSocnet', 'OnSocNetUserToGroupAdd'); UnRegisterModuleDependences('socialnetwork', 'OnSocNetUserToGroupUpdate', 'webdav', 'CIBlockWebdavSocnet', 'OnSocNetUserToGroupUpdate'); UnRegisterModuleDependences('socialnetwork', 'OnSocNetUserToGroupDelete', 'webdav', 'CIBlockWebdavSocnet', 'OnSocNetUserToGroupDelete'); UnRegisterModuleDependences('socialnetwork', 'OnSocNetGroupDelete', 'webdav', 'CIBlockWebdavSocnet', 'OnSocNetGroupDelete'); UnRegisterModuleDependences('socialnetwork', 'OnSocNetGroupAdd', 'webdav', 'CIBlockWebdavSocnet', 'OnSocNetGroupAdd'); UnRegisterModuleDependences('socialnetwork', 'OnSocNetGroupUpdate', 'webdav', 'CIBlockWebdavSocnet', 'OnSocNetGroupUpdate'); UnRegisterModuleDependences('socialnetwork', 'OnAfterSocNetLogCommentAdd', 'webdav', 'CIBlockWebdavSocnet', 'CopyCommentRights'); UnRegisterModuleDependences('main', 'OnUserTypeBuildList', 'webdav', 'CUserTypeWebdavElement', 'GetUserTypeDescription'); UnRegisterModuleDependences('main', 'OnUserTypeBuildList', 'webdav', 'CUserTypeWebdavElementHistory', 'GetUserTypeDescription'); UnRegisterModuleDependences('blog', 'OnPostAdd', 'webdav', 'CUserTypeWebdavElement', 'OnPostAdd'); UnRegisterModuleDependences('blog', 'OnPostUpdate', 'webdav', 'CUserTypeWebdavElement', 'OnPostUpdate'); UnRegisterModuleDependences('blog', 'OnBeforePostDelete', 'webdav', 'CUserTypeWebdavElement', 'OnBeforePostDelete'); UnRegisterModuleDependences("blog", "OnCommentAdd", 'webdav', 'CUserTypeWebdavElement', "OnCommentAdd"); UnRegisterModuleDependences("blog", "OnCommentUpdate", 'webdav', 'CUserTypeWebdavElement', "OnCommentUpdate"); UnRegisterModuleDependences("blog", "OnBeforeCommentDelete", 'webdav', 'CUserTypeWebdavElement', "OnBeforeCommentDelete"); UnRegisterModuleDependences("im", "OnBeforeConfirmNotify", "webdav", "CWebDavSymlinkHelper", "OnBeforeConfirmNotify"); CAgent::removeModuleAgents("webdav"); $this->registerHandlerToBlockIblock(); disk::RegisterModuleDependencies(true); } protected function registerHandlerToBlockIblock() { RegisterModuleDependences('iblock', 'OnBeforeIBlockElementAdd', 'webdav', 'CWebDavIblock', 'OnBeforeIBlockElementAdd'); RegisterModuleDependences('iblock', 'OnBeforeIBlockElementUpdate', 'webdav', 'CWebDavIblock', 'OnBeforeIBlockElementUpdate'); RegisterModuleDependences('iblock', 'OnBeforeIBlockElementDelete', 'webdav', 'CWebDavIblock', 'OnBeforeIBlockElementDelete'); RegisterModuleDependences('iblock', 'OnBeforeIBlockSectionAdd', 'webdav', 'CWebDavIblock', 'OnBeforeIBlockSectionAdd'); RegisterModuleDependences('iblock', 'OnBeforeIBlockSectionUpdate', 'webdav', 'CWebDavIblock', 'OnBeforeIBlockSectionUpdate'); RegisterModuleDependences('iblock', 'OnBeforeIBlockSectionDelete', 'webdav', 'CWebDavIblock', 'OnBeforeIBlockSectionDelete'); } private function moveCommonElements($storageId, $rootObjectId, $iblock) { $iblockId = $iblock['ID']; $sqlHelper = $this->connection->getSqlHelper(); if($iblock['VERSION'] == 2) { $props = $this->connection->query("SELECT * FROM b_iblock_property WHERE VERSION = 2 AND IBLOCK_ID = {$iblockId} AND CODE IN ('WEBDAV_SIZE', 'FILE', 'WEBDAV_VERSION')")->fetchAll(); $joinTable = 'b_iblock_element_prop_s' . $iblockId; $columnForFileId = $columnForSize = 'null'; $columnForVersion = '1'; foreach($props as $prop) { switch($prop['CODE']) { case 'WEBDAV_SIZE': $columnForSize = 'PROPERTY_' . $prop['ID']; break; case 'FILE': $columnForFileId = 'PROPERTY_' . $prop['ID']; break; case 'WEBDAV_VERSION': $columnForVersion = 'PROPERTY_' . $prop['ID']; break; } } unset($prop); if($this->isMysql) { $sql = " INSERT IGNORE INTO b_disk_object (FILE_ID, SIZE, GLOBAL_CONTENT_VERSION, NAME, TYPE, CODE, STORAGE_ID, PARENT_ID, CREATE_TIME, UPDATE_TIME, SYNC_UPDATE_TIME, CREATED_BY, UPDATED_BY, XML_ID, WEBDAV_ELEMENT_ID, WEBDAV_IBLOCK_ID) SELECT {$columnForFileId}, {$columnForSize}, {$columnForVersion}, child.NAME, 3, null, {$storageId}, " . $sqlHelper->getIsNullFunction('child.IBLOCK_SECTION_ID', $rootObjectId) . ", child.DATE_CREATE, " . $this->sqlHelper->getIsNullFunction('child.TIMESTAMP_X', 'child.DATE_CREATE') . ", " . $this->sqlHelper->getIsNullFunction('child.TIMESTAMP_X', 'child.DATE_CREATE') . ", " . $this->sqlHelper->getIsNullFunction('child.CREATED_BY', 0) . ", child.MODIFIED_BY, child.ID, child.ID, child.IBLOCK_ID FROM b_iblock_element child INNER JOIN {$joinTable} props ON props.IBLOCK_ELEMENT_ID = child.ID WHERE child.IBLOCK_ID = {$iblockId} AND child.IBLOCK_SECTION_ID IS NULL "; } elseif($this->isOracle || $this->isMssql) { $sql = " INSERT INTO b_disk_object (FILE_ID, " . $this->sqlHelper->quote('SIZE') . ", GLOBAL_CONTENT_VERSION, NAME, TYPE, CODE, STORAGE_ID, PARENT_ID, CREATE_TIME, UPDATE_TIME, SYNC_UPDATE_TIME, CREATED_BY, UPDATED_BY, XML_ID, WEBDAV_ELEMENT_ID, WEBDAV_IBLOCK_ID) SELECT {$columnForFileId}, {$columnForSize}, {$columnForVersion}, child.NAME, 3, null, {$storageId}, " . $sqlHelper->getIsNullFunction('child.IBLOCK_SECTION_ID', $rootObjectId) . ", child.DATE_CREATE, " . $this->sqlHelper->getIsNullFunction('child.TIMESTAMP_X', 'child.DATE_CREATE') . ", " . $this->sqlHelper->getIsNullFunction('child.TIMESTAMP_X', 'child.DATE_CREATE') . ", " . $this->sqlHelper->getIsNullFunction('child.CREATED_BY', 0) . ", child.MODIFIED_BY, child.ID, child.ID, child.IBLOCK_ID FROM b_iblock_element child INNER JOIN {$joinTable} props ON props.IBLOCK_ELEMENT_ID = child.ID WHERE child.IBLOCK_ID = {$iblockId} AND child.IBLOCK_SECTION_ID IS NULL AND NOT EXISTS(SELECT 'x' FROM b_disk_object WHERE NAME = child.NAME AND PARENT_ID = child.IBLOCK_SECTION_ID AND child.IBLOCK_SECTION_ID IS NOT NULL) "; } $this->connection->queryExecute($sql); $this->connection->queryExecute(" INSERT INTO b_disk_object (FILE_ID, " . $this->sqlHelper->quote('SIZE') . ", GLOBAL_CONTENT_VERSION, NAME, TYPE, CODE, STORAGE_ID, PARENT_ID, CREATE_TIME, UPDATE_TIME, SYNC_UPDATE_TIME, CREATED_BY, UPDATED_BY, XML_ID, WEBDAV_ELEMENT_ID, WEBDAV_IBLOCK_ID) SELECT {$columnForFileId}, {$columnForSize}, {$columnForVersion}, " . $this->getConcatFunction('child.ID', 'child.NAME') . ", 3, null, {$storageId}, " . $sqlHelper->getIsNullFunction('child.IBLOCK_SECTION_ID', $rootObjectId) . ", child.DATE_CREATE, " . $this->sqlHelper->getIsNullFunction('child.TIMESTAMP_X', 'child.DATE_CREATE') . ", " . $this->sqlHelper->getIsNullFunction('child.TIMESTAMP_X', 'child.DATE_CREATE') . ", " . $this->sqlHelper->getIsNullFunction('child.CREATED_BY', 0) . ", child.MODIFIED_BY, child.ID, child.ID, child.IBLOCK_ID FROM b_iblock_element child INNER JOIN {$joinTable} props ON props.IBLOCK_ELEMENT_ID = child.ID WHERE child.IBLOCK_ID = {$iblockId} AND child.IBLOCK_SECTION_ID IS NULL AND NOT EXISTS(SELECT 'x' FROM b_disk_object do WHERE do.WEBDAV_ELEMENT_ID=child.ID) "); } else { if($this->isMysql) { $sql = " INSERT IGNORE INTO b_disk_object (FILE_ID, SIZE, GLOBAL_CONTENT_VERSION, NAME, TYPE, CODE, STORAGE_ID, PARENT_ID, CREATE_TIME, UPDATE_TIME, SYNC_UPDATE_TIME, CREATED_BY, UPDATED_BY, XML_ID, WEBDAV_ELEMENT_ID, WEBDAV_IBLOCK_ID) SELECT PROP_FILE_EL.VALUE, PROP_SIZE_EL.VALUE, " . $sqlHelper->getIsNullFunction('PPROP_VERSION_G_EL.VALUE', 1) . ", child.NAME, 3, null, {$storageId}, " . $sqlHelper->getIsNullFunction('child.IBLOCK_SECTION_ID', $rootObjectId) . ", child.DATE_CREATE, " . $this->sqlHelper->getIsNullFunction('child.TIMESTAMP_X', 'child.DATE_CREATE') . ", " . $this->sqlHelper->getIsNullFunction('child.TIMESTAMP_X', 'child.DATE_CREATE') . ", " . $this->sqlHelper->getIsNullFunction('child.CREATED_BY', 0) . ", child.MODIFIED_BY, child.ID, child.ID, child.IBLOCK_ID FROM b_iblock_element child INNER JOIN b_iblock_property PROP_SIZE ON PROP_SIZE.IBLOCK_ID = child.IBLOCK_ID AND PROP_SIZE.CODE = 'WEBDAV_SIZE' INNER JOIN b_iblock_element_property PROP_SIZE_EL ON PROP_SIZE_EL.IBLOCK_PROPERTY_ID = PROP_SIZE.ID AND PROP_SIZE_EL.IBLOCK_ELEMENT_ID = child.ID INNER JOIN b_iblock_property PROP_FILE ON PROP_FILE.IBLOCK_ID = child.IBLOCK_ID AND PROP_FILE.CODE = 'FILE' INNER JOIN b_iblock_element_property PROP_FILE_EL ON PROP_FILE_EL.IBLOCK_PROPERTY_ID = PROP_FILE.ID AND PROP_FILE_EL.IBLOCK_ELEMENT_ID = child.ID LEFT JOIN b_iblock_property PROP_VERSION_G ON PROP_VERSION_G.IBLOCK_ID = child.IBLOCK_ID AND PROP_VERSION_G.CODE = 'WEBDAV_VERSION' LEFT JOIN b_iblock_element_property PPROP_VERSION_G_EL ON PPROP_VERSION_G_EL.IBLOCK_PROPERTY_ID = PROP_VERSION_G.ID AND PPROP_VERSION_G_EL.IBLOCK_ELEMENT_ID = child.ID WHERE child.IBLOCK_ID = {$iblockId} AND child.IBLOCK_SECTION_ID IS NULL "; } elseif($this->isOracle || $this->isMssql) { $sql = " INSERT INTO b_disk_object (FILE_ID, " . $this->sqlHelper->quote('SIZE') . ", GLOBAL_CONTENT_VERSION, NAME, TYPE, CODE, STORAGE_ID, PARENT_ID, CREATE_TIME, UPDATE_TIME, SYNC_UPDATE_TIME, CREATED_BY, UPDATED_BY, XML_ID, WEBDAV_ELEMENT_ID, WEBDAV_IBLOCK_ID) SELECT PROP_FILE_EL.VALUE, PROP_SIZE_EL.VALUE, " . $sqlHelper->getIsNullFunction('PPROP_VERSION_G_EL.VALUE', 1) . ", child.NAME, 3, null, {$storageId}, " . $sqlHelper->getIsNullFunction('child.IBLOCK_SECTION_ID', $rootObjectId) . ", child.DATE_CREATE, " . $this->sqlHelper->getIsNullFunction('child.TIMESTAMP_X', 'child.DATE_CREATE') . ", " . $this->sqlHelper->getIsNullFunction('child.TIMESTAMP_X', 'child.DATE_CREATE') . ", " . $this->sqlHelper->getIsNullFunction('child.CREATED_BY', 0) . ", child.MODIFIED_BY, child.ID, child.ID, child.IBLOCK_ID FROM b_iblock_element child INNER JOIN b_iblock_property PROP_SIZE ON PROP_SIZE.IBLOCK_ID = child.IBLOCK_ID AND PROP_SIZE.CODE = 'WEBDAV_SIZE' INNER JOIN b_iblock_element_property PROP_SIZE_EL ON PROP_SIZE_EL.IBLOCK_PROPERTY_ID = PROP_SIZE.ID AND PROP_SIZE_EL.IBLOCK_ELEMENT_ID = child.ID INNER JOIN b_iblock_property PROP_FILE ON PROP_FILE.IBLOCK_ID = child.IBLOCK_ID AND PROP_FILE.CODE = 'FILE' INNER JOIN b_iblock_element_property PROP_FILE_EL ON PROP_FILE_EL.IBLOCK_PROPERTY_ID = PROP_FILE.ID AND PROP_FILE_EL.IBLOCK_ELEMENT_ID = child.ID LEFT JOIN b_iblock_property PROP_VERSION_G ON PROP_VERSION_G.IBLOCK_ID = child.IBLOCK_ID AND PROP_VERSION_G.CODE = 'WEBDAV_VERSION' LEFT JOIN b_iblock_element_property PPROP_VERSION_G_EL ON PPROP_VERSION_G_EL.IBLOCK_PROPERTY_ID = PROP_VERSION_G.ID AND PPROP_VERSION_G_EL.IBLOCK_ELEMENT_ID = child.ID WHERE child.IBLOCK_ID = {$iblockId} AND child.IBLOCK_SECTION_ID IS NULL AND NOT EXISTS(SELECT 'x' FROM b_disk_object WHERE NAME = child.NAME AND PARENT_ID = child.IBLOCK_SECTION_ID AND child.IBLOCK_SECTION_ID IS NOT NULL) "; } $this->connection->queryExecute($sql); $this->connection->queryExecute(" INSERT INTO b_disk_object (FILE_ID, " . $this->sqlHelper->quote('SIZE') . ", GLOBAL_CONTENT_VERSION, NAME, TYPE, CODE, STORAGE_ID, PARENT_ID, CREATE_TIME, UPDATE_TIME, SYNC_UPDATE_TIME, CREATED_BY, UPDATED_BY, XML_ID, WEBDAV_ELEMENT_ID, WEBDAV_IBLOCK_ID) SELECT PROP_FILE_EL.VALUE, PROP_SIZE_EL.VALUE, " . $sqlHelper->getIsNullFunction('PPROP_VERSION_G_EL.VALUE', 1) . ", " . $this->getConcatFunction('child.ID', 'child.NAME') . ", 3, null, {$storageId}, " . $sqlHelper->getIsNullFunction('child.IBLOCK_SECTION_ID', $rootObjectId) . ", child.DATE_CREATE, " . $this->sqlHelper->getIsNullFunction('child.TIMESTAMP_X', 'child.DATE_CREATE') . ", " . $this->sqlHelper->getIsNullFunction('child.TIMESTAMP_X', 'child.DATE_CREATE') . ", " . $this->sqlHelper->getIsNullFunction('child.CREATED_BY', 0) . ", child.MODIFIED_BY, child.ID, child.ID, child.IBLOCK_ID FROM b_iblock_element child INNER JOIN b_iblock_property PROP_SIZE ON PROP_SIZE.IBLOCK_ID = child.IBLOCK_ID AND PROP_SIZE.CODE = 'WEBDAV_SIZE' INNER JOIN b_iblock_element_property PROP_SIZE_EL ON PROP_SIZE_EL.IBLOCK_PROPERTY_ID = PROP_SIZE.ID AND PROP_SIZE_EL.IBLOCK_ELEMENT_ID = child.ID INNER JOIN b_iblock_property PROP_FILE ON PROP_FILE.IBLOCK_ID = child.IBLOCK_ID AND PROP_FILE.CODE = 'FILE' INNER JOIN b_iblock_element_property PROP_FILE_EL ON PROP_FILE_EL.IBLOCK_PROPERTY_ID = PROP_FILE.ID AND PROP_FILE_EL.IBLOCK_ELEMENT_ID = child.ID LEFT JOIN b_iblock_property PROP_VERSION_G ON PROP_VERSION_G.IBLOCK_ID = child.IBLOCK_ID AND PROP_VERSION_G.CODE = 'WEBDAV_VERSION' LEFT JOIN b_iblock_element_property PPROP_VERSION_G_EL ON PPROP_VERSION_G_EL.IBLOCK_PROPERTY_ID = PROP_VERSION_G.ID AND PPROP_VERSION_G_EL.IBLOCK_ELEMENT_ID = child.ID WHERE child.IBLOCK_ID = {$iblockId} AND child.IBLOCK_SECTION_ID IS NULL AND NOT EXISTS(SELECT 'x' FROM b_disk_object do WHERE do.WEBDAV_ELEMENT_ID=child.ID) "); } } }