Файловый менеджер - Редактировать - /var/www/axolotl/data/www/axolotls.ru/www/bitrix/modules/crm/lib/volume/base.php
Назад
<?php namespace Bitrix\Crm\Volume; use Bitrix\Crm; use Bitrix\Crm\Volume; use Bitrix\Main; use Bitrix\Main\ORM; use Bitrix\Main\Error; use Bitrix\Disk; /** * @implements \Bitrix\Crm\Volume\IVolumeClear * @implements \Bitrix\Crm\Volume\IVolumeClearFile * @implements \Bitrix\Crm\Volume\IVolumeClearActivity * @implements \Bitrix\Crm\Volume\IVolumeClearEvents */ abstract class Base implements Volume\IVolumeIndicator, Main\Errorable { use Main\ErrorableImplementation; /** @var array Indicator list available in library. */ protected static $indicatorTypeList = array(); /** @var array */ protected static $tablesInformation = array(); /** @var array */ protected static $userFieldInformation = array(); /** @var array */ protected static $maxIdRangeCache = array(); /** @var array */ protected $tableList = array(); /** @var int */ protected $ownerId = 0; /** @var int */ protected $entitySize = 0; /** @var int */ protected $entityCount = 0; /** @var int */ protected $fileSize = 0; /** @var int */ protected $fileCount = 0; /** @var int */ protected $diskSize = 0; /** @var int */ protected $diskCount = 0; /** @var int */ protected $eventSize = 0; /** @var int */ protected $eventCount = 0; /** @var int */ protected $activitySize = 0; /** @var int */ protected $activityCount = 0; /** @var array */ protected $filter = array(); /** @var float seconds */ private $timeLimit = -1; /** @var float seconds */ private $startTime = -1; /** @var boolean */ private $timeLimitReached = false; /** @var int */ private $processOffset = 0; /** @var int */ private $droppedCount = 0; /** @var int */ private $droppedFileCount = 0; /** @var int */ private $failCount = 0; const ERROR_PERMISSION_DENIED = 'CRM_PERMISSION_DENIED'; const ERROR_DELETION_FAILED = 'CRM_DELETION_FAILED'; // limit maximum number selected entity const MAX_ENTITY_PER_INTERACTION = 1000; // limit maximum number selected files const MAX_FILE_PER_INTERACTION = 1000; /** @var array */ protected static $filterFieldAlias = array(); /** @var array */ protected static $entityList = array(); /** @var array */ protected $dateSplitPeriod = array(1, 'months'); /** @var false */ protected $collectEntityRowSize = false; /** * @return string the fully qualified name of this class. */ final public static function className() { return get_called_class(); } /** * @return string The short indicator name of this class. */ final public static function getIndicatorId() { return str_replace(array(__NAMESPACE__. '\\', '\\'), array('', '_'), static::className()); } /** * Checks if module Voximplant is available. * @param string $moduleId Mmodule Id. * @return boolean */ protected static function isModuleAvailable($moduleId) { static $available = array(); if (!isset($available[$moduleId])) { $available[$moduleId] = Main\ModuleManager::isModuleInstalled($moduleId) && Main\Loader::includeModule($moduleId); } return $available[$moduleId]; } /** * Gets task owner. * @return \CUser */ protected function getUser() { /** @global \CUser $USER */ global $USER; return $USER; } /** * Checks data base structure and vipe old data. * @return void */ protected function checkTemporally() { if (Crm\VolumeTmpTable::checkTemporally()) { Crm\VolumeTmpTable::deleteBatch(array( '=INDICATOR_TYPE' => static::getIndicatorId(), '=OWNER_ID' => $this->getOwner(), )); } else { Crm\VolumeTmpTable::createTemporally(); } } /** * Copy data from temporally table. * @return void */ protected function copyTemporallyData() { $connection = Main\Application::getConnection(); $keyFields = array( 'INDICATOR_TYPE', 'OWNER_ID', 'DATE_CREATE', 'STAGE_SEMANTIC_ID', ); $updateFields = array( 'ENTITY_SIZE', 'ENTITY_COUNT', 'FILE_SIZE', 'FILE_COUNT', 'DISK_SIZE', 'DISK_COUNT', 'EVENT_SIZE', 'EVENT_COUNT', 'ACTIVITY_SIZE', 'ACTIVITY_COUNT', ); $target = $connection->getSqlHelper()->quote(Crm\VolumeTable::getTableName()); $query = Crm\VolumeTmpTable::query(); $query ->setSelect(array_merge($keyFields, $updateFields)) ->setFilter(array( '=INDICATOR_TYPE' => static::getIndicatorId(), '=OWNER_ID' => $this->getOwner(), )); $sourceSql = $query->getQuery(); $columns = $update = array(); foreach ($keyFields as $field) { $field = $connection->getSqlHelper()->quote($field); $columns[] = $field; } foreach ($updateFields as $field) { $field = $connection->getSqlHelper()->quote($field); $columns[] = $field; $update[] = "{$target}.{$field} = {$target}.{$field} + VALUES({$field})"; } $sqlIns = "INSERT INTO {$target} (". implode(', ', $columns). ") {$sourceSql} ". "ON DUPLICATE KEY UPDATE ". implode(', ', $update) ; $connection->queryExecute($sqlIns); } /** * Runs measure test. * @return self */ public function measure() { $this ->purify() ->measureEntity() ->measureFiles(); if ($this instanceof Volume\IVolumeClearActivity || is_callable([$this, 'measureActivity'])) { $this->measureActivity(); } if ($this instanceof Volume\IVolumeClearEvent || is_callable([$this, 'measureEvent'])) { $this->measureEvent(); } return $this; } /** * Deletes objects selecting by filter. * @return self */ public function purify() { Crm\VolumeTable::deleteBatch(array( '=INDICATOR_TYPE' => static::getIndicatorId(), '=OWNER_ID' => $this->getOwner(), )); return $this; } /** * Returns total amount of objects selecting by filter. * @return double[] */ public function loadTotals() { $query = Crm\VolumeTable::query(); $filter = array( '=INDICATOR_TYPE' => static::getIndicatorId(), '=OWNER_ID' => $this->getOwner(), '=AGENT_LOCK' => Volume\Cleaner::TASK_STATUS_NONE, ); $filterExt = $this->getFilter(); foreach ($filterExt as $key => $value) { if (empty($value)) { continue; } $filter[$key] = $value; } $query ->setFilter($filter) ->registerRuntimeField(new ORM\Fields\ExpressionField('CNT', 'COUNT(*)')) ->registerRuntimeField(new ORM\Fields\ExpressionField('ENTITY_SIZE', 'SUM(ENTITY_SIZE)')) ->registerRuntimeField(new ORM\Fields\ExpressionField('ENTITY_COUNT', 'SUM(ENTITY_COUNT)')) ->registerRuntimeField(new ORM\Fields\ExpressionField('FILE_SIZE', 'SUM(FILE_SIZE)')) ->registerRuntimeField(new ORM\Fields\ExpressionField('FILE_COUNT', 'SUM(FILE_COUNT)')) ->registerRuntimeField(new ORM\Fields\ExpressionField('DISK_SIZE', 'SUM(DISK_SIZE)')) ->registerRuntimeField(new ORM\Fields\ExpressionField('DISK_COUNT', 'SUM(DISK_COUNT)')) ->registerRuntimeField(new ORM\Fields\ExpressionField('EVENT_SIZE', 'SUM(EVENT_SIZE)')) ->registerRuntimeField(new ORM\Fields\ExpressionField('EVENT_COUNT', 'SUM(EVENT_COUNT)')) ->registerRuntimeField(new ORM\Fields\ExpressionField('ACTIVITY_SIZE', 'SUM(ACTIVITY_SIZE)')) ->registerRuntimeField(new ORM\Fields\ExpressionField('ACTIVITY_COUNT', 'SUM(ACTIVITY_COUNT)')) ->addSelect('CNT') ->addSelect('ENTITY_SIZE') ->addSelect('ENTITY_COUNT') ->addSelect('FILE_SIZE') ->addSelect('FILE_COUNT') ->addSelect('DISK_SIZE') ->addSelect('DISK_COUNT') ->addSelect('EVENT_SIZE') ->addSelect('EVENT_COUNT') ->addSelect('ACTIVITY_SIZE') ->addSelect('ACTIVITY_COUNT') ; $res = $query->exec(); if ($row = $res->fetch()) { $this->entitySize = (double)$row['ENTITY_SIZE']; $this->entityCount = (double)$row['ENTITY_COUNT']; $this->fileSize = (double)$row['FILE_SIZE']; $this->fileCount = (double)$row['FILE_COUNT']; $this->diskSize = (double)$row['DISK_SIZE']; $this->diskCount = (double)$row['DISK_COUNT']; $this->eventSize = (double)$row['EVENT_SIZE']; $this->eventCount = (double)$row['EVENT_COUNT']; $this->activitySize = (double)$row['ACTIVITY_SIZE']; $this->activityCount = (double)$row['ACTIVITY_COUNT']; } return $row; } /** * Runs measure test for tables. * @return self */ public function measureEntity() { self::loadTablesInformation(); // database size $this->entitySize = 0; $this->entityCount = 0; if (count($this->getFilter()) > 0) { if (!$this->canBeFiltered()) { // nonfiterable return $this; } $entityList = static::getEntityList(); foreach ($entityList as $classEntity) { /** * @var ORM\Data\DataManager $classEntity */ $query = $classEntity::query(); $entity = $classEntity::getEntity(); // filter if ($this->prepareEntityFilter($query, $entity)) { $query ->registerRuntimeField(new ORM\Fields\ExpressionField('CNT', 'COUNT(*)')) ->addSelect('CNT'); $res = $query->exec(); if ($row = $res->fetch()) { $table = $classEntity::getTableName(); $avgTableRowLength = (double)self::$tablesInformation[$table]['AVG_SIZE']; $this->entitySize += $avgTableRowLength * (double)$row['CNT']; } } } } else { $tableList = $this->getTableList(); if (count($tableList) > 0) { $this->entityCount = self::$tablesInformation[$tableList[0]]['TABLE_ROWS']; foreach ($tableList as $tableName) { $this->entitySize += (double)self::$tablesInformation[$tableName]['SIZE']; } } } $connection = Main\Application::getConnection(); $data = array( 'INDICATOR_TYPE' => static::getIndicatorId(), 'OWNER_ID' => $this->getOwner(), 'ENTITY_COUNT' => ($this->entityCount ? : 0), 'ENTITY_SIZE' => ($this->entitySize ? : 0), 'STAGE_SEMANTIC_ID' => '-', ); $insert = $connection->getSqlHelper()->prepareInsert(Crm\VolumeTable::getTableName(), $data); $querySql = 'INSERT INTO '.$connection->getSqlHelper()->quote(Crm\VolumeTable::getTableName()). '('. $insert[0]. ') VALUES ('. $insert[1]. ')'; Crm\VolumeTable::deleteBatch(array( '=INDICATOR_TYPE' => static::getIndicatorId(), '=OWNER_ID' => $this->getOwner(), '=AGENT_LOCK' => Volume\Cleaner::TASK_STATUS_NONE, )); $connection->queryExecute($querySql); return $this; } /** * Setups filter params into query. * @param ORM\Query\Query $query Query. * @param ORM\Entity $entity Use only this entity fields. * @param string $entityAlias Table alias. * @return boolean */ public function prepareEntityFilter(ORM\Query\Query $query, ORM\Entity $entity, $entityAlias = '') { $isAllValueApplied = true; // Samples naming: // EVENT.DATE_CREATE // DealCategory.CREATED_DATE // InvoiceStatusHistory.CREATED_TIME // ActivityTable.CREATED $dateCreatedAlias = array('DATE_CREATE', 'CREATED_TIME', 'CREATED_DATE', 'CREATED'); // Samples naming: // DEAL.STAGE_SEMANTIC_ID // LEAD.STATUS_SEMANTIC_ID $stageSemanticAlias = array('STAGE_SEMANTIC_ID', 'STATUS_SEMANTIC_ID'); $filter = $this->getFilter(); foreach ($filter as $key => $value) { if (empty($value)) { continue; } $key0 = trim($key, '<>!=@'); if (strlen($key) > strlen($key0)) { $operator = substr($key, 0, strlen($key) - strlen($key0)); } else { $operator = '='; if (is_array($value)) { $operator = 'in'; } } switch ($key0) { case 'STAGE_SEMANTIC_ID': $isApplied = false; foreach ($stageSemanticAlias as $aliasStageSemantic) { if ($entity->hasField($aliasStageSemantic)) { $isApplied = true; if ($entityAlias !== '') { $aliasStageSemantic = "{$entityAlias}.{$aliasStageSemantic}"; } $query->where($aliasStageSemantic, $operator, $value); break; } } if (!$isApplied) { $isAllValueApplied = false; } break; case 'DATE_CREATE': $isApplied = false; foreach ($dateCreatedAlias as $aliasDateCreated) { if ($entity->hasField($aliasDateCreated)) { if ($entity->getField($aliasDateCreated) instanceof ORM\Fields\DatetimeField) { $isApplied = true; if ($entityAlias !== '') { $aliasDateCreated = "{$entityAlias}.{$aliasDateCreated}"; } $query->where($aliasDateCreated, $operator, $value); break; } } } if (!$isApplied) { $isAllValueApplied = false; } break; default: $isApplied = $this->addFilterEntityField($query, $entity, $key, $value); if (!$isApplied) { $isAllValueApplied = false; } } } return $isAllValueApplied; } /** * Setups filter params into query. * @param ORM\Query\Query $query Query. * @param ORM\Entity $entity Use only this entity fields. * @param string $key Key name. * @param mixed $value Value. * @return boolean */ protected function addFilterEntityField(ORM\Query\Query $query, ORM\Entity $entity, $key, $value) { $isAllValueApplied = false; $key0 = trim($key, '<>!='); if (strpos($key0, '.') !== false) { $key0 = substr($key0, 0, strpos($key0,'.')); if ($entity->hasField($key0)) { $query->addFilter($key, $value); $isAllValueApplied = true; } } elseif ($entity->hasField($key0)) { $query->addFilter($key, $value); $isAllValueApplied = true; } return $isAllValueApplied; } /** * Runs measure test for files. * * @return self * @throws Main\Db\SqlQueryException * @throws Main\LoaderException */ public function measureFiles() { $this->fileSize = 0; $this->fileCount = 0; $this->diskSize = 0; $this->diskCount = 0; if (count($this->getFilter()) > 0 && !$this->canBeFiltered()) { // nonfiterable return $this; } self::loadTablesInformation(); $connection = Main\Application::getConnection(); $source = array(); $entityList = static::getEntityList(); foreach ($entityList as $entityClass) { $entityUserFieldList = $this->getUserTypeFieldList($entityClass); /** @var array $userField */ foreach ($entityUserFieldList as $userField) { $sql = $this->prepareUserFieldQuery($entityClass, $userField); if ($sql !== '') { $source[] = $sql; } } $diskConnector = static::getDiskConnector($entityClass); if ($diskConnector !== null) { $sql = $this->prepareDiskAttachedQuery($entityClass, $diskConnector); if ($sql !== '') { $source[] = $sql; } } $liveFeedConnector = static::getLiveFeedConnector($entityClass); if ($liveFeedConnector !== null) { $sql = $this->prepareLiveFeedQuery($entityClass, $liveFeedConnector); if ($sql !== '') { $source[] = $sql; } } } if (count($source) > 0) { $querySql = " SELECT SUM(src.FILE_SIZE) as FILE_SIZE, SUM(src.FILE_COUNT) as FILE_COUNT, SUM(src.DISK_SIZE) as DISK_SIZE, SUM(src.DISK_COUNT) as DISK_COUNT FROM ( (". implode(' ) UNION ( ', $source). ") ) src "; $result = $connection->query($querySql); if ($row = $result->fetch()) { $this->fileSize += (double)$row['FILE_SIZE']; $this->fileCount += (double)$row['FILE_COUNT']; $this->diskSize += (double)$row['DISK_SIZE']; $this->diskCount += (double)$row['DISK_COUNT']; } } $data = array( 'INDICATOR_TYPE' => static::getIndicatorId(), 'OWNER_ID' => $this->getOwner(), 'STAGE_SEMANTIC_ID' => '-', 'FILE_SIZE' => $this->fileSize, 'FILE_COUNT' => $this->fileCount, 'DISK_SIZE' => $this->diskSize, 'DISK_COUNT' => $this->diskCount, ); $insert = $connection->getSqlHelper()->prepareInsert(Crm\VolumeTable::getTableName(), $data); $querySql = 'INSERT INTO '.$connection->getSqlHelper()->quote(Crm\VolumeTable::getTableName()). '('. $insert[0]. ') VALUES ('. $insert[1]. ')'; Crm\VolumeTable::deleteBatch(array( '=INDICATOR_TYPE' => static::getIndicatorId(), '=OWNER_ID' => $this->getOwner(), '=AGENT_LOCK' => Volume\Cleaner::TASK_STATUS_NONE, )); $connection->queryExecute($querySql); return $this; } /** * Tells that is is participated in the total volume. * @return boolean */ public function isParticipatedTotal() { return true; } /** * Returns query. * * @return ORM\Query\Query */ public function prepareQuery() { return null; } /** * Setups filter params into query. * @param ORM\Query\Query $query Query. * @return boolean */ public function prepareFilter(ORM\Query\Query $query) { $filter = $this->getFilter(); if (count($filter) > 0 && !$this->canBeFiltered()) { return false; } $isAllValueApplied = true; foreach ($filter as $key => $value) { if (empty($value)) { continue; } $key0 = trim($key, '<>!='); if (isset(static::$filterFieldAlias[$key0])) { $key1 = str_replace($key0, static::$filterFieldAlias[$key0], $key); if (is_array($value)) { $query->where($key1, 'in', $value); } else { $query->addFilter($key1, $value); } } else { $isAllValueApplied = $isAllValueApplied && $this->addFilterEntityField($query, $query->getEntity(), $key, $value); } } return $isAllValueApplied; } /** * Returns indicator list available in library. * @return array */ final public static function getListIndicator() { if (empty(self::$indicatorTypeList)) { self::loadListIndicator(); } return self::$indicatorTypeList; } /** * Recursively looks for indicator class files available in library. * @param string $libraryPath Sub folder name inside current library. * @return void */ private static function loadListIndicator($libraryPath = '') { $directory = new Main\IO\Directory(__DIR__. '/'. $libraryPath); $fileList = $directory->getChildren(); foreach ($fileList as $entry) { if ($entry->isFile() && preg_match("/^(.+)\.php$/i", $entry->getName(), $parts)) { $subNamespace = ($libraryPath != '' ? '\\'.$libraryPath : ''). '\\'; /** @var Volume\IVolumeIndicator $indicatorType */ $indicatorType = __NAMESPACE__. $subNamespace. $parts[1]; try { $reflection = new \ReflectionClass($indicatorType); if ( !$reflection->isInterface() && !$reflection->isAbstract() && !$reflection->isTrait() && $reflection->implementsInterface(__NAMESPACE__.'\\IVolumeIndicator') ) { self::$indicatorTypeList[$indicatorType::getIndicatorId()] = $indicatorType::className(); } } catch(\ReflectionException $exception) { } } elseif ($entry->isDirectory()) { self::loadListIndicator($entry->getName()); } } } /** * Constructs and returns indicator type object. * @param string $indicatorId Indicator class name. * @return Volume\IVolumeIndicator * @throws Main\ObjectException * @throws Main\ArgumentNullException */ final public static function getIndicator($indicatorId) { if (!$indicatorId) { throw new Main\ArgumentNullException('Wrong parameter indicatorTypeId'); } if (strpos($indicatorId, __NAMESPACE__) !== false) { $className = $indicatorId; } else { $className = __NAMESPACE__.'\\'.str_replace('_', '\\', $indicatorId); } /** @var Volume\IVolumeIndicator $indicator */ $indicator = new $className(); if (!$indicator instanceof Volume\IVolumeIndicator) { throw new Main\ObjectException('Return must implements '. __NAMESPACE__. '\\IVolumeIndicator interface.'); } return $indicator; } /** * Component action list for measure process. * @param array $componentCommandAlias Command alias. * @return array */ public function getActionList($componentCommandAlias) { $indicatorId = static::getIndicatorId(); $queueList[] = array( 'indicatorId' => $indicatorId, 'action' => $componentCommandAlias['MEASURE_ENTITY'], ); $queueList[] = array( 'indicatorId' => $indicatorId, 'action' => $componentCommandAlias['MEASURE_FILE'], ); $queueList[] = array( 'indicatorId' => $indicatorId, 'action' => $componentCommandAlias['MEASURE_ACTIVITY'], ); $queueList[] = array( 'indicatorId' => $indicatorId, 'action' => $componentCommandAlias['MEASURE_EVENT'], ); return $queueList; } /** * Returns date split period. * @return array */ public function getDateSplitPeriod() { return $this->dateSplitPeriod; } /** * Sets date split period. * @param array $dateSplitPeriod Value and units. * @return void */ public function setDateSplitPeriod(array $dateSplitPeriod) { $this->dateSplitPeriod = $dateSplitPeriod; } /** * Can filter applied to the indicator. * @return boolean */ public function canBeFiltered() { // can not be filtered return false; } /** * Sets filter parameters. * @param string $key Parameter name to filter. * @param string|string[] $value Parameter value. * @return $this */ public function addFilter($key, $value) { $this->filter[$key] = $value; return $this; } /** * Replace filter parameters. * @param array $filter Filter key = value pair. * @return $this */ public function setFilter(array $filter) { $this->filter = $filter; return $this; } /** * Gets filter parameter by key. * * @param string $key Parameter name to filter. * @param mixed|null $defaultValue Default value. * @param string $acceptedListModificators List of accepted filter modificator. Defaults are '=<>!'. * * @return mixed|null */ public function getFilterValue($key, $defaultValue = null, $acceptedListModificators = '<>!=') { if (isset($this->filter[$key])) { return $this->filter[$key]; } $filter = $this->getFilter(); foreach ($filter as $k => $value) { $k0 = trim($k, $acceptedListModificators); if ($k0 == $key) { return $value; } } return $defaultValue; } /** * Removes filter parameter by key. * @param string $key Parameter name to filter. * @param string $acceptedListModificators List of accepted filter modificator. Defaults are '=<>!'. * @return void */ public function delFilterValue($key, $acceptedListModificators = '<>!=') { if (isset($this->filter[$key])) { unset($this->filter[$key]); } $filter = $this->getFilter(); foreach ($filter as $k => $value) { $k0 = trim($k, $acceptedListModificators); if ($k0 == $key) { unset($this->filter[$k]); } } } /** * Gets filter parameters. * @param string[] $defaultFilter Default filter set. * @return array */ public function getFilter(array $defaultFilter = array()) { return (!empty($this->filter) ? $this->filter : $defaultFilter); } /** * Returns total volume size. * @return double */ public function getTotalSize() { return (double)$this->entitySize + (double)$this->fileSize; } /** * Returns total volume size of tables corresponding to indicator. * @return integer */ public function getEntitySize() { return (double)$this->entitySize; } /** * Returns total count of entities corresponding to indicator. * @return integer */ public function getEntityCount() { return (double)$this->entityCount; } /** * Returns total volume size of files corresponding to indicator. * @return integer */ public function getFileSize() { return (double)$this->fileSize; } /** * Returns total amount of files corresponding to indicator. * @return integer */ public function getFileCount() { return (double)$this->fileCount; } /** * Returns total volume size of file on disk. * @return double */ public function getDiskSize() { return (double)$this->diskSize; } /** * Returns total amount of files on disk. * @return double */ public function getDiskCount() { return (double)$this->diskCount; } /** * Returns total volume size of activities and associated files. * @return integer */ public function getActivitySize() { return (double)$this->activitySize; } /** * Returns total amount of activities and associated files. * @return integer */ public function getActivityCount() { return (double)$this->activityCount; } /** * Returns total volume size of events and associated files. * @return integer */ public function getEventSize() { return (double)$this->eventSize; } /** * Returns total amount of events and associated files. * @return integer */ public function getEventCount() { return (double)$this->eventCount; } /** * Returns title of the indicator. * @return string * @throws Main\NotImplementedException */ abstract public function getTitle(); /** * Returns entity list. * @return string[] */ public static function getEntityList() { return static::$entityList; } /** * Returns special folder list. * @return Disk\Folder[]|null */ public function getSpecialFolderList() { return array(); } /** * Returns entity list attached to disk object. * @param string $entityClass Class name of entity. * @return string|null */ public static function getDiskConnector($entityClass) { return null; } /** * Returns Socialnetwork log entity list attached to disk object. * @param string $entityClass Class name of entity. * @return string|null */ public static function getLiveFeedConnector($entityClass) { return null; } /** * Load tables information. * * @return void * @throws Main\Db\SqlQueryException */ protected static function loadTablesInformation() { if (empty(self::$tablesInformation)) { $connection = Main\Application::getConnection(); self::$tablesInformation = array(); $querySql = " SELECT TABLE_NAME, TABLE_ROWS AS TABLE_ROWS, DATA_LENGTH + INDEX_LENGTH AS SIZE, case TABLE_ROWS when 0 then 0 else round((DATA_LENGTH + INDEX_LENGTH) / TABLE_ROWS) end AS AVG_SIZE FROM information_schema.TABLES WHERE TABLE_SCHEMA = '".$connection->getDatabase()."' AND ( TABLE_NAME LIKE 'b_crm_%' OR TABLE_NAME LIKE 'b_uts_crm_%' OR TABLE_NAME LIKE 'b_utm_crm_%' OR TABLE_NAME LIKE 'b_uts_order' OR TABLE_NAME LIKE 'b_utm_order' ) "; $result = $connection->query($querySql); while ($row = $result->fetch()) { self::$tablesInformation[strtolower($row['TABLE_NAME'])] = $row; } } } /** * Returns table list corresponding to indicator. * * @return string[] * @throws Main\Db\SqlQueryException */ public function getTableList() { if (empty($this->tableList)) { $this->tableList = array(); self::loadTablesInformation(); $entityList = static::getEntityList(); foreach ($entityList as $entity) { try { $reflection = new \ReflectionClass($entity); if ( !$reflection->isInterface() && !$reflection->isAbstract() && $reflection->isSubclassOf(ORM\Data\DataManager::class) ) { /** @var ORM\Data\DataManager $entity */ $this->tableList[] = $entity::getTableName(); /** @var ORM\Data\DataManager $entity */ $ufName = $entity::getUfId(); if ($ufName != '') { $utmEntityTableName = 'b_utm_'.strtolower($ufName); if (isset(self::$tablesInformation[$utmEntityTableName])) { $this->tableList[] = $utmEntityTableName; } $utsEntityTableName = 'b_uts_'.strtolower($ufName); if (isset(self::$tablesInformation[$utsEntityTableName])) { $this->tableList[] = $utsEntityTableName; } } } } catch (\ReflectionException $exception) { } } } return $this->tableList; } /** * Loads list of user fields information. * * @return void * @throws Main\ArgumentException */ protected static function loadUserFieldInformation() { $entityList = static::getEntityList(); foreach ($entityList as $entity) { if (isset(self::$userFieldInformation[$entity])) { continue; } self::$userFieldInformation[$entity] = false; try { $reflection = new \ReflectionClass($entity); if ( !$reflection->isInterface() && !$reflection->isAbstract() && $reflection->isSubclassOf(ORM\Data\DataManager::class) ) { /** @var ORM\Data\DataManager $entity */ $ufName = $entity::getUfId(); if (strlen($ufName) > 0) { $userFieldList = Main\UserFieldTable::getList(array( 'filter' => array( '=ENTITY_ID' => $ufName, ), 'select' => array( 'ID', 'ENTITY_ID', 'USER_TYPE_ID', 'FIELD_NAME', 'MULTIPLE', 'XML_ID', ), )); if ($userFieldList->getSelectedRowsCount() > 0) { self::$userFieldInformation[$entity] = array(); foreach ($userFieldList as $userField) { self::$userFieldInformation[$entity][$userField['FIELD_NAME']] = $userField; } } } } } catch (\ReflectionException $exception) { } } } /** * Returns list of user fields corresponding to entity. * @param string $entity Class name of entity. * @return array */ public function getUserTypeFieldList($entity) { self::loadUserFieldInformation(); $fields = array(); if (isset(self::$userFieldInformation[$entity]) && is_array(self::$userFieldInformation[$entity])) { $userTypeField = array( \CUserTypeFile::USER_TYPE_ID, ); if (self::isModuleAvailable('disk')) { $userTypeField[] = Disk\Uf\FileUserType::USER_TYPE_ID; $userTypeField[] = Disk\Uf\VersionUserType::USER_TYPE_ID; } foreach (self::$userFieldInformation[$entity] as $userField) { if (is_array($userField) && in_array($userField['USER_TYPE_ID'], $userTypeField)) { $fields[$userField['FIELD_NAME']] = $userField; } } } return $fields; } /** * Gets SQL query code to userfield table. * * @param string $entityClass Class name of entity. * @param array $userField User field params. * @param array $entityGroupField Entity fields to group by. * * @return string */ protected function prepareUserFieldQuery($entityClass, array $userField, array $entityGroupField = array()) { /** * @var ORM\Data\DataManager $entityClass */ $ufName = $entityClass::getUfId(); if (empty($ufName)) { return ''; } $ufType = $userField['USER_TYPE_ID']; $isDiskAvailable = self::isModuleAvailable('disk'); // need to filter by Entity $entityQuery = $entityClass::query(); $entityEntity = $entityClass::getEntity(); $entityQuery->addSelect('ID'); // STAGE_SEMANTIC_ID if ($entityClass == Crm\QuoteTable::class) { Volume\Quote::registerStageField($entityQuery, '', 'STAGE_SEMANTIC_ID'); Volume\Quote::registerStageField($entityQuery, '', 'QUOTE_STAGE_SEMANTIC_ID'); } if ($entityClass == Crm\InvoiceTable::class) { Volume\Invoice::registerStageField($entityQuery, '', 'STAGE_SEMANTIC_ID'); Volume\Invoice::registerStageField($entityQuery, '', 'INVOICE_STAGE_SEMANTIC_ID'); } // DATE if ( $entityClass == Crm\CompanyTable::class || $entityClass == Crm\ContactTable::class ) { $dayField = new ORM\Fields\ExpressionField( 'DATE_CREATE_SHORT', 'DATE(%s)', 'DATE_CREATE' ); $entityQuery->registerRuntimeField($dayField); } if ( $entityClass == Crm\InvoiceTable::class ) { $dayField = new ORM\Fields\ExpressionField( 'DATE_CREATE_SHORT', 'DATE(%s)', 'DATE_INSERT' ); $entityQuery->registerRuntimeField($dayField); } $entityFieldsSql = ''; $entityFieldsGroupSql = ''; $entityFields = array(); foreach ($entityGroupField as $alias => $field) { $entityQuery->addSelect($field, $alias); $entityFields[] = 'entity.'. $alias; } if ($this->prepareEntityFilter($entityQuery, $entityEntity)) { $entityFilterQuerySql = $entityQuery->getQuery(); if (count($entityFields) > 0) { $entityFieldsSql = ', '.implode(', ', $entityFields); $entityFieldsGroupSql = 'GROUP BY '.implode(', ', $entityFields); } } else { // cannot filter this Entity return ''; } $querySql = ''; if ($userField['MULTIPLE'] === 'Y') { $ufId = $userField['ID']; $utmEntityTableName = 'b_utm_'.strtolower($ufName); if (isset(self::$tablesInformation[$utmEntityTableName])) { if ( $isDiskAvailable && $ufType === Disk\Uf\FileUserType::USER_TYPE_ID ) { $querySql = " SELECT SUM(f.FILE_SIZE) as FILE_SIZE, COUNT(DISTINCT f.ID) as FILE_COUNT, SUM(f.FILE_SIZE) as DISK_SIZE, COUNT(DISTINCT f.ID) as DISK_COUNT {$entityFieldsSql} FROM {$utmEntityTableName} ufsrc INNER JOIN ( {$entityFilterQuerySql} ) entity ON entity.ID = ufsrc.VALUE_ID INNER JOIN b_disk_attached_object attached ON attached.ID = ufsrc.VALUE_INT AND ufsrc.FIELD_ID = '{$ufId}' INNER JOIN b_disk_object files ON files.ID = attached.OBJECT_ID AND files.ID = files.REAL_OBJECT_ID AND files.TYPE = '".Disk\Internals\ObjectTable::TYPE_FILE."' INNER JOIN b_file f ON f.ID = files.FILE_ID {$entityFieldsGroupSql} "; } elseif ( $isDiskAvailable && $ufType === Disk\Uf\VersionUserType::USER_TYPE_ID ) { $querySql = " SELECT DISTINCT SUM(f.FILE_SIZE) as FILE_SIZE, COUNT(DISTINCT f.ID) as FILE_COUNT, SUM(f.FILE_SIZE) as DISK_SIZE, COUNT(DISTINCT f.ID) as DISK_COUNT {$entityFieldsSql} FROM {$utmEntityTableName} ufsrc INNER JOIN ( {$entityFilterQuerySql} ) entity ON entity.ID = ufsrc.VALUE_ID INNER JOIN b_disk_attached_object attached ON attached.ID = ufsrc.VALUE_INT AND ufsrc.FIELD_ID = '{$ufId}' INNER JOIN b_disk_version versions ON versions.ID = attached.VERSION_ID INNER JOIN b_disk_object files ON files.ID = versions.OBJECT_ID AND files.ID = attached.OBJECT_ID AND files.ID = files.REAL_OBJECT_ID AND files.TYPE = '".Disk\Internals\ObjectTable::TYPE_FILE."' INNER JOIN b_file f ON f.ID = versions.FILE_ID {$entityFieldsGroupSql} "; } elseif ( $ufType === \CUserTypeFile::USER_TYPE_ID ) { $querySql = " SELECT SUM(f.FILE_SIZE) as FILE_SIZE, COUNT(DISTINCT f.ID) as FILE_COUNT, 0 as DISK_SIZE, 0 as DISK_COUNT {$entityFieldsSql} FROM {$utmEntityTableName} ufsrc INNER JOIN ( {$entityFilterQuerySql} ) entity ON entity.ID = ufsrc.VALUE_ID INNER JOIN b_file f ON f.ID = ufsrc.VALUE_INT AND ufsrc.FIELD_ID = '{$ufId}' {$entityFieldsGroupSql} "; } } } else { $ufEntityTableFieldName = $userField['FIELD_NAME']; $utsEntityTableName = 'b_uts_'.strtolower($ufName); if (isset(self::$tablesInformation[$utsEntityTableName])) { if ( $isDiskAvailable && $ufType === Disk\Uf\FileUserType::USER_TYPE_ID ) { $querySql = " SELECT SUM(f.FILE_SIZE) as FILE_SIZE, COUNT(DISTINCT f.ID) as FILE_COUNT, SUM(f.FILE_SIZE) as DISK_SIZE, COUNT(DISTINCT f.ID) as DISK_COUNT {$entityFieldsSql} FROM {$utsEntityTableName} ufsrc INNER JOIN ( {$entityFilterQuerySql} ) entity ON entity.ID = ufsrc.VALUE_ID INNER JOIN b_disk_attached_object attached ON attached.ID = cast(ufsrc.{$ufEntityTableFieldName} as UNSIGNED) and ufsrc.{$ufEntityTableFieldName} REGEXP '^[0-9]+$' INNER JOIN b_disk_object files ON files.ID = attached.OBJECT_ID AND files.ID = files.REAL_OBJECT_ID AND files.TYPE = '".Disk\Internals\ObjectTable::TYPE_FILE."' INNER JOIN b_file f ON f.ID = files.FILE_ID {$entityFieldsGroupSql} "; } elseif ( $isDiskAvailable && $ufType === Disk\Uf\VersionUserType::USER_TYPE_ID ) { $querySql = " SELECT SUM(f.FILE_SIZE) as FILE_SIZE, COUNT(DISTINCT f.ID) as FILE_COUNT, SUM(f.FILE_SIZE) as DISK_SIZE, COUNT(DISTINCT f.ID) as DISK_COUNT {$entityFieldsSql} FROM {$utsEntityTableName} ufsrc INNER JOIN ( {$entityFilterQuerySql} ) entity ON entity.ID = ufsrc.VALUE_ID INNER JOIN b_disk_attached_object attached ON attached.ID = cast(ufsrc.{$ufEntityTableFieldName} as UNSIGNED) and ufsrc.{$ufEntityTableFieldName} REGEXP '^[0-9]+$' INNER JOIN b_disk_version versions ON versions.ID = attached.VERSION_ID INNER JOIN b_disk_object files ON files.ID = versions.OBJECT_ID AND files.ID = attached.OBJECT_ID AND files.ID = files.REAL_OBJECT_ID AND files.TYPE = '".Disk\Internals\ObjectTable::TYPE_FILE."' INNER JOIN b_file f ON f.ID = versions.FILE_ID {$entityFieldsGroupSql} "; } elseif ( $ufType === \CUserTypeFile::USER_TYPE_ID ) { $querySql = " SELECT SUM(f.FILE_SIZE) as FILE_SIZE, COUNT(DISTINCT f.ID) as FILE_COUNT, 0 as DISK_SIZE, 0 as DISK_COUNT {$entityFieldsSql} FROM {$utsEntityTableName} ufsrc INNER JOIN ( {$entityFilterQuerySql} ) entity ON entity.ID = ufsrc.VALUE_ID INNER JOIN b_file f ON f.ID = cast(ufsrc.{$ufEntityTableFieldName} as UNSIGNED) and ufsrc.{$ufEntityTableFieldName} REGEXP '^[0-9]+$' {$entityFieldsGroupSql} "; } } } return $querySql; } /** * Gets SQL query code for disk attached entity. * * @param string $entityClass Entity class name. * @param string $diskConnector Connector class name. * @param array $entityGroupField Entity fields to group by. * * @return string */ protected function prepareDiskAttachedQuery($entityClass, $diskConnector, array $entityGroupField = array()) { if (self::isModuleAvailable('disk') !== true) { return ''; } /** * @var ORM\Data\DataManager $entityClass */ $entityQuery = $entityClass::query(); $entityEntity = $entityClass::getEntity(); $entityQuery->addSelect('ID'); // STAGE_SEMANTIC_ID if ($entityClass == Crm\QuoteTable::class) { Volume\Quote::registerStageField($entityQuery, '', 'QUOTE_STAGE_SEMANTIC_ID'); } if ($entityClass == Crm\InvoiceTable::class) { Volume\Invoice::registerStageField($entityQuery, '', 'INVOICE_STAGE_SEMANTIC_ID'); } // DATE if ( $entityClass == Crm\CompanyTable::class || $entityClass == Crm\ContactTable::class ) { $dayField = new ORM\Fields\ExpressionField( 'DATE_CREATE_SHORT', 'DATE(%s)', 'DATE_CREATE' ); $entityQuery->registerRuntimeField($dayField); } if ( $entityClass == Crm\InvoiceTable::class ) { $dayField = new ORM\Fields\ExpressionField( 'DATE_CREATE_SHORT', 'DATE(%s)', 'DATE_INSERT' ); $entityQuery->registerRuntimeField($dayField); } $entityFieldsSql = ''; $entityFieldsGroupSql = ''; $entityFields = array(); foreach ($entityGroupField as $alias => $field) { $entityQuery->addSelect($field, $alias); $entityFields[] = 'entity.'. $alias; } if ($this->prepareEntityFilter($entityQuery, $entityEntity)) { $entityFilterQuerySql = $entityQuery->getQuery(); if (count($entityFields) > 0) { $entityFieldsSql = ', '.implode(', ', $entityFields); $entityFieldsGroupSql = 'GROUP BY '.implode(', ', $entityFields); } } else { // cannot filter this Entity return ''; } $attachedEntitySql = Main\Application::getConnection()->getSqlHelper()->forSql($diskConnector); $querySql = " SELECT SUM(ver.SIZE) as FILE_SIZE, COUNT(ver.FILE_ID) as FILE_COUNT, SUM(ver.SIZE) as DISK_SIZE, COUNT(DISTINCT files.ID) as DISK_COUNT {$entityFieldsSql} FROM b_disk_version ver INNER JOIN b_disk_object files ON files.ID = ver.OBJECT_ID AND files.TYPE = '".Disk\Internals\ObjectTable::TYPE_FILE."' AND files.ID = files.REAL_OBJECT_ID INNER JOIN b_disk_attached_object attached ON attached.OBJECT_ID = files.ID AND (attached.VERSION_ID IS NULL OR attached.VERSION_ID = ver.ID) AND attached.ENTITY_TYPE = '{$attachedEntitySql}' INNER JOIN ( {$entityFilterQuerySql} ) entity ON entity.ID = attached.ENTITY_ID {$entityFieldsGroupSql} "; return $querySql; } /** * Gets SQL query code for disk attache linked by social network log. * * @param string $entityClass Entity class name. * @param string $eventEntityType Connector class name. * @param array $entityGroupField Entity fields to group by. * * @return string */ protected function prepareLiveFeedQuery($entityClass, $eventEntityType, array $entityGroupField = array()) { if (!(self::isModuleAvailable('socialnetwork') && self::isModuleAvailable('disk'))) { return ''; } /** * @var ORM\Data\DataManager $entityClass */ $entityQuery = $entityClass::query(); $entityEntity = $entityClass::getEntity(); $entityQuery->addSelect('ID'); // STAGE_SEMANTIC_ID if ($entityClass == Crm\QuoteTable::class) { Volume\Quote::registerStageField($entityQuery, '', 'QUOTE_STAGE_SEMANTIC_ID'); } if ($entityClass == Crm\InvoiceTable::class) { Volume\Invoice::registerStageField($entityQuery, '', 'INVOICE_STAGE_SEMANTIC_ID'); } // DATE if ( $entityClass == Crm\CompanyTable::class || $entityClass == Crm\ContactTable::class ) { $dayField = new ORM\Fields\ExpressionField( 'DATE_CREATE_SHORT', 'DATE(%s)', 'DATE_CREATE' ); $entityQuery->registerRuntimeField($dayField); } if ( $entityClass == Crm\InvoiceTable::class ) { $dayField = new ORM\Fields\ExpressionField( 'DATE_CREATE_SHORT', 'DATE(%s)', 'DATE_INSERT' ); $entityQuery->registerRuntimeField($dayField); } $entityFieldsSql = ''; $entityFieldsGroupSql = ''; $entityFields = array(); foreach ($entityGroupField as $alias => $field) { $entityQuery->addSelect($field, $alias); $entityFields[] = 'entity.'. $alias; } if ($this->prepareEntityFilter($entityQuery, $entityEntity)) { $entityFilterQuerySql = $entityQuery->getQuery(); if (count($entityFields) > 0) { $entityFieldsSql = ', '.implode(', ', $entityFields); $entityFieldsGroupSql = 'GROUP BY '.implode(', ', $entityFields); } } else { // cannot filter this Entity return ''; } $logTable = \Bitrix\Socialnetwork\LogTable::getTableName(); $helper = Main\Application::getConnection()->getSqlHelper(); $attachedEntitySql = $helper->forSql(Disk\Uf\SonetLogConnector::class); $eventEntitySql = $helper->forSql($eventEntityType); $querySql = " SELECT SUM(ver.SIZE) as FILE_SIZE, COUNT(ver.FILE_ID) as FILE_COUNT, SUM(ver.SIZE) as DISK_SIZE, COUNT(DISTINCT files.ID) as DISK_COUNT {$entityFieldsSql} FROM b_disk_version ver INNER JOIN b_disk_object files ON files.ID = ver.OBJECT_ID AND files.TYPE = '".Disk\Internals\ObjectTable::TYPE_FILE."' AND files.ID = files.REAL_OBJECT_ID INNER JOIN b_disk_attached_object attached ON attached.OBJECT_ID = files.ID AND (attached.VERSION_ID IS NULL OR attached.VERSION_ID = ver.ID) AND attached.ENTITY_TYPE = '{$attachedEntitySql}' INNER JOIN {$logTable} live_feed_log ON attached.ENTITY_ID = live_feed_log.ID AND live_feed_log.ENTITY_TYPE = '{$eventEntitySql}' INNER JOIN ( {$entityFilterQuerySql} ) entity ON entity.ID = live_feed_log.ENTITY_ID {$entityFieldsGroupSql} "; return $querySql; } /** * Method generates component action list for measure process. * * @param string $entityClass Entity class name. * @param string $dateFieldAlias Date field alias. * @param array $actionAliases Command alias. * * @return array */ protected function prepareRangeActionList($entityClass, $dateFieldAlias, $actionAliases) { $indicatorId = static::getIndicatorId(); $queueList = array(); $actionCommands = array( 'MEASURE_ENTITY', 'MEASURE_FILE', 'MEASURE_ACTIVITY', 'MEASURE_EVENT', ); $maxIdRange = -1; if (isset(static::$maxIdRangeCache[$entityClass])) { $maxIdRange = static::$maxIdRangeCache[$entityClass]; } else { $cache = new \CPHPCache(); if ($cache->startDataCache(3 * 3600, "{$entityClass}:{$indicatorId}:maxIdRange", 'crm/configs/volume')) { /** * @var ORM\Data\DataManager $entityClass */ $entityQuery = $entityClass::query(); $row0 = $entityQuery ->registerRuntimeField(new ORM\Fields\ExpressionField('CNT', 'COUNT(*)')) ->addSelect('CNT') ->exec() ->fetch(); if ($row0) { if ((int)$row0['CNT'] > 500000) { $maxIdRange = 100000; } elseif ((int)$row0['CNT'] > 100000) { $maxIdRange = 50000; } } static::$maxIdRangeCache[$entityClass] = $maxIdRange; $cache->endDataCache($maxIdRange); } else { $maxIdRange = $cache->getVars(); static::$maxIdRangeCache[$entityClass] = $maxIdRange; } } if ($maxIdRange > 0) { $cache = new \CPHPCache(); if ($cache->startDataCache(3 * 3600, "{$entityClass}:{$indicatorId}:queueList", 'crm/configs/volume')) { /** * @var ORM\Data\DataManager $entityClass */ $query = $entityClass::query(); $month = new ORM\Fields\ExpressionField('YY', "YEAR(%s)", $dateFieldAlias); $query->registerRuntimeField($month)->addSelect('YY'); $month = new ORM\Fields\ExpressionField('MM', "MONTH(%s)", $dateFieldAlias); $query->registerRuntimeField($month)->addSelect('MM'); $month = new ORM\Fields\ExpressionField('DD', "DAY(%s)", $dateFieldAlias); $query->registerRuntimeField($month)->addSelect('DD'); $border = new ORM\Fields\ExpressionField('BRDR', 'MAX(%s)', 'ID'); $query->registerRuntimeField($border)->addSelect('BRDR'); $counter = new ORM\Fields\ExpressionField('CNT', 'COUNT(*)'); $query->registerRuntimeField($counter)->addSelect('CNT'); $query->setGroup(array('YY', 'MM', 'DD'))->setOrder(array('BRDR' => 'ASC')); $res = $query->exec(); if ($row = $res->fetch()) { $count = 0; $appendQueueList = function($range) use ($actionCommands, $actionAliases, &$queueList, $indicatorId) { foreach ($actionCommands as $command) { if (isset($actionAliases[$command])) { $queueList[] = array( 'indicatorId' => $indicatorId, 'action' => $actionAliases[$command], 'range' => $range, ); } } }; $prevId = null; do { if ( $row['CNT'] >= $maxIdRange || ($count + (int)$row['CNT']) >= $maxIdRange * 1.3 || $count >= $maxIdRange ) { $range = ''; if ($prevId > 0) { $range .= $prevId; } $range .= '-'.(int)$row['BRDR']; $appendQueueList($range); $count = 0; $prevId = (int)$row['BRDR']; continue; } $count += (int)$row['CNT']; } while ($row = $res->fetch()); if ($count >= 0 && $prevId > 0) { $range = $prevId.'-'; $appendQueueList($range); } } $cache->endDataCache($queueList); } else { $queueList = $cache->getVars(); } } else { foreach ($actionCommands as $command) { if (isset($actionAliases[$command])) { $queueList[] = array( 'indicatorId' => $indicatorId, 'action' => $actionAliases[$command], ); } } } return $queueList; } /** * Method generates component action list for measure process. * * @param string $entityClass Entity class name. * @param string $dateFieldAlias Date field alias. * @param array $actionAliases Command alias. * * @return array */ protected function prepareDateActionList($entityClass, $dateFieldAlias, $actionAliases) { $indicatorId = static::getIndicatorId(); $queueList = array(); $actionCommands = array( 'MEASURE_ENTITY', 'MEASURE_FILE', 'MEASURE_ACTIVITY', 'MEASURE_EVENT', ); /** * @var ORM\Data\DataManager $entityClass */ $query = $entityClass::query(); $dateMin = new ORM\Fields\ExpressionField('DATE_MIN', "DATE_FORMAT(MIN(%s), '%%Y-%%m-%%d')", $dateFieldAlias); $query->registerRuntimeField($dateMin)->addSelect('DATE_MIN'); $monthCount = new ORM\Fields\ExpressionField('MONTHS', 'TIMESTAMPDIFF(MONTH, MIN(%s), MAX(%s))', array($dateFieldAlias, $dateFieldAlias)); $query->registerRuntimeField($monthCount)->addSelect('MONTHS'); $res = $query->exec(); if ($row = $res->fetch()) { list($dateSplitPeriod, $dateSplitPeriodUnits) = $this->getDateSplitPeriod(); $dateMin = new Main\Type\DateTime($row['DATE_MIN'], 'Y-m-d'); $months = $row['MONTHS']; while ($months >= 0) { $period = $dateMin->format('Y.m'); $dateMin->add("$dateSplitPeriod $dateSplitPeriodUnits"); $period .= '-'; $period .= $dateMin->format('Y.m'); $months -= $dateSplitPeriod; foreach ($actionCommands as $command) { if (isset($actionAliases[$command])) { $queueList[] = array( 'indicatorId' => $indicatorId, 'action' => $actionAliases[$command], 'period' => $period, ); } } } } return $queueList; } /** * Sets owner id. * @param int $ownerId User id. * @return void */ public function setOwner($ownerId) { $this->ownerId = $ownerId; } /** * Gets owner id. * @return int|null */ public function getOwner() { return $this->ownerId > 0 ? $this->ownerId : 0; } /** * Adds an array of errors to the collection. * * @param Main\Error[] | Main\Error $errors Raised error. * @return void */ public function collectError($errors) { if (!($this->errorCollection instanceof Main\ErrorCollection)) { $this->errorCollection = new Main\ErrorCollection(); } if (is_array($errors)) { $this->errorCollection->add($errors); } else { $this->errorCollection->add(array($errors)); } } /** * Returns errors list. * * @implements Volume\IVolumeClear * @return Main\Error|null */ public function getLastError() { if ($this->errorCollection instanceof Main\ErrorCollection) { $offset = $this->errorCollection->count() - 1; return $this->errorCollection->offsetGet($offset); } return null; } /** * Returns process offset. * * @implements Volume\IVolumeClear * @p * @return int */ public function getProcessOffset() { return $this->processOffset; } /** * Setup process offset. * * @implements Volume\IVolumeClear * @param int $offset Offset position. * @return void */ public function setProcessOffset($offset) { $this->processOffset = $offset; } /** * Sets dropped count of entity attachments. * * @implements Volume\IVolumeClearFile * @param int $count Amount to set. * @return void */ public function setDroppedFileCount($count) { $this->droppedFileCount = $count; } /** * Returns dropped count of entity attachments. * * @implements Volume\IVolumeClearFile * @param int $count Amount to increment. * @return void */ public function incrementDroppedFileCount($count = 1) { $this->droppedFileCount += $count; } /** * Returns dropped count of entity attachments. * @implements Volume\IVolumeClearFile * * @return int */ public function getDroppedFileCount() { return $this->droppedFileCount; } /** * Sets dropped count of entities. * * @implements Volume\IVolumeClear * @param int $count Amount to set. * @return void */ public function setDroppedEntityCount($count) { $this->droppedCount = $count; } /** * Returns dropped count of entities. * * @implements Volume\IVolumeClear * @param int $count Amount to increment. * @return void */ public function incrementDroppedEntityCount($count = 1) { $this->droppedCount += $count; } /** * Returns dropped count of entities. * * @implements Volume\IVolumeClear * @return int */ public function getDroppedEntityCount() { return $this->droppedCount; } /** * Returns error count. * * @implements Volume\IVolumeClear * @return int */ public function getFailCount() { return $this->failCount; } /** * Sets error count. * * @implements Volume\IVolumeClear * @param int $count Amount to set. * @return void */ public function setFailCount($count) { $this->failCount = $count; } /** * Returns error count. * * @implements Volume\IVolumeClearEvent * @param int $count Amount to increment. * @return void */ public function incrementFailCount($count = 1) { $this->failCount += $count; } /** * Start up timer. * * @implements Volume\IVolumeClear * @param int $timeLimit Time limit. * @return void */ public function startTimer($timeLimit = 25) { $this->timeLimit = $timeLimit; if (defined('START_EXEC_TIME') && START_EXEC_TIME > 0) { $this->startTime = (int)START_EXEC_TIME; } else { $this->startTime = time(); } } /** * Tells true if time limit reached. * * @implements Volume\IVolumeClear * @return boolean */ public function hasTimeLimitReached() { if ($this->timeLimit > 0) { if ($this->timeLimitReached) { return true; } if ((time() - $this->startTime) >= $this->timeLimit) { $this->timeLimitReached = true; return true; } } return false; } /** * Returns count of files in disk folder. * * @param Disk\Folder $folder Disk folder to analize. * @param array $filter Additional filter for file selection. * * @return int * @throws Main\ObjectPropertyException * @throws Main\SystemException */ protected function countDiskFiles(Disk\Folder $folder, $filter = array()) { $count = 0; if (self::isModuleAvailable('disk')) { if ($folder instanceof Disk\Folder) { $filter['=STORAGE_ID'] = $folder->getStorageId(); $filter['=PATH_CHILD.PARENT_ID'] = $folder->getId(); $filter['=TYPE'] = Disk\Internals\ObjectTable::TYPE_FILE; $count = Disk\Internals\ObjectTable::getCount($filter); } } return $count; } /** * Performs dropping entity attachments. * * @param Disk\Folder $folder Disk folder to analize. * @param array $filter Additional filter for file selection. * * @return boolean * @throws Main\ArgumentException * @throws Main\ObjectPropertyException * @throws Main\SystemException */ protected function clearDiskFiles(Disk\Folder $folder, $filter = array()) { if (!self::isModuleAvailable('disk')) { return false; } if (!($folder instanceof Disk\Folder)) { return false; } $filter['=STORAGE_ID'] = $folder->getStorageId(); $filter['=PATH_CHILD.PARENT_ID'] = $folder->getId(); $filter['=TYPE'] = Disk\Internals\ObjectTable::TYPE_FILE; if ($this->getProcessOffset() > 0) { $filter['>ID'] = $this->getProcessOffset(); } $objectList = Disk\Internals\ObjectTable::getList(array( 'filter' => $filter, 'order' => array( 'PATH_CHILD.DEPTH_LEVEL' => 'DESC', 'ID' => 'ASC', ), 'limit' => static::MAX_FILE_PER_INTERACTION, )); $success = true; foreach ($objectList as $row) { $file = Disk\BaseObject::buildFromArray($row); if($file instanceof Disk\File) { /** @var Disk\File $file */ $securityContext = $this->getDiskSecurityContext($file); if($file->canDelete($securityContext)) { if ($this->deleteDiskFile($file)) { $this->incrementDroppedFileCount(); } else { //$this->collectError(new Error('Deletion failed with file #'. $file->getId(), self::ERROR_DELETION_FAILED)); $this->incrementFailCount(); } } else { $this->collectError(new Error('Access denied to file #'. $file->getId(), self::ERROR_PERMISSION_DENIED)); $this->incrementFailCount(); } } $this->setProcessOffset($row['ID']); if ($this->hasTimeLimitReached()) { $success = false; break; } } return $success; } /** * Returns disk security context. * @param Disk\BaseObject $object File or folder. * @return Disk\Security\SecurityContext */ protected function getDiskSecurityContext($object) { static $securityContext = null; $userId = $this->getUser()->getId(); if (!($securityContext instanceof Disk\Security\SecurityContext)) { if (Disk\User::isCurrentUserAdmin()) { $securityContext = new Disk\Security\FakeSecurityContext($userId); } else { $securityContext = $object->getStorage()->getSecurityContext($userId); } } return $securityContext; } /** * Deletes file. * @param Disk\File $file File to drop. * @return boolean */ protected function deleteDiskFile(Disk\File $file) { $userId = $this->getUser()->getId(); if(!$file->delete($userId)) { $this->collectError($file->getErrors()); return false; } return true; } }
| ver. 1.4 |
Github
|
.
| PHP 7.4.8 | Генерация страницы: 0 |
proxy
|
phpinfo
|
Настройка