Server IP : 80.87.202.40 / Your IP : 216.73.216.169 Web Server : Apache System : Linux rospirotorg.ru 5.14.0-539.el9.x86_64 #1 SMP PREEMPT_DYNAMIC Thu Dec 5 22:26:13 UTC 2024 x86_64 User : bitrix ( 600) PHP Version : 8.2.27 Disable Function : NONE MySQL : OFF | cURL : ON | WGET : ON | Perl : ON | Python : OFF | Sudo : ON | Pkexec : ON Directory : /home/bitrix/ext_www/rospirotorg.ru/bitrix/modules/clouds/classes/general/ |
Upload File : |
<?php IncludeModuleLangFile(__FILE__); /** * @property int $ID * @property string $ACTIVE * @property int $SORT * @property string $READ_ONLY * @property string $SERVICE_ID * @property string $BUCKET * @property string $LOCATION * @property string $CNAME * @property int $FILE_COUNT * @property float $FILE_SIZE * @property int $LAST_FILE_ID * @property string $PREFIX * @property string $SETTINGS * @property string $FILE_RULES */ class CCloudStorageBucket { protected/*.int.*/$_ID = 0; protected/*.array[string]string.*/$arBucket; protected $enabledFailover = true; protected/*.CCloudStorageBucket.*/$failoverBucket; protected $queueFlag = true; /** @var CCloudStorageService $service */ protected/*.CCloudStorageService.*/ $service; protected static/*.array[int][string]string.*/$arBuckets; /** * @param int $ID * @param bool $enabledFailover */ public function __construct($ID, $enabledFailover = true) { $this->_ID = intval($ID); if (!$enabledFailover) { $this->disableFailOver(); } } public function disableFailOver() { $this->enabledFailover = false; } /** * @return bool */ public function isFailoverEnabled() { return $this->enabledFailover; } /** * @param bool $queueFlag */ public function setQueueFlag($queueFlag = true) { $this->queueFlag = (bool)$queueFlag; } /** * @return bool */ public function getQueueFlag() { return $this->queueFlag; } protected function GetActualBucketId() { if ( $this->isFailoverEnabled() && CCloudFailover::IsEnabled() && $this->FAILOVER_ACTIVE === 'Y' && $this->FAILOVER_BUCKET_ID > 0 ) { return $this->FAILOVER_BUCKET_ID; } else { return $this->ID; } } /** * @return array[string]string */ public function getBucketArray() { if (!isset($this->arBucket)) { self::_init(); $this->arBucket = self::$arBuckets[$this->_ID]; if ( $this->isFailoverEnabled() && CCloudFailover::IsEnabled() && $this->arBucket['FAILOVER_ACTIVE'] === 'Y' && $this->arBucket['FAILOVER_BUCKET_ID'] > 0 ) { $this->failoverBucket = new CCloudStorageBucket($this->FAILOVER_BUCKET_ID, false); if ($this->failoverBucket->Init()) { $this->arBucket['SERVICE_ID'] = $this->failoverBucket->SERVICE_ID; $this->arBucket['BUCKET'] = $this->failoverBucket->BUCKET; $this->arBucket['LOCATION'] = $this->failoverBucket->LOCATION; $this->arBucket['CNAME'] = $this->failoverBucket->CNAME; $this->arBucket['PREFIX'] = $this->failoverBucket->PREFIX; $this->arBucket['SETTINGS'] = $this->failoverBucket->SETTINGS; } else { $this->failoverBucket = null; } } } return $this->arBucket; } /** * @return CCloudStorageService */ public function getService() { return $this->service; } /** * @param string $str * @return string */ private static function CompileModuleRule($str) { $res = []; $ar = explode(',', $str); foreach ($ar as $s) { $s = trim($s); if ($s !== '') { $res[$s] = preg_quote($s, '/'); } } if (!empty($res)) { return '/^(' . implode('|', $res) . ')$/'; } else { return ''; } } /** * @param string $str * @return string */ private static function CompileExtentionRule($str) { $res = []; $ar = explode(',', $str); foreach ($ar as $s) { $s = trim($s); if ($s !== '') { $res[$s] = preg_quote('.' . $s, '/'); } } if (!empty($res)) { return '/(' . implode('|', $res) . ')$/i'; } else { return ''; } } /** * @param string $str * @return float */ private static function ParseSize($str) { static $scale = [ '' => 1.0, 'K' => 1024.0, 'M' => 1048576.0, 'G' => 1073741824.0, ]; $str = mb_strtoupper(trim($str)); if ($str !== '' && preg_match('/([0-9.]+)(|K|M|G)$/', $str, $match) > 0) { return doubleval($match[1]) * $scale[$match[2]]; } else { return 0.0; } } /** * @param string $str * @return array[int][int]double */ private static function CompileSizeRule($str) { $res = /*.(array[int][int]double).*/[]; $ar = explode(',', $str); foreach ($ar as $s) { $s = trim($s); if ($s !== '') { $arSize = explode('-', $s); if (count($arSize) == 1) { $res[] = [self::ParseSize($arSize[0]), self::ParseSize($arSize[0])]; } else { $res[] = [self::ParseSize($arSize[0]), self::ParseSize($arSize[1])]; } } } return $res; } /** * @param array[int][string]string $arRules * @return array[int][string]string */ private static function CompileRules($arRules) { $arCompiled = /*.(array[int][string]string).*/[]; if (is_array($arRules)) { foreach ($arRules as $rule) { if (is_array($rule)) { $arCompiled[] = [ 'MODULE_MASK' => isset($rule['MODULE']) ? self::CompileModuleRule($rule['MODULE']) : '', 'EXTENTION_MASK' => isset($rule['EXTENSION']) ? self::CompileExtentionRule($rule['EXTENSION']) : '', 'SIZE_ARRAY' => isset($rule['SIZE']) ? self::CompileSizeRule($rule['SIZE']) : '', ]; } } } return $arCompiled; } /** * @return void */ private static function _init() { global $DB, $CACHE_MANAGER; if (isset(self::$arBuckets)) { return; } $cache_id = 'cloud_buckets_v2'; if ( CACHED_b_clouds_file_bucket !== false && $CACHE_MANAGER->Read(CACHED_b_clouds_file_bucket, $cache_id, 'b_clouds_file_bucket') ) { self::$arBuckets = $CACHE_MANAGER->Get($cache_id); } else { self::$arBuckets = /*.(array[int]CCloudStorageBucket).*/[]; $rs = $DB->Query(' SELECT * FROM b_clouds_file_bucket ORDER BY SORT DESC, ID ASC '); while (is_array($ar = $rs->Fetch())) { if ($ar['FILE_RULES'] != '') { $arRules = unserialize($ar['FILE_RULES'], ['allowed_classes' => false]); } else { $arRules = []; } $ar['FILE_RULES_COMPILED'] = self::CompileRules($arRules); if ($ar['SETTINGS'] != '') { $arSettings = unserialize($ar['SETTINGS'], ['allowed_classes' => false]); } else { $arSettings = []; } if (is_array($arSettings)) { $ar['SETTINGS'] = $arSettings; } else { $ar['SETTINGS'] = []; } self::$arBuckets[intval($ar['ID'])] = $ar; } if (CACHED_b_clouds_file_bucket !== false) { $CACHE_MANAGER->Set($cache_id, self::$arBuckets); } } } /** * @param string $name * @return mixed */ public function __get($name) { $arBucket = $this->getBucketArray(); if ($arBucket && array_key_exists($name, $arBucket)) { return $arBucket[$name]; } else { return null; } } /** * @return bool */ public function Init() { if (is_object($this->service)) { return true; } else { if ($this->SERVICE_ID) { $this->service = CCloudStorage::GetServiceByID($this->SERVICE_ID); } return is_object($this->service); } } /** * @return bool */ public function RenewToken() { if ($this->service->tokenHasExpired) { $arBucket = $this->failoverBucket ? $this->failoverBucket->arBucket : $this->arBucket; $newSettings = false; foreach (GetModuleEvents('clouds', 'OnExpiredToken', true) as $arEvent) { $newSettings = ExecuteModuleEventEx($arEvent, [$arBucket]); if ($newSettings) { break; } } if ($newSettings) { if ($this->failoverBucket) { $updateResult = $this->failoverBucket->Update(['SETTINGS' => $newSettings]); $this->arBucket = null; } else { $updateResult = $this->Update(['SETTINGS' => $newSettings]); } if ($updateResult) { $this->service->tokenHasExpired = false; return true; } } } return false; } /** * @param array[string]string $arSettings * @return bool */ public function CheckSettings(&$arSettings) { return $this->service->CheckSettings($this->arBucket, $arSettings); } /** * @return bool */ public function CreateBucket() { return $this->service->CreateBucket($this->arBucket); } /** * @param mixed $arFile * @param bool $encoded * @return string */ public function GetFileSRC($arFile, $encoded = true) { if (is_array($arFile) && isset($arFile['URN'])) { return $this->service->GetFileSRC($this->arBucket, $arFile['URN'], $encoded); } else { return preg_replace("'(?<!:)/+'s", '/', $this->service->GetFileSRC($this->arBucket, $arFile, $encoded)); } } /** * @param string $filePath * @return bool */ public function FileExists($filePath) { $result = $this->service->FileExists($this->arBucket, $filePath); if (!$result && $this->RenewToken()) { $result = $this->service->FileExists($this->getBucketArray(), $filePath); } return $result; } /** * @param mixed $arFile * @param string $filePath * @return bool */ public function DownloadToFile($arFile, $filePath) { $result = $this->service->DownloadToFile($this->arBucket, $arFile, $filePath); return $result; } /** * @param string $filePath * @param mixed $arFile * @return bool */ public function SaveFile($filePath, $arFile) { $result = $this->service->SaveFile($this->arBucket, $filePath, $arFile); if (!$result && $this->RenewToken()) { $result = $this->service->SaveFile($this->getBucketArray(), $filePath, $arFile); } if ($result) { if ($this->queueFlag) { CCloudFailover::queueCopy($this, $filePath); } foreach (GetModuleEvents('clouds', 'OnAfterSaveFile', true) as $arEvent) { ExecuteModuleEventEx($arEvent, [$this, $arFile, $filePath]); } } return $result; } /** * @param string $filePath * @return bool */ public function DeleteFile($filePath, $fileSize = null) { $result = $this->service->DeleteFile($this->arBucket, $filePath); if (!$result && $this->RenewToken()) { $result = $this->service->DeleteFile($this->getBucketArray(), $filePath); } if ($result) { if ($this->queueFlag) { CCloudFailover::queueDelete($this, $filePath); } $eventData = [ 'del' => 'Y', 'size' => $fileSize, ]; foreach (GetModuleEvents('clouds', 'OnAfterDeleteFile', true) as $arEvent) { ExecuteModuleEventEx($arEvent, [$this, $eventData, $filePath]); } } return $result; } /** * @param mixed $arFile * @param string $filePath * @return bool */ public function FileCopy($arFile, $filePath) { $result = $this->service->FileCopy($this->arBucket, $arFile, $filePath); if (!$result && $this->RenewToken()) { $result = $this->service->FileCopy($this->getBucketArray(), $arFile, $filePath); } if ($result) { if ($this->queueFlag) { CCloudFailover::queueCopy($this, $filePath); } foreach (GetModuleEvents('clouds', 'OnAfterCopyFile', true) as $arEvent) { ExecuteModuleEventEx($arEvent, [$this, $arFile, $filePath]); } } return $result; } /** * @param string $sourcePath * @param string $targetPath * @param bool $overwrite * @return bool */ public function FileRename($sourcePath, $targetPath, $overwrite = true) { $result = $this->service->FileRename($this->arBucket, $sourcePath, $targetPath, $overwrite); if ($result) { if ($this->queueFlag) { CCloudFailover::queueRename($this, $sourcePath, $targetPath); } foreach (GetModuleEvents('clouds', 'OnAfterRenameFile', true) as $arEvent) { ExecuteModuleEventEx($arEvent, [$this, $sourcePath, $targetPath]); } } return $result; } /** * @param string $filePath * @param bool $bRecursive * @param int $pageSize * @param string $pageMarker * @return array[string][int]string */ public function ListFiles($filePath = '/', $bRecursive = false, $pageSize = 0, $pageMarker = '') { $result = $this->service->ListFiles($this->arBucket, $filePath, $bRecursive, $pageSize, $pageMarker); if (!$result && $this->RenewToken()) { $result = $this->service->ListFiles($this->getBucketArray(), $filePath, $bRecursive, $pageSize, $pageMarker); } return $result; } /** * @param string $filePath * @return array|false */ public function GetFileInfo($filePath) { $DIR_NAME = mb_substr($filePath, 0, mb_strrpos($filePath, '/') + 1); $FILE_NAME = mb_substr($filePath, mb_strlen($DIR_NAME)); $arFileInfo = $this->service->GetFileInfo($this->arBucket, $filePath); if ($arFileInfo === false && $this->RenewToken()) { $arFileInfo = $this->service->GetFileInfo($this->getBucketArray(), $filePath); } if ($arFileInfo === null) { $arListing = $this->service->ListFiles($this->arBucket, $DIR_NAME, false); if (is_array($arListing)) { foreach ($arListing['file'] as $i => $name) { if ($name === $FILE_NAME) { return [ 'name' => $name, 'size' => $arListing['file_size'][$i], 'mtime' => $arListing['file_mtime'][$i], 'hash' => $arListing['file_hash'][$i], ]; } } } } elseif ($arFileInfo) { $arFileInfo['name'] = $FILE_NAME; return $arFileInfo; } return false; } /** * @param string $filePath * @return float */ public function GetFileSize($filePath) { $fileInfo = $this->GetFileInfo($filePath); if ($fileInfo) { return doubleval($fileInfo['size']); } else { return 0.0; } } /** * @return array[int][string]string */ public static function GetAllBuckets() { self::_init(); return self::$arBuckets; } /** * @param array[string]string $arFields * @param int $ID * @return bool */ public function CheckFields(&$arFields, $ID) { global $APPLICATION; $aMsg = []; if (array_key_exists('ACTIVE', $arFields)) { $arFields['ACTIVE'] = $arFields['ACTIVE'] === 'N' ? 'N' : 'Y'; } if (array_key_exists('READ_ONLY', $arFields)) { $arFields['READ_ONLY'] = $arFields['READ_ONLY'] === 'Y' ? 'Y' : 'N'; } $arServices = CCloudStorage::GetServiceList(); if (isset($arFields['SERVICE_ID'])) { if (!array_key_exists($arFields['SERVICE_ID'], $arServices)) { $aMsg[] = ['id' => 'SERVICE_ID', 'text' => GetMessage('CLO_STORAGE_WRONG_SERVICE')]; } } if (isset($arFields['BUCKET'])) { $arFields['BUCKET'] = trim($arFields['BUCKET']); $bBadLength = false; if (mb_strpos($arFields['BUCKET'], '.') !== false) { $arName = explode('.', $arFields['BUCKET']); $bBadLength = false; foreach ($arName as $str) { if (mb_strlen($str) < 2 || mb_strlen($str) > 63) { $bBadLength = true; } } } if ($arFields['BUCKET'] == '') { $aMsg[] = ['id' => 'BUCKET', 'text' => GetMessage('CLO_STORAGE_EMPTY_BUCKET')]; } if (preg_match('/[^a-z0-9._-]/', $arFields['BUCKET']) > 0) { $aMsg[] = ['id' => 'BUCKET', 'text' => GetMessage('CLO_STORAGE_BAD_BUCKET_NAME')]; } if (mb_strlen($arFields['BUCKET']) < 2 || mb_strlen($arFields['BUCKET']) > 63) { $aMsg[] = ['id' => 'BUCKET', 'text' => GetMessage('CLO_STORAGE_WRONG_BUCKET_NAME_LENGTH')]; } if ($bBadLength) { $aMsg[] = ['id' => 'BUCKET', 'text' => GetMessage('CLO_STORAGE_WRONG_BUCKET_NAME_LENGTH2')]; } if (!preg_match('/^[a-z0-9].*[a-z0-9]$/', $arFields['BUCKET'])) { $aMsg[] = ['id' => 'BUCKET', 'text' => GetMessage('CLO_STORAGE_BAD_BUCKET_NAME2')]; } if (preg_match('/(-\\.|\\.-)/', $arFields['BUCKET']) > 0) { $aMsg[] = ['id' => 'BUCKET', 'text' => GetMessage('CLO_STORAGE_BAD_BUCKET_NAME3')]; } if ($arFields['BUCKET'] <> '') { $rsBucket = self::GetList([], [ '=SERVICE_ID' => $arFields['SERVICE_ID'], '=BUCKET' => $arFields['BUCKET'], ]); $arBucket = $rsBucket->Fetch(); if (is_array($arBucket) && $arBucket['ID'] != $ID) { $aMsg[] = ['id' => 'BUCKET', 'text' => GetMessage('CLO_STORAGE_BUCKET_ALREADY_EXISTS')]; } } } if (array_key_exists('FAILOVER_ACTIVE', $arFields)) { $arFields['FAILOVER_ACTIVE'] = $arFields['FAILOVER_ACTIVE'] === 'Y' ? 'Y' : 'N'; } if (isset($arFields['FAILOVER_BUCKET_ID']) && $arFields['FAILOVER_BUCKET_ID'] == $ID) { unset($arFields['FAILOVER_BUCKET_ID']); } if (array_key_exists('FAILOVER_COPY', $arFields)) { $arFields['FAILOVER_COPY'] = $arFields['FAILOVER_COPY'] === 'Y' ? 'Y' : 'N'; } if (array_key_exists('FAILOVER_DELETE', $arFields)) { $arFields['FAILOVER_DELETE'] = $arFields['FAILOVER_DELETE'] === 'Y' ? 'Y' : 'N'; } if (array_key_exists('FAILOVER_DELETE_DELAY', $arFields)) { $arFields['FAILOVER_DELETE_DELAY'] = (int)$arFields['FAILOVER_DELETE_DELAY']; } if (array_key_exists('CNAME', $arFields)) { $arFields['CNAME'] = preg_replace('#^https?://#i', '', $arFields['CNAME']); } if (!empty($aMsg)) { $e = new CAdminException($aMsg); $APPLICATION->ThrowException($e); return false; } return true; } /** * @param array[string]string $arOrder * @param array[string]string $arFilter * @param array[string]string $arSelect * @return CDBResult */ public static function GetList($arOrder=[], $arFilter=[], $arSelect=[]) { global $DB; if (!is_array($arSelect)) { $arSelect = /*.(array[string]string).*/[]; } if (count($arSelect) < 1) { $arSelect = [ 'ID', 'ACTIVE', 'READ_ONLY', 'SORT', 'SERVICE_ID', 'LOCATION', 'BUCKET', 'SETTINGS', 'CNAME', 'PREFIX', 'FILE_COUNT', 'FILE_SIZE', 'LAST_FILE_ID', 'FILE_RULES', 'FAILOVER_ACTIVE', 'FAILOVER_BUCKET_ID', 'FAILOVER_COPY', 'FAILOVER_DELETE', 'FAILOVER_DELETE_DELAY', ]; } if (!is_array($arOrder)) { $arOrder = /*.(array[string]string).*/[]; } $arQueryOrder = []; foreach ($arOrder as $strColumn => $strDirection) { $strColumn = mb_strtoupper($strColumn); $strDirection = mb_strtoupper($strDirection) === 'ASC' ? 'ASC' : 'DESC'; switch ($strColumn) { case 'ID': case 'SORT': $arSelect[] = $strColumn; $arQueryOrder[$strColumn] = $strColumn . ' ' . $strDirection; break; default: break; } } $arQuerySelect = []; foreach ($arSelect as $strColumn) { $strColumn = mb_strtoupper($strColumn); switch ($strColumn) { case 'ID': case 'ACTIVE': case 'READ_ONLY': case 'SORT': case 'SERVICE_ID': case 'LOCATION': case 'BUCKET': case 'SETTINGS': case 'CNAME': case 'PREFIX': case 'FILE_COUNT': case 'FILE_SIZE': case 'LAST_FILE_ID': case 'FILE_RULES': case 'FAILOVER_ACTIVE': case 'FAILOVER_BUCKET_ID': case 'FAILOVER_COPY': case 'FAILOVER_DELETE': case 'FAILOVER_DELETE_DELAY': $arQuerySelect[$strColumn] = 's.' . $strColumn; break; } } if (count($arQuerySelect) < 1) { $arQuerySelect = ['ID' => 's.ID']; } $obQueryWhere = new CSQLWhere; $arFields = [ 'ID' => [ 'TABLE_ALIAS' => 's', 'FIELD_NAME' => 's.ID', 'FIELD_TYPE' => 'int', ], 'ACTIVE' => [ 'TABLE_ALIAS' => 's', 'FIELD_NAME' => 's.ACTIVE', 'FIELD_TYPE' => 'string', ], 'READ_ONLY' => [ 'TABLE_ALIAS' => 's', 'FIELD_NAME' => 's.READ_ONLY', 'FIELD_TYPE' => 'string', ], 'SERVICE_ID' => [ 'TABLE_ALIAS' => 's', 'FIELD_NAME' => 's.SERVICE_ID', 'FIELD_TYPE' => 'string', ], 'BUCKET' => [ 'TABLE_ALIAS' => 's', 'FIELD_NAME' => 's.BUCKET', 'FIELD_TYPE' => 'string', ], 'FAILOVER_ACTIVE' => [ 'TABLE_ALIAS' => 's', 'FIELD_NAME' => 's.FAILOVER_ACTIVE', 'FIELD_TYPE' => 'string', ], 'FAILOVER_BUCKET_ID' => [ 'TABLE_ALIAS' => 's', 'FIELD_NAME' => 's.FAILOVER_BUCKET_ID', 'FIELD_TYPE' => 'int', ], 'FAILOVER_COPY' => [ 'TABLE_ALIAS' => 's', 'FIELD_NAME' => 's.FAILOVER_COPY', 'FIELD_TYPE' => 'string', ], 'FAILOVER_DELETE' => [ 'TABLE_ALIAS' => 's', 'FIELD_NAME' => 's.FAILOVER_DELETE', 'FIELD_TYPE' => 'string', ], 'FAILOVER_DELETE_DELAY' => [ 'TABLE_ALIAS' => 's', 'FIELD_NAME' => 's.FAILOVER_DELETE_DELAY', 'FIELD_TYPE' => 'int', ], ]; $obQueryWhere->SetFields($arFields); if (!is_array($arFilter)) { $arFilter = /*.(array[string]string).*/[]; } $strQueryWhere = $obQueryWhere->GetQuery($arFilter); $bDistinct = $obQueryWhere->bDistinctReqired; $strSql = ' SELECT ' . ($bDistinct ? 'DISTINCT' : '') . ' ' . implode(', ', $arQuerySelect) . ' FROM b_clouds_file_bucket s ' . $obQueryWhere->GetJoins() . ' '; if ($strQueryWhere !== '') { $strSql .= ' WHERE ' . $strQueryWhere . ' '; } if (count($arQueryOrder) > 0) { $strSql .= ' ORDER BY ' . implode(', ', $arQueryOrder) . ' '; } return $DB->Query($strSql); } /** * @param array[string]string $arFields * @param bool $createBucket * @return mixed */ public function Add($arFields, $createBucket = true) { global $DB, $APPLICATION, $CACHE_MANAGER; $strError = ''; $this->_ID = 0; if (!$this->CheckFields($arFields, 0)) { return false; } $arFields['FILE_COUNT'] = 0; if (is_array($arFields['FILE_RULES'])) { $arFields['FILE_RULES'] = serialize($arFields['FILE_RULES']); } else { $arFields['FILE_RULES'] = false; } $this->arBucket = $arFields; if ($this->Init()) { if (!$this->CheckSettings($arFields['SETTINGS'])) { return false; } $this->arBucket['SETTINGS'] = $arFields['SETTINGS']; if ($createBucket) { $creationResult = $this->CreateBucket(); } else { $creationResult = true; } if ($creationResult) { $arFields['SETTINGS'] = serialize($arFields['SETTINGS']); $this->_ID = $DB->Add('b_clouds_file_bucket', $arFields); self::$arBuckets = null; $this->arBucket = null; if (CACHED_b_clouds_file_bucket !== false) { $CACHE_MANAGER->CleanDir('b_clouds_file_bucket'); } return $this->_ID; } else { $e = $APPLICATION->GetException(); if (is_object($e)) { $strError = GetMessage('CLO_STORAGE_CLOUD_ADD_ERROR', ['#error_msg#' => $e->GetString()]); } else { $strError = GetMessage('CLO_STORAGE_CLOUD_ADD_ERROR', ['#error_msg#' => 'CSB42343']); } } } else { $strError = GetMessage('CLO_STORAGE_CLOUD_ADD_ERROR', ['#error_msg#' => GetMessage('CLO_STORAGE_UNKNOWN_SERVICE')]); } $APPLICATION->ResetException(); $e = new CApplicationException($strError); $APPLICATION->ThrowException($e); return false; } /** * @return bool */ public function Delete() { global $DB, $APPLICATION, $CACHE_MANAGER; $strError = ''; if ($this->Init()) { $isEmptyBucket = $this->service->IsEmptyBucket($this->arBucket); $forceDeleteTry = false; if (!$isEmptyBucket && is_object($APPLICATION->GetException())) { // The bucket was created within wrong s3 region if ( $this->service->GetLastRequestStatus() == 301 && $this->service->GetLastRequestHeader('x-amz-bucket-region') !== '' ) { $forceDeleteTry = true; } } if ($isEmptyBucket || $forceDeleteTry) { $isDeleted = $this->service->DeleteBucket($this->arBucket); $forceDelete = false; if (!$isDeleted && is_object($APPLICATION->GetException())) { // The bucket was created within wrong s3 region if ( $this->service->GetLastRequestStatus() == 301 && $this->service->GetLastRequestHeader('x-amz-bucket-region') !== '' ) { $forceDelete = true; } } if ($isDeleted || $forceDelete) { $res = $DB->Query('DELETE FROM b_clouds_file_bucket WHERE ID = ' . $this->_ID); if (CACHED_b_clouds_file_bucket !== false) { $CACHE_MANAGER->CleanDir('b_clouds_file_bucket'); } if (is_object($res)) { $this->arBucket = null; $this->_ID = 0; return true; } else { $strError = GetMessage('CLO_STORAGE_DB_DELETE_ERROR'); } } else { $e = $APPLICATION->GetException(); $strError = GetMessage('CLO_STORAGE_CLOUD_DELETE_ERROR', ['#error_msg#' => is_object($e) ? $e->GetString() : '']); } } else { $e = $APPLICATION->GetException(); if (is_object($e)) { $strError = GetMessage('CLO_STORAGE_CLOUD_DELETE_ERROR', ['#error_msg#' => $e->GetString()]); } else { $strError = GetMessage('CLO_STORAGE_CLOUD_BUCKET_NOT_EMPTY'); } } } else { $strError = GetMessage('CLO_STORAGE_CLOUD_DELETE_ERROR', ['#error_msg#' => GetMessage('CLO_STORAGE_UNKNOWN_SERVICE')]); } $APPLICATION->ResetException(); $e = new CApplicationException($strError); $APPLICATION->ThrowException($e); return false; } /** * @param array[string]string $arFields * @return mixed */ public function Update($arFields) { global $DB, $CACHE_MANAGER; if ($this->_ID <= 0) { return false; } unset($arFields['FILE_COUNT']); unset($arFields['SERVICE_ID']); unset($arFields['LOCATION']); unset($arFields['BUCKET']); if ( array_key_exists('SETTINGS', $arFields) && is_array($arFields['SETTINGS']) && isset($arFields['SETTINGS']['MIGRATE_TO']) && $arFields['SETTINGS']['MIGRATE_TO'] ) { $this->SERVICE_ID = $arFields['SERVICE_ID'] = $arFields['SETTINGS']['MIGRATE_TO']; } $this->service = CCloudStorage::GetServiceByID($this->SERVICE_ID); if (!is_object($this->service)) { return false; } if (!$this->CheckFields($arFields, $this->_ID)) { return false; } if (array_key_exists('FILE_RULES', $arFields)) { if (is_array($arFields['FILE_RULES'])) { $arFields['FILE_RULES'] = serialize($arFields['FILE_RULES']); } else { $arFields['FILE_RULES'] = false; } } if (array_key_exists('SETTINGS', $arFields)) { if (!$this->CheckSettings($arFields['SETTINGS'])) { return false; } $arFields['SETTINGS'] = serialize($arFields['SETTINGS']); } $strUpdate = $DB->PrepareUpdate('b_clouds_file_bucket', $arFields); if ($strUpdate <> '') { $strSql = ' UPDATE b_clouds_file_bucket SET ' . $strUpdate . ' WHERE ID = ' . $this->_ID . ' '; if (!is_object($DB->Query($strSql))) { return false; } } self::$arBuckets = null; $this->arBucket = null; if (CACHED_b_clouds_file_bucket !== false) { $CACHE_MANAGER->CleanDir('b_clouds_file_bucket'); } return $this->_ID; } /** * @param array[string][int]string $arPOST * @return array[int][string]string */ public static function ConvertPOST($arPOST) { $arRules = /*.(array[int][string]string).*/[]; if (isset($arPOST['MODULE']) && is_array($arPOST['MODULE'])) { foreach ($arPOST['MODULE'] as $i => $MODULE) { if (!isset($arRules[intval($i)])) { $arRules[intval($i)] = ['MODULE' => '', 'EXTENSION' => '', 'SIZE' => '']; } $arRules[intval($i)]['MODULE'] = $MODULE; } } if (isset($arPOST['EXTENSION']) && is_array($arPOST['EXTENSION'])) { foreach ($arPOST['EXTENSION'] as $i => $EXTENSION) { if (!isset($arRules[intval($i)])) { $arRules[intval($i)] = ['MODULE' => '', 'EXTENSION' => '', 'SIZE' => '']; } $arRules[intval($i)]['EXTENSION'] = $EXTENSION; } } if (isset($arPOST['SIZE']) && is_array($arPOST['SIZE'])) { foreach ($arPOST['SIZE'] as $i => $SIZE) { if (!isset($arRules[intval($i)])) { $arRules[intval($i)] = ['MODULE' => '', 'EXTENSION' => '', 'SIZE' => '']; } $arRules[intval($i)]['SIZE'] = $SIZE; } } return $arRules; } /** * @param string $name * @param string $value * @return void */ public function setHeader($name, $value) { $this->service->SetHeader($name, $value); } /** * @param float $file_size * @param int $file_count * @return CDBResult */ public function SetFileCounter($file_size, $file_count) { global $DB, $CACHE_MANAGER; $res = $DB->Query(' UPDATE b_clouds_file_bucket SET FILE_COUNT = ' . intval($file_count) . ' ,FILE_SIZE = ' . roundDB($file_size) . ' WHERE ID = ' . $this->GetActualBucketId() . ' '); if (CACHED_b_clouds_file_bucket !== false) { $CACHE_MANAGER->CleanDir('b_clouds_file_bucket'); } return $res; } protected static $applyFileCounterJobAdded = false; /** * @param float $file_size * @return CDBResult */ public function IncFileCounter($file_size = 0.0) { global $DB; $res = $DB->Query(' INSERT INTO b_clouds_size_queue (BUCKET_ID, FILE_COUNT, FILE_SIZE) VALUES (' . $this->GetActualBucketId() . ', 1, ' . roundDB($file_size) . ') '); if (defined('BX_CLOUDS_COUNTERS_DEBUG')) { \CCloudsDebug::getInstance()->endAction(); } if (!static::$applyFileCounterJobAdded) { static::$applyFileCounterJobAdded = true; \Bitrix\Main\Application::getInstance()->addBackgroundJob([__CLASS__, 'ApplyFileCounter'], [], \Bitrix\Main\Application::JOB_PRIORITY_NORMAL); } return $res; } /** * @param float $file_size * @return CDBResult */ public function DecFileCounter($file_size = 0.0) { global $DB; $res = $DB->Query(' INSERT INTO b_clouds_size_queue (BUCKET_ID, FILE_COUNT, FILE_SIZE) VALUES (' . $this->GetActualBucketId() . ', -1, ' . roundDB($file_size) . ') '); if (defined('BX_CLOUDS_COUNTERS_DEBUG')) { \CCloudsDebug::getInstance()->endAction(); } if (!static::$applyFileCounterJobAdded) { static::$applyFileCounterJobAdded = true; \Bitrix\Main\Application::getInstance()->addBackgroundJob([__CLASS__, 'ApplyFileCounter'], [], \Bitrix\Main\Application::JOB_PRIORITY_NORMAL); } return $res; } /** * @return void */ public static function ApplyFileCounter() { global $DB, $CACHE_MANAGER; $connection = \Bitrix\Main\Application::getConnection(); if ($connection->lock('CCloudStorageBucket::ApplyFileCounter')) { $res = $DB->Query('SELECT * FROM b_clouds_size_queue ORDER BY ID'); $c = 0; while ($job = $res->Fetch()) { if ($job['FILE_COUNT'] > 0) { $DB->Query(' UPDATE b_clouds_file_bucket SET FILE_COUNT = FILE_COUNT + 1 ,FILE_SIZE = FILE_SIZE + ' . $job['FILE_SIZE'] . ' WHERE ID = ' . $job['BUCKET_ID'] . ' '); $c++; COption::SetOptionString('main_size', '~cloud', intval(COption::GetOptionString('main_size', '~cloud')) + $job['FILE_SIZE']); } elseif ($job['FILE_COUNT'] < 0) { $DB->Query(' UPDATE b_clouds_file_bucket SET FILE_COUNT = case when FILE_COUNT - 1 > 0 then FILE_COUNT - 1 else 0 end ,FILE_SIZE = case when FILE_SIZE - ' . $job['FILE_SIZE'] . ' > 0 then FILE_SIZE - ' . $job['FILE_SIZE'] . ' else 0 end WHERE ID = ' . $job['BUCKET_ID'] . ' '); $c++; COption::SetOptionString('main_size', '~cloud', intval(COption::GetOptionString('main_size', '~cloud')) - $job['FILE_SIZE']); } $DB->Query('DELETE FROM b_clouds_size_queue WHERE ID = ' . $job['ID']); } if ($c > 0 && CACHED_b_clouds_file_bucket !== false) { $CACHE_MANAGER->CleanDir('b_clouds_file_bucket'); } $connection->unlock('CCloudStorageBucket::ApplyFileCounter'); } } }