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/cvetdv.ru/bitrix/modules/acrit.cleanmaster/classes/general/ |
Upload File : |
<?php /** @noinspection SqlResolve */ /** @noinspection SqlNoDataSourceInspection */ use \Acrit\Cleanmaster\Data\UploadBfileindexTable, \Acrit\Cleanmaster\Data\UploadFilelostTable, \Acrit\Cleanmaster\Helpers\UpoadFilterIterator; use Bitrix\Main\Config\Option; final class CCleanUpload extends TCleanMasterFunctions { private $documentRoot; public $mediaCount; private $knownFolders; // value used if no config by this setting public const PER_STEP_PROCESS_FILES = 2000; public function __construct() { $this->documentRoot = Bitrix\Main\Application::getDocumentRoot(); $this->knownFolders = ['tmp', 'resize_cache', '1c_catalog', '1c_exchange', 'cleanmaster', 'uf', '.htaccess', 'medialibrary', 'rk']; foreach (['/bitrix/modules', '/local/modules'] as $p) { if (! is_dir($this->documentRoot . $p)) { continue; } $idir = new DirectoryIterator($this->documentRoot . $p); foreach ($idir as $v) { if ($v->isDot()) { continue; } if ($v->isDir()) { $this->knownFolders[] = $v->getBasename(); } } } $this->mediaCount = (int)Option::get(\CCleanMain::MODULE_ID, 'CCleanUpload_PER_STEP_PROCESS_FILES', self::PER_STEP_PROCESS_FILES); if (!$this->mediaCount) { $this->mediaCount = self::PER_STEP_PROCESS_FILES; } } /** * Сколько обрабатывать за шаг (2000 файлов) * @return int */ public function GetStepCount(): int { return $this->mediaCount; } /** * получить кол-во записей в таблице b_file * @return integer */ public function GetCount(): int { global $DB; $arCount = $DB->Query("SELECT count(ID) AS CNT FROM b_file")->Fetch(); return (int)$arCount['CNT']; } /** * получить кол-во записей в таблице b_file * @return integer * @deprecated */ public function GetCountEx(): int { return 0; } /** * Получить строки из b_file * * @param $step * * @return array|bool */ public function GetRows($step) { global $DB; $count = $this->GetStepCount(); $start = $step * $count; $files = []; $dbFiles = $DB->Query("SELECT * FROM b_file LIMIT $count OFFSET $start"); while ($arFile = $dbFiles->Fetch()) { $files[] = $arFile; } return is_array($files) ? $files : false; } /** * Получить ВСЕ строки из b_file (cron) * @return array|bool */ public function GetRowsFull() { global $DB; $files = []; $dbFiles = $DB->Query("SELECT * FROM b_file"); while ($arFile = $dbFiles->Fetch()) { $files[] = $arFile; } return is_array($files) ? $files : false; } public function DeleteTempDir($step = false, $delete_resize_cache = 'N'): bool { if (file_exists($this->documentRoot . '/upload/tmp')) { DeleteDirFilesEx('/upload/tmp/'); } if ($delete_resize_cache == 'Y') { // its used in admin lists if (file_exists($this->documentRoot . '/upload/resize_cache')) { DeleteDirFilesEx('/upload/resize_cache/'); } // drop resize_cache need drop cache $cleanCache = new CCleanCache; $cleanCache->CacheClear(); } if (file_exists($this->documentRoot . '/upload/1c_catalog')) { DeleteDirFilesEx('/upload/1c_catalog/'); } $temp_upload = '/upload/cleanmaster/'; $this->SetPermission($this->documentRoot . $temp_upload, 0777); DeleteDirFilesEx($temp_upload); return false; } /** * Откат с папки /upload/cleanmaster/ */ public function RevertTmpDir(): void { $path = $this->documentRoot . '/upload/cleanmaster'; $idir = new RecursiveIteratorIterator( new RecursiveDirectoryIterator($path, FilesystemIterator::SKIP_DOTS), RecursiveIteratorIterator::CHILD_FIRST ); foreach ($idir as $v) { /* @var $v \SplFileInfo */ if ($v->isFile()) { $p = str_replace('/upload/cleanmaster', '', $idir->key()); CheckDirPath($p); copy($idir->key(), $p); } } $this->ClearTmpDir(); } public function ClearTmpDir(): void { DeleteDirFilesEx('/upload/cleanmaster/'); } public function fillBfileIndex($step, $noLimit = false) { $step = (int)$step; if ($step == 0) { UploadBfileindexTable::clearTable(); } $cntSteps = $this->getCountStepsBfileIndex(); if ($noLimit === true) { $records = $this->GetRowsFull(); } else { $records = $this->GetRows($step); } foreach ($records as $record) { $record['F_PATH'] = \CFile::GetFileSRC($record, false, false); UploadBfileindexTable::add([ 'F_PATH' => $record['F_PATH'], 'FILE_ID' => $record['ID'] ]); } $step++; if ($step > $cntSteps - 1) { // step from zero return false; } return $step; } public function getCountStepsBfileIndex(): float { $cntRows = $this->GetCount(); $cntPerStep = $this->GetStepCount(); $cntSteps = ceil($cntRows / $cntPerStep); return $cntSteps; } /** * folder may be too big, optional to run method * @return float */ public function getCountStepsDiagnosticData(): float { $cntFiles = 0; $directory = new \RecursiveDirectoryIterator($this->documentRoot . '/upload', \FilesystemIterator::SKIP_DOTS | \FilesystemIterator::FOLLOW_SYMLINKS ); $filter = new UpoadFilterIterator($directory); $fsi = new \RecursiveIteratorIterator($filter); foreach ($fsi as $f) { $cntFiles++; } return ceil($cntFiles / $this->GetStepCount()); } public function GetDiagnosticData($step, bool $noLimit = false): bool { $step = (int)$step; if ($step == 0) { $_SESSION['cleanmaster']['diagnostic']['upload']['dbSize'] = 0; $_SESSION['cleanmaster']['diagnostic']['upload']['dirs'] = []; //$_SESSION['cleanmaster']['diagnostic']['upload']['dirSize']['.'] = $this->GetUploadSize($this->documentRoot.'/upload/'); UploadFilelostTable::clearTable(); $_SESSION['cleanmaster']['diagnostic']['upload']['lost_file_size'] = 0; } $directory = new \RecursiveDirectoryIterator($this->documentRoot . '/upload', \FilesystemIterator::SKIP_DOTS | \FilesystemIterator::FOLLOW_SYMLINKS ); $filter = new UpoadFilterIterator($directory); $fsi = new \RecursiveIteratorIterator($filter); $cntPerStep = $this->GetStepCount(); $fileISkip = $step * $cntPerStep; $fileI = 0; $filenames = []; foreach ($fsi as $f) { /* @var $f SplFileInfo */ if ($fileISkip > 0) { $fileISkip--; continue; } $filename = str_replace('\\', '/', $f->getRealPath()); $filename = str_replace(realpath($this->documentRoot . '/upload'), '/upload', $filename); // upload like symlink-folder $filenames[] = $filename; if (!$noLimit) { if ((++$fileI % $cntPerStep) === 0) { break; } } } if (count($filenames) > 0) { $filenamesRegistered = []; $rsRows = UploadBfileindexTable::getList([ 'select' => ['F_PATH'], 'filter' => ['=F_PATH' => $filenames], ]); while ($row = $rsRows->fetch()) { $filenamesRegistered[] = $row['F_PATH']; } $toDelete = array_diff($filenames, $filenamesRegistered); foreach ($toDelete as $filename) { UploadFilelostTable::add([ 'F_PATH' => $filename, 'SIZE' => filesize($this->documentRoot . $filename) ]); } } if ($fileISkip > 0) { $_SESSION['cleanmaster']['diagnostic']['upload']['lost_file_size'] = UploadFilelostTable::getLostSize(); } return ($fileISkip == 0); } /** * Для интерфейса, отчет какие файлы будут удалены * * @param $dirSizes = array() заранее известные размеры папок (если известны) * @param $limit = 0 сколько строк выбрать сверху * @param $subselectTmps = true * @param bool $showStrangeFiles = true показывать найденные странные файлы в папке upload * * @return array * @throws \Bitrix\Main\ArgumentException */ public function getDiagnosticListFiles($dirSizes = [], $limit = 0, $subselectTmps = true, $showStrangeFiles = true): array { $r = $ra = []; $arS = [ 'select' => ['*'], 'order' => ['ID' => 'asc'] ]; if ((int)$limit > 0) { $arS['limit'] = $limit; } $rows = UploadFilelostTable::getList($arS); while ($row = $rows->fetch()) { $r[] = $row['F_PATH'] . ' (' . \CFile::FormatSize($row['SIZE']) . ')'; //$row['SIZE'] = 0; // recalc with getDiagnosticListFilesFullSize() method $ra[] = $row; } if ($subselectTmps) { $tmpDirsAll = []; $tmpDirs = [ '/upload/tmp/', // '/upload/resize_cache/', // TODO folder is too big, make stepper on size of it '/upload/1c_catalog/', '/upload/cleanmaster/' ]; foreach ($tmpDirs as &$d) { $dt = str_replace(['/upload/', '/'], '', $d); if (isset($dirSizes[$dt])) { $size = $dirSizes[$dt]; } else { $size = $this->GetDirSize($this->documentRoot . $d) * 1024 * 1024; } $tmpDirsAll[] = [ 'F_PATH' => $d, 'SIZE' => $size ]; $d = $d . ' (' . \CFile::FormatSize($size) . ')'; } unset($d); $r = array_merge($r, $tmpDirs); $ra = array_merge($ra, $tmpDirsAll); unset($tmpDirs, $tmpDirsAll); } if ($showStrangeFiles) { $tmpDirsAll = $tmpDirs = []; $idir = new DirectoryIterator($this->documentRoot . '/upload'); foreach ($idir as $v) { if ($v->isDot() || in_array($v->getBasename(), $this->knownFolders)) { continue; } $size = 0; if ($v->isDir()) { $size = $this->GetDirSize($this->documentRoot . '/upload/' . $v->getBasename()) * 1024 * 1024; } else if ($v->isFile()) { $size = $v->getSize(); } $tmpDirs[] = '/upload/' . $v->getBasename() . ' (' . \CFile::FormatSize($size) . ')'; $tmpDirsAll[] = [ 'F_PATH' => '/upload/' . $v->getBasename(), 'SIZE' => $size, 'IS_MANUAL_CHECK' => 'Y' ]; } $r = array_merge($r, $tmpDirs); $ra = array_merge($ra, $tmpDirsAll); unset($tmpDirs, $tmpDirsAll); } $returMod = [ 'r' => $r, 'ra' => $ra ]; return $returMod; } public function getDiagnosticListFilesFullSize(): float { global $DB; $r = $DB->Query('SELECT SUM(SIZE) AS `SUM` FROM ' . UploadFilelostTable::getTableName())->Fetch(); return (float)$r['SUM']; } public function DeleteLostFiles($step, $noLimit = false) { $temp_upload = $this->documentRoot . '/upload/cleanmaster/'; if (!file_exists($temp_upload)) { /** @noinspection MkdirRaceConditionInspection */ mkdir($temp_upload); $this->SetPermission($temp_upload, 0777); } $params = [ 'select' => ['*'], 'order' => ['ID' => 'asc'], 'limit' => 200, ]; if ($noLimit === true) { unset($params['limit']); } $rows = UploadFilelostTable::getList($params); $bFinded = false; while ($row = $rows->fetch()) { $bFinded = true; CheckDirPath($temp_upload . $row['F_PATH']); copy($this->documentRoot . $row['F_PATH'], $temp_upload . $row['F_PATH']); unlink($this->documentRoot . $row['F_PATH']); UploadFilelostTable::delete($row['ID']); } return $bFinded; } public function getCountStepsDeleteLostFiles(): float { return ceil(UploadFilelostTable::getCntRows() / 200); } /** * Получаем размер папок и сохраняем в сессию для диагностики * (только временных папок tmp + resize_cache) * * @param $path * @param int $level * * @return float|int * @deprecated */ private function GetUploadSize($path, $level = 1) { $files = scandir($path, SCANDIR_SORT_NONE); $size = 0; if (is_array($files)) { foreach ($files as $file) { if ($file == '.' || $file == '..' || ($level == 1 && !in_array($file, ['tmp', 'cleanmaster', 'resize_cache', '1c_catalog']))) { continue; } if (is_dir($path . $file)) { $dirSize = $this->GetUploadSize($path . $file . '/', $level + 1); if ($level == 1) { $_SESSION['cleanmaster']['diagnostic']['upload']['dirSize'][$file] = $dirSize; } $size += $dirSize; } else { $size += filesize($path . $file) / 1024 / 1024; } } } return $size; } } // end class