uawdijnntqw1x1x1
IP : 18.222.178.70
Hostname : axolotl
Kernel : Linux axolotl 4.9.0-13-amd64 #1 SMP Debian 4.9.228-1 (2020-07-05) x86_64
Disable Function : pcntl_alarm,pcntl_fork,pcntl_waitpid,pcntl_wait,pcntl_wifexited,pcntl_wifstopped,pcntl_wifsignaled,pcntl_wexitstatus,pcntl_wtermsig,pcntl_wstopsig,pcntl_signal,pcntl_signal_dispatch,pcntl_get_last_error,pcntl_strerror,pcntl_sigprocmask,pcntl_sigwaitinfo,pcntl_sigtimedwait,pcntl_exec,pcntl_getpriority,pcntl_setpriority,
OS : Linux
PATH:
/
var
/
www
/
axolotl
/
data
/
www
/
nn.axolotls.ru
/
bitrix
/
modules
/
tasks
/
lib
/
manager
/
task.php
/
/
<? /** * Bitrix Framework * @package bitrix * @subpackage sale * @copyright 2001-2015 Bitrix * * @access private * * This class should be used in components, inside agent functions, in rest, ajax and more, bringing unification to all places and processes */ namespace Bitrix\Tasks\Manager; use Bitrix\Tasks\Access\ActionDictionary; use Bitrix\Tasks\Comments; use Bitrix\Tasks\Integration\Extranet; use Bitrix\Tasks\Integration\SocialNetwork\Group; use Bitrix\Tasks\Integration\Timeman; use Bitrix\Tasks\Internals\Task\ParameterTable; use Bitrix\Tasks\Manager\Task\Accomplice; use Bitrix\Tasks\Manager\Task\Auditor; use Bitrix\Tasks\Manager\Task\Checklist; use Bitrix\Tasks\Manager\Task\ElapsedTime; use Bitrix\Tasks\Manager\Task\Log; use Bitrix\Tasks\Manager\Task\Originator; use Bitrix\Tasks\Manager\Task\Parameter; use Bitrix\Tasks\Manager\Task\ParentTask; use Bitrix\Tasks\Manager\Task\Project; use Bitrix\Tasks\Manager\Task\ProjectDependence; use Bitrix\Tasks\Manager\Task\RelatedTask; use Bitrix\Tasks\Manager\Task\Reminder; use Bitrix\Tasks\Manager\Task\Responsible; use Bitrix\Tasks\Manager\Task\Tag; use Bitrix\Tasks\Manager\Task\Template; use Bitrix\Tasks\CheckList\Task\TaskCheckListFacade; use Bitrix\Tasks\Util\User; use Bitrix\Tasks\Util\Error\Collection; use Bitrix\Tasks\Util\UserField\Task as UserField; final class Task extends \Bitrix\Tasks\Manager { const LIMIT_PAGE_SIZE = 50; // standard CRUD /** * @param int $userId * @param mixed[] $data * @param mixed[] $parameters * <li>PUBLIC_MODE * <li>SOURCE * <li> TYPE (TEMPLATE or TASK) * <li> ID */ public static function add($userId, array $data, array $parameters = array('PUBLIC_MODE' => false, 'RETURN_ENTITY' => false)) { $errors = static::ensureHaveErrorCollection($parameters); $task = null; $can = array(); if ($parameters['PUBLIC_MODE']) { $data = static::filterData($data, static::getFieldMap(), $errors); } $parameters['ANALYTICS_DATA'] = static::getAnalyticsData($data); if ($errors->checkNoFatals()) { $cacheAFWasDisabled = \CTasks::disableCacheAutoClear(); $notifADWasDisabled = \CTaskNotifications::disableAutoDeliver(); $task = static::doAdd($userId, $data, $parameters); if ($notifADWasDisabled) { \CTaskNotifications::enableAutoDeliver(); } if ($cacheAFWasDisabled) { \CTasks::enableCacheAutoClear(); } if ($errors->checkNoFatals()) { $data = array('ID' => $task->getId()); if ($parameters[ 'RETURN_ENTITY' ]) { $data = $task->getData(false); $data[ static::ACT_KEY ] = $can = static::translateAllowedActionNames($task->getAllowedActions(true)); } } } return array( 'TASK' => $task, 'ERRORS' => $errors, 'DATA' => $data, 'CAN' => $can ); } private static function getFieldMap() { // READ, WRITE, SORT, FILTER, DATE $fieldMap = \CTasks::getPublicFieldMap(); $fieldMap[ 'REPLICATE' ] = array(1, 1, 0, 0, 0); // not allowed in rest, but allowed here $fieldMap[ 'MULTITASK' ] = array(1, 1, 0, 0, 0); // not allowed in rest, but allowed here $fieldMap[ 'ADD_TO_FAVORITE' ] = array(0, 1, 0, 0, 0); // virtual, for add() only $fieldMap[ 'ADD_TO_TIMEMAN' ] = array(0, 1, 0, 0, 0); // virtual, for add() only $fieldMap[ 'RESPONSIBLES' ] = array(0, 1, 0, 0, 0); // just for compatibility return $fieldMap; } private static function doAdd($userId, array $data, array $parameters) { $userId = (int)$userId; $errors = static::ensureHaveErrorCollection($parameters); $data = static::normalizeData($data); static::inviteMembers($data, $errors); static::adaptSet($data); static::ensureDatePlanChangeAllowed($userId, $data); static::setDefaultUFValues($userId, $data); $task = \CTaskItem::add(static::stripSubEntityData($data), $userId, $parameters); $taskId = $task->getId(); if ($taskId) { $commentPoster = Comments\Task\CommentPoster::getInstance($taskId, $userId); $commentPoster->enableDeferredPostMode(); $commentPoster->clearComments(); if ( $data['ADD_TO_TIMEMAN'] === 'Y' && $userId === (int)$data['RESPONSIBLE_ID'] && $userId === User::getId() && !Extranet\User::isExtranet($userId) ) { // add the task to planner only if the user this method executed under is current and responsible for the task \CTaskPlannerMaintance::plannerActions(['add' => [$taskId]]); } if ($data['ADD_TO_FAVORITE'] == "Y") { $task->addToFavorite(); } // add sub-entities (SE_*) $subEntityParams = array_merge($parameters, ['MODE' => static::MODE_ADD]); if (array_key_exists(Reminder::getCode(true), $data)) { Reminder::manageSet($userId, $taskId, $data[ Reminder::getCode(true) ], $subEntityParams); } if (array_key_exists(ProjectDependence::getCode(true), $data)) { ProjectDependence::manageSet($userId, $taskId, $data[ ProjectDependence::getCode(true) ], $subEntityParams); } if (array_key_exists(Checklist::getCode(true), $data)) { TaskCheckListFacade::merge( $taskId, $userId, $data[CheckList::getCode(true)], ['analyticsData' => $parameters['ANALYTICS_DATA']] ); } if (array_key_exists('SE_PARAMETER', $data)) { Parameter::manageSet($userId, $taskId, $data[ 'SE_PARAMETER' ], $subEntityParams); } Template::manageTaskReplication($userId, $taskId, $data, $subEntityParams); } return $task; } public static function normalizeData($data) { if (!is_array($data) || empty($data)) { return array(); } foreach ($data as $k => $v) { if ($seName = static::checkIsSubEntityKey($k)) { $fName = __NAMESPACE__ . '\\Task\\' . $seName . '::normalizeData'; if (is_callable($fName)) { $data[ $k ] = call_user_func_array($fName, array($v)); } } } return $data; } private static function inviteMembers(&$data, Collection $errors) { //Originator::inviteMembers($data, $errors); // we may not invite originator Auditor::inviteMembers($data, $errors); Accomplice::inviteMembers($data, $errors); Responsible::inviteMembers($data, $errors); } private static function adaptSet(&$data) { Originator::adaptSet($data); Auditor::adaptSet($data); Accomplice::adaptSet($data); Tag::adaptSet($data); CheckList::adaptSet($data); RelatedTask::adaptSet($data); ParentTask::adaptSet($data); Project::adaptSet($data); // special case: responsibles Responsible::adaptSet($data); if (is_array($data[ Responsible::getLegacyFieldName() ])) { $data[ Responsible::getLegacyFieldName() ] = array_shift($data[ Responsible::getLegacyFieldName() ]); } } // specific functionality private static function ensureDatePlanChangeAllowed($userId, array &$data) { $projdepKey = ProjectDependence::getCode(true); // smth is meant to be added in project dependency, thus we must enable ALLOW_CHANGE_DEADLINE for the task // todo: this is required for making dependencies in case of task update with rights loose. remove this when AUTHOR_ID field introduced if (array_key_exists($projdepKey, $data) && !empty($data[ $projdepKey ]) && $userId == $data[ 'RESPONSIBLE_ID' ]) { $data[ 'ALLOW_CHANGE_DEADLINE' ] = 'Y'; } } private static function setDefaultUFValues($userId, array &$data) { $scheme = UserField::getScheme(0, $userId); foreach ($scheme as $field => $desc) { if (!array_key_exists($field, $data)) { $default = UserField::getDefaultValue($field, $userId); if ($default !== null) { $data[ $field ] = $default; } } } } private static function translateAllowedActionNames($can) { $newCan = array(); if (is_array($can)) { foreach ($can as $act => $flag) { $newCan[ str_replace('ACTION_', '', $act) ] = $flag; } static::replaceKey($newCan, 'CHANGE_DIRECTOR', 'EDIT.ORIGINATOR'); static::replaceKey($newCan, 'CHECKLIST_REORDER_ITEMS', 'CHECKLIST.REORDER'); static::replaceKey($newCan, 'ELAPSED_TIME_ADD', 'ELAPSEDTIME.ADD'); static::replaceKey($newCan, 'START_TIME_TRACKING', 'DAYPLAN.TIMER.TOGGLE'); // todo: when mobile stops using this fields, remove the third argument here static::replaceKey($newCan, 'CHANGE_DEADLINE', 'EDIT.PLAN', false); // used in mobile already static::replaceKey($newCan, 'CHECKLIST_ADD_ITEMS', 'CHECKLIST.ADD', false); // used in mobile already static::replaceKey($newCan, 'ADD_FAVORITE', 'FAVORITE.ADD', false); // used in mobile already static::replaceKey($newCan, 'DELETE_FAVORITE', 'FAVORITE.DELETE', false); // used in mobile already } return $newCan; } private static function replaceKey(array &$data, $from, $to, $dropFrom = true) { if (array_key_exists($from, $data)) { $data[ $to ] = $data[ $from ]; if ($dropFrom) { unset($data[ $from ]); } } } // private methods public static function update($userId, $taskId, array $data, array $parameters = array('PUBLIC_MODE' => false, 'RETURN_ENTITY' => false)) { $errors = static::ensureHaveErrorCollection($parameters); $task = null; $can = array(); if ($parameters[ 'PUBLIC_MODE' ]) { $data = static::filterData($data, static::getFieldMap(), $errors); } if ($errors->checkNoFatals()) { $cacheAFWasDisabled = \CTasks::disableCacheAutoClear(); $notifADWasDisabled = \CTaskNotifications::disableAutoDeliver(); $updateParams = array( 'TASK_ACTION_UPDATE_PARAMETERS' => array( 'THROTTLE_MESSAGES' => $parameters[ 'THROTTLE_MESSAGES' ] ), 'PUBLIC_MODE' => $parameters[ 'PUBLIC_MODE' ], 'ERRORS' => $errors, 'ANALYTICS_DATA' => static::getAnalyticsData($data), ); $task = static::doUpdate($userId, $taskId, $data, $updateParams); if ($notifADWasDisabled) { \CTaskNotifications::enableAutoDeliver(); } if ($cacheAFWasDisabled) { \CTasks::enableCacheAutoClear(); } if ($errors->checkNoFatals()) { $data = array('ID' => $task->getId()); if ($parameters[ 'RETURN_ENTITY' ]) { $data = $task->getData(false); $data[ static::ACT_KEY ] = $can = static::translateAllowedActionNames($task->getAllowedActions(true)); } } } return array( 'TASK' => $task, 'ERRORS' => $errors, 'DATA' => $data, 'CAN' => $can ); } private static function doUpdate($userId, $taskId, array $data, array $parameters) { $errors = static::ensureHaveErrorCollection($parameters); $task = static::getTask($userId, $taskId); $data = static::normalizeData($data); static::inviteMembers($data, $errors); static::adaptSet($data); if (!is_array($parameters[ 'TASK_ACTION_UPDATE_PARAMETERS' ])) { $parameters[ 'TASK_ACTION_UPDATE_PARAMETERS' ] = array(); } static::ensureDatePlanChangeAllowed($userId, $data); $cleanData = static::stripSubEntityData($data); $commentPoster = Comments\Task\CommentPoster::getInstance($taskId, $userId); $commentPoster->clearComments(); $action = ActionDictionary::ACTION_TASK_EDIT; // under some conditions we may loose rights (for edit or read, or both) during update, so a little trick is needed $canEditBefore = $task->checkAccess($action); // get our rights before doing anything if (!empty($cleanData)) { // spike: save parameters before CTasks::Update(), at low level, to be sure worker will work out correctly // todo: get rid of this if ($canEditBefore && array_key_exists('SE_PARAMETER', $data) && is_array($data[ 'SE_PARAMETER' ])) { \Bitrix\Tasks\Item\Task\Parameter::deleteByParent($taskId, array()); foreach ($data[ 'SE_PARAMETER' ] as $parameter) { unset($parameter[ 'ID' ]); $parameter[ 'TASK_ID' ] = $taskId; ParameterTable::add($parameter); } } $commentPoster->enableDeferredPostMode(); $task->update($cleanData, $parameters['TASK_ACTION_UPDATE_PARAMETERS']); // do not check return result, because method will throw an exception on error } $canReadAfter = $task->checkCanRead(); $canEditAfter = $canReadAfter && $task->checkAccess($action); $rightsLost = $canEditBefore && !$canEditAfter; $adminUserId = \Bitrix\Tasks\Util\User::getAdminId(); // if we have had rights before, but have lost them now, do the rest of update under superuser`s rights, or else continue normally // todo: instead of replacing userId make option "skipRights under current user" $continueAs = $rightsLost ? $adminUserId : $userId; if (!$canReadAfter) // at least become an auditor for that task { $sameTask = \CTaskItem::getInstance($taskId, $adminUserId); $sameTask->startWatch($userId); } // update sub-entities (SE_*) $subEntityParams = array_merge( $parameters, array('MODE' => static::MODE_UPDATE, 'ERROR' => $errors) ); if (array_key_exists(Reminder::getCode(true), $data)) { Reminder::manageSet($userId, $taskId, $data[ Reminder::getCode(true) ], $subEntityParams); } if (array_key_exists(ProjectDependence::getCode(true), $data)) { ProjectDependence::manageSet($continueAs, $taskId, $data[ ProjectDependence::getCode(true) ], $subEntityParams); } if (array_key_exists(Checklist::getCode(true), $data)) { TaskCheckListFacade::merge( $taskId, $continueAs, $data[Checklist::getCode(true)], ['analyticsData' => $parameters['ANALYTICS_DATA']] ); } if (array_key_exists('SE_PARAMETER', $data)) { Parameter::manageSet($userId, $taskId, $data[ 'SE_PARAMETER' ], $subEntityParams); } Template::manageTaskReplication($userId, $taskId, $data, $subEntityParams); $commentPoster->postComments(); $commentPoster->clearComments(); return $task; } public static function convertFromItem($item) { if (!\Bitrix\Tasks\Item::isA($item)) { return array(); } $data = $item->getArray(); // do some transformations... Originator::formatSet($data); Auditor::formatSet($data); Accomplice::formatSet($data); ParentTask::formatSet($data); Project::formatSet($data); Tag::formatSet($data); RelatedTask::formatSet($data); // special case for checklist... i hate special cases... CheckList::parseSet($data); return $data; } public static function makeItem($data, $userId = 0) { Originator::adaptSet($data); Auditor::adaptSet($data); Accomplice::adaptSet($data); ParentTask::adaptSet($data); Project::adaptSet($data); Tag::adaptSet($data); RelatedTask::adaptSet($data); return new \Bitrix\Tasks\Item\Task($data, $userId); } public static function get($userId, $taskId, array $parameters = array()) { $errors = static::ensureHaveErrorCollection($parameters); // todo: filterArguments() and filterResult() here on public mode? $data = static::getBasicData($userId, $taskId, $parameters); $can = array(); if ($errors->checkNoFatals()) { $can = array(static::ACT_KEY => &$data[ static::ACT_KEY ]); // for compatibility // select sub-entity related data if (!is_array($parameters[ 'ENTITY_SELECT' ])) { // by default none is selected $parameters[ 'ENTITY_SELECT' ] = array(); // could be of static::getLegalSubEntities() } $entitySelect = array_flip($parameters[ 'ENTITY_SELECT' ]); Originator::formatSet($data); Auditor::formatSet($data); Accomplice::formatSet($data); ParentTask::formatSet($data); Project::formatSet($data); // special case: responsibles $data[ Responsible::getCode(true) ] = array(array('ID' => $data[ 'RESPONSIBLE_ID' ])); $code = Tag::getCode(true); if (isset($entitySelect[ Tag::getCode() ])) { $mgrResult = Tag::getList($userId, $taskId); $data[ $code ] = $mgrResult[ 'DATA' ]; if (!empty($mgrResult[ 'CAN' ])) { $can[ $code ] = $mgrResult[ 'CAN' ]; } Tag::adaptSet($data); // for compatibility } $code = Checklist::getCode(true); if (isset($entitySelect[ 'CHECKLIST' ])) { $mgrResult = TaskCheckListFacade::getItemsForEntity($taskId, $userId); $data[$code] = $mgrResult; foreach ($mgrResult as $id => $item) { $can[$code][$id]['ACTION'] = $item['ACTION']; } } if (isset($entitySelect[ 'REMINDER' ])) { $mgrResult = Reminder::getListByParentEntity($userId, $taskId, $parameters); $data[ static::SE_PREFIX . 'REMINDER' ] = $mgrResult[ 'DATA' ]; if (!empty($mgrResult[ 'CAN' ])) { $can[ static::SE_PREFIX . 'REMINDER' ] = $mgrResult[ 'CAN' ]; } } if (isset($entitySelect[ 'LOG' ])) { $mgrResult = Log::getListByParentEntity($userId, $taskId, $parameters); $data[ static::SE_PREFIX . 'LOG' ] = $mgrResult[ 'DATA' ]; if (!empty($mgrResult[ 'CAN' ])) { $can[ static::SE_PREFIX . 'LOG' ] = $mgrResult[ 'CAN' ]; } } if (isset($entitySelect[ 'ELAPSEDTIME' ])) { $mgrResult = ElapsedTime::getListByParentEntity($userId, $taskId, $parameters); $data[ static::SE_PREFIX . 'ELAPSEDTIME' ] = $mgrResult[ 'DATA' ]; if (!empty($mgrResult[ 'CAN' ])) { $can[ static::SE_PREFIX . 'ELAPSEDTIME' ] = $mgrResult[ 'CAN' ]; } } if (isset($entitySelect[ 'PROJECTDEPENDENCE' ])) { $mgrResult = ProjectDependence::getListByParentEntity($userId, $taskId, array_merge($parameters, array( 'TYPE' => ProjectDependence::INGOING, 'DIRECT' => true, 'DEPENDS_ON_DATA' => true ))); $data[ static::SE_PREFIX . 'PROJECTDEPENDENCE' ] = $mgrResult[ 'DATA' ]; if (!empty($mgrResult[ 'CAN' ])) { $can[ static::SE_PREFIX . 'PROJECTDEPENDENCE' ] = $mgrResult[ 'CAN' ]; } } if (isset($entitySelect[ 'TEMPLATE' ])) { if ($data[ 'REPLICATE' ] == 'Y') { $template = Template::getByParentTask($userId, $taskId); $data[ static::SE_PREFIX . 'TEMPLATE' ] = $template[ 'DATA' ]; } } if (isset($entitySelect[ 'TEMPLATE.SOURCE' ])) { if (intval($data[ 'FORKED_BY_TEMPLATE_ID' ])) { $template = Template::get($userId, intval($data[ 'FORKED_BY_TEMPLATE_ID' ])); // todo: remove this $tData = $template[ 'DATA' ]; if (!empty($tData)) { $tData = array( 'ID' => $tData[ 'ID' ], 'TITLE' => $tData[ 'TITLE' ], 'TASK_ID' => $tData[ 'TASK_ID' ], 'TPARAM_TYPE' => $tData[ 'TPARAM_TYPE' ], 'REPLICATE_PARAMS' => $tData[ 'REPLICATE_PARAMS' ] ); } $data[ static::SE_PREFIX . 'TEMPLATE.SOURCE' ] = $tData; } } if (isset($entitySelect[ 'RELATEDTASK' ])) { $mgrResult = RelatedTask::getListByParentEntity($userId, $taskId, $parameters); $data[ static::SE_PREFIX . 'RELATEDTASK' ] = $mgrResult[ 'DATA' ]; if (!empty($mgrResult[ 'CAN' ])) { $can[ static::SE_PREFIX . 'RELATEDTASK' ] = $mgrResult[ 'CAN' ]; } } if (isset($entitySelect[ 'TIMEMANAGER' ]) || isset($entitySelect[ 'DAYPLAN' ])) // 'TIMEMANAGER' condition left for compatibility { $subData = array($data[ 'ID' ] => &$data); $subCan = array($data[ 'ID' ] => &$can); static::injectDayPlanFields($userId, $parameters, $subData, $subCan); } } return array( 'DATA' => $data, 'CAN' => $can, // for compatibility 'ERRORS' => $errors ); } private static function getBasicData($userId, $taskId, array $parameters) { $data = array(); $denied = false; try { $task = static::getTask($userId, $taskId); $taskParameters = array(); if ($task !== null) { $data = $task->getData(!!$parameters[ 'ESCAPE_DATA' ]); $data[ static::ACT_KEY ] = static::translateAllowedActionNames($task->getAllowedActions(true)); if (!intval($data[ 'FORUM_ID' ])) { $data[ 'FORUM_ID' ] = \CTasksTools::getForumIdForIntranet(); } $data[ 'COMMENTS_COUNT' ] = intval($data[ 'COMMENTS_COUNT' ]); // get task parameters $res = ParameterTable::getList(array('filter' => array('=TASK_ID' => $taskId))); while ($item = $res->fetch()) { $taskParameters[] = $item; } } if ($parameters[ 'DROP_PRIMARY' ]) { unset($data[ 'ID' ]); $data[ static::ACT_KEY ] = static::getFullRights($userId); } $data[ 'SE_PARAMETER' ] = $taskParameters; } catch (\TasksException $e) // todo: get rid of this annoying catch by making \Bitrix\Tasks\*Exception classes inherited from TasksException (dont forget about code) { if ($e->checkOfType(\TasksException::TE_TASK_NOT_FOUND_OR_NOT_ACCESSIBLE)) { $denied = true; } else { throw $e; // let it log } } catch (\Bitrix\Tasks\AccessDeniedException $e) // task not found or not accessible { $denied = true; } if ($denied) { $parameters[ 'ERRORS' ]->add('ACCESS_DENIED.NO_TASK', 'Task not found or not accessible'); } return $data; } public static function getFullRights($userId) { // get rights as creator, just EDIT for now return array( 'EDIT' => true, 'EDIT.PLAN' => true, 'CHECKLIST.ADD' => true, 'CHECKLIST.REORDER' => true, 'EDIT.ORIGINATOR' => true, 'FAVORITE.ADD' => true, 'FAVORITE.DELETE' => false, 'DAYPLAN.ADD' => (!Extranet\User::isExtranet($userId) && Timeman::canUse()) ); } private static function injectDayPlanFields($userId, array $parameters, array &$data, array &$can) { if (empty($data)) { return; } $extranetSite = Extranet::isExtranetSite(); $extranetUser = Extranet\User::isExtranet($userId); // no dayplan for extranet site, even if intranet user goes to extranet site $plan = array(); if (!$extranetSite && !$extranetUser) { $plan = \CTaskPlannerMaintance::getCurrentTasksList(); if (is_array($plan) && !empty($plan)) { $plan = array_flip($plan); } } foreach ($data as &$task) { $inDayPlan = false; $canAddToPlan = false; if ($task[ "RESPONSIBLE_ID" ] == $userId || (is_array($task[ 'ACCOMPLICES' ]) && in_array($userId, $task[ 'ACCOMPLICES' ]))) { $canAddToPlan = true; // if in day plan already if (isset($plan[ $task[ 'ID' ] ])) { $inDayPlan = true; $canAddToPlan = false; } } $task[ 'IN_DAY_PLAN' ] = $inDayPlan; $task[ 'TIME_ELAPSED' ] = intval($task[ 'TIME_SPENT_IN_LOGS' ]); $task[ 'TIMER_IS_RUNNING_FOR_CURRENT_USER' ] = false; $can[ $task[ 'ID' ] ][ 'ACTION' ][ 'ADD_TO_DAY_PLAN' ] = $can[ $task[ 'ID' ] ][ 'ACTION' ][ 'DAYPLAN.ADD' ] = !$extranetUser && $canAddToPlan && Timeman::canUse(); } unset($task); // current timer $runningTaskData = \CTaskTimerManager::getInstance($userId)->getRunningTask(false); foreach ($data as $k => &$task) { if ($task[ 'ID' ] == $runningTaskData[ 'TASK_ID' ] && $task[ 'ALLOW_TIME_TRACKING' ] == 'Y') { $task[ 'TIME_ELAPSED' ] += (time() - $runningTaskData[ 'TIMER_STARTED_AT' ]); // elapsed time is a sum of times in task log plus time of the current timer $task[ 'TIME_ELAPSED' ] = (string)$task[ 'TIME_ELAPSED' ]; // for consistency $task[ 'TIMER_IS_RUNNING_FOR_CURRENT_USER' ] = true; } } unset($task); } public static function getList($userId, array $listParameters = array(), array $parameters = array()) { $data = []; $can = []; $errors = static::ensureHaveErrorCollection($parameters); // todo: get rid of LIST_PARAMETERS, if can. Move limit, filter, sort, etc.. to the first level if (array_key_exists('NAV_PARAMS', $listParameters) && !empty($listParameters['NAV_PARAMS'])) { $params = ['NAV_PARAMS' => $listParameters['NAV_PARAMS']]; } else { $navParams = static::prepareNav( $listParameters['limit'], $listParameters['offset'], $listParameters['page'], $parameters['PUBLIC_MODE'] ); $params = false; if (!empty($navParams)) { $params = ['NAV_PARAMS' => $navParams]; } } $getNewCommentsCount = in_array('NEW_COMMENTS_COUNT', $listParameters['select'], true); if ( array_key_exists('SORTING', (array)$listParameters['order']) && array_key_exists('GROUP_ID', $listParameters['legacyFilter']) ) { $params['SORTING_GROUP_ID'] = $listParameters['legacyFilter']['GROUP_ID']; } if (array_key_exists('USE_MINIMAL_SELECT_LEGACY', $parameters)) { $params['USE_MINIMAL_SELECT_LEGACY'] = $parameters['USE_MINIMAL_SELECT_LEGACY']; } if (array_key_exists('MAKE_ACCESS_FILTER', $parameters)) { $params['MAKE_ACCESS_FILTER'] = $parameters['MAKE_ACCESS_FILTER']; } if ($getNewCommentsCount) { $listParameters['select'][] = 'CREATED_DATE'; $listParameters['select'][] = 'VIEWED_DATE'; } if ( !array_key_exists('RETURN_ACCESS', $parameters) || (array_key_exists('RETURN_ACCESS', $parameters) && $parameters['RETURN_ACCESS'] != 'N') ) { $listParameters['select'][] = 'ALLOW_CHANGE_DEADLINE'; $listParameters['select'][] = 'TASK_CONTROL'; $listParameters['select'][] = 'ALLOW_TIME_TRACKING'; } // an exception about sql error may fall here [$items, $res] = \CTaskItem::fetchListArray( $userId, $listParameters['order'], $listParameters['legacyFilter'], $params, $listParameters['select'] ); if (is_array($items) && !empty($items)) { foreach ($items as $taskData) { $taskId = $taskData['ID']; if (!array_key_exists('RETURN_ACCESS', $parameters) || $parameters['RETURN_ACCESS'] != 'N') { $taskData['ACTION'] = $can[$taskId]['ACTION'] = static::translateAllowedActionNames( \CTaskItem::getAllowedActionsArray($userId, $taskData, true) ); } $data[$taskId] = $taskData; } if ($getNewCommentsCount) { $newComments = Comments\Task::getNewCommentsCountForTasks(array_keys($items), $userId); foreach ($newComments as $taskId => $commentsCount) { $data[$taskId]['NEW_COMMENTS_COUNT'] = $commentsCount; } } } return [ 'DATA' => $data, 'CAN' => $can, 'ERRORS' => $errors, 'AUX' => [ 'OBJ_RES' => $res, ], ]; } public static function getCount(array $filter = array(), array $params = array()) { return \CTasks::GetCountInt($filter, $params); } private static function prepareNav($limit = false, $offset = false, $page=1, $public = false) { $nav = array(); if ($limit !== false && $limit !== null) { $limit = intval($limit); if ($public) { $limit = min($limit, static::LIMIT_PAGE_SIZE); } if ($offset !== false) { $nav[ 'nPageSize' ] = $limit; } else { $nav[ 'nTopCount' ] = $limit; } } else { if ($public) { $nav[ 'nTopCount' ] = static::LIMIT_PAGE_SIZE; } } if ($offset !== false && $offset !== null) { $nav[ 'iNumPageSize' ] = intval($offset); $nav[ 'iNumPage' ] = intval($page); } return $nav; } public static function extendData(&$data, array $references = array()) { if (is_array($references[ 'USER' ])) { Originator::extendData($data, $references[ 'USER' ]); Responsible::extendData($data, $references[ 'USER' ]); Auditor::extendData($data, $references[ 'USER' ]); Accomplice::extendData($data, $references[ 'USER' ]); } if (is_array($references[ 'RELATED_TASK' ])) { RelatedTask::extendData($data, $references[ 'RELATED_TASK' ]); ParentTask::extendData($data, $references[ 'RELATED_TASK' ]); ProjectDependence::extendData($data, $references[ 'RELATED_TASK' ]); } if (is_array($references[ 'GROUP' ])) { Project::extendData($data, $references[ 'GROUP' ]); } } public static function mergeData($primary = array(), $secondary = array()) { if (is_array($secondary) && is_array($primary)) { foreach ($secondary as $k => $v) { if (!array_key_exists($k, $primary) || $k == static::ACT_KEY) // force rights merging { $primary[ $k ] = $secondary[ $k ]; } elseif ($seName = static::checkIsSubEntityKey($k)) { $fName = __NAMESPACE__ . '\\Task\\' . $seName . '::mergeData'; if (is_callable($fName)) { $primary[ $k ] = call_user_func_array($fName, array($primary[ $k ], $secondary[ $k ])); } } } } return $primary; } /** * @param array $task * @param array $fields * @return array|string */ public static function prepareSearchIndex(array $task, array $fields = []) { if (empty($task)) { return ''; } if (empty($fields)) { $fields = [ 'ID', 'TITLE', 'DESCRIPTION', 'CHECKLIST', 'RESPONSIBLE', 'ORIGINATOR', 'AUDITORS', 'ACCOMPLICES', 'CRM', 'TAGS', 'GROUP' ]; } $index = []; foreach ($fields as $field) { switch ($field) { default: if (array_key_exists($field, $task) && !empty($task[$field])) { $index[] = $task[$field]; } break; // custom fields case 'CHECKLIST': /** Bitrix\Tasks\Item\Task\Collection\CheckList */ $checkList = (is_object($task['SE_CHECKLIST'])? $task['SE_CHECKLIST']->export() : (array)$task['CHECKLIST']); foreach ($checkList as $item) { $index[] = $item['TITLE']; } break; case 'RESPONSIBLE': $index[] = join(' ', User::getUserName([$task['RESPONSIBLE_ID']])); break; case 'ORIGINATOR': $index[] = join(' ', User::getUserName([$task['CREATED_BY']])); break; case 'AUDITORS': if (array_key_exists('AUDITORS', $task)) { $auditors = (is_object($task['AUDITORS'])? $task['AUDITORS']->toArray() : $task['AUDITORS']); if ($auditors) { $index[] = join(' ', User::getUserName(array_unique($auditors))); } } break; case 'ACCOMPLICES': if (array_key_exists('ACCOMPLICES', $task)) { $accomplices = (is_object($task['ACCOMPLICES'])? $task['ACCOMPLICES']->toArray() : $task['ACCOMPLICES']); if ($accomplices) { $index[] = join(' ', User::getUserName(array_unique($accomplices))); } } break; case 'CRM': if (\Bitrix\Main\ModuleManager::isModuleInstalled('crm')) { $uf = (is_object($task['UF_CRM_TASK'])? $task['UF_CRM_TASK']->toArray() : (array)$task['UF_CRM_TASK']); foreach ($uf as $item) { $crmElement = explode('_', $item); $type = $crmElement[0]; $typeId = \CCrmOwnerType::ResolveID(\CCrmOwnerTypeAbbr::ResolveName($type)); $title = \CCrmOwnerType::GetCaption($typeId, $crmElement[1]); $index[] = $title; } } break; case 'TAGS': $tags = (is_object($task['TAGS'])? $task['TAGS']->export() : (array)$task['TAGS']); $index[] = join(' ', $tags); break; case 'GROUP': $groupId = $task['GROUP_ID']; $groups = Group::getData([$groupId]); $groupName = $groups[$groupId]['NAME']; $index[] = $groupName; break; } } $strIndex = join(' ', $index); $strIndex = array_unique(explode(' ', $strIndex)); $strIndex = join(' ', $strIndex); $strIndex = toUpper($strIndex); return $strIndex; } protected static function getLegalSubEntities() { static $legal; if ($legal === null) { $legal = array( Originator::getCode(), Responsible::getCode(), Auditor::getCode(), Accomplice::getCode(), Checklist::getCode(), Reminder::getCode(), ElapsedTime::getCode(), Log::getCode(), ProjectDependence::getCode(), Template::getCode(), Tag::getCode(), RelatedTask::getCode(), 'DAYPLAN', 'TIMEMANAGER', // alias for DAYPLAN ); } return $legal; } /** * @param $data * @return array * @throws \Bitrix\Main\SystemException */ protected static function getAnalyticsData(&$data) { $code = Checklist::getCode(true); $checklistData = $data[$code]; if (!$checklistData) { return []; } $checklistParents = array_filter( $checklistData, static function($item) { return is_array($item) && $item['PARENT_NODE_ID'] === '0'; } ); $analyticsData = [ 'checklistCount' => count($checklistParents), ]; if ($checklistData['analyticsData']) { foreach (explode(',', $checklistData['analyticsData']) as $key => $value) { $analyticsData[$value] = 1; } } if ($checklistData['fromDescription']) { $analyticsData['fromDescription'] = 1; } unset($data[$code]['analyticsData'], $data[$code]['fromDescription']); return $analyticsData; } }
/var/www/axolotl/data/www/nn.axolotls.ru/bitrix/modules/tasks/lib/manager/task.php