Ejemplo n.º 1
0
 public function addDependOn($parentId, $linkType = DependenceTable::LINK_TYPE_FINISH_START)
 {
     $exceptionInfo = array('AUX' => array('MESSAGE' => array('FROM_TASK_ID' => $parentId, 'TASK_ID' => $this->getId(), 'LINK_TYPE' => $linkType)));
     if (!\Bitrix\Tasks\Util\Restriction::checkCanCreateDependence()) {
         $exceptionInfo['ERROR'] = array(array('CODE' => 'TRIAL_EXPIRED', 'MESSAGE' => Loc::getMessage('TASKS_TRIAL_PERIOD_EXPIRED')));
         throw new ActionRestrictedException(Loc::getMessage('TASK_CANT_ADD_LINK'), $exceptionInfo);
     }
     if ($this->isActionAllowed(self::ACTION_CHANGE_DEADLINE)) {
         $parentTask = CTaskItem::getInstanceFromPool($parentId, $this->executiveUserId);
         if ($parentTask->isActionAllowed(self::ACTION_CHANGE_DEADLINE)) {
             // DependenceTable does not care about PARENT_ID relations and other restrictions except
             // those which may compromise dependence mechanism logic
             // so PARENT_ID check and DATE assignment are placed outside
             $errors = array();
             if ($this->checkIsSubtaskOf($parentId) || $parentTask->checkIsSubtaskOf($this->getId())) {
                 $errors['TASKS_HAS_PARENT_RELATION'] = Loc::getMessage('TASKS_HAS_PARENT_RELATION');
             } else {
                 // assign dates
                 $calendar = new Calendar();
                 $taskScheduler = new Scheduler($this->executiveUserId, $this, array(), $calendar);
                 $taskScheduler->defineDates();
                 $taskScheduler->sync();
                 $parentTaskScheduler = new Scheduler($this->executiveUserId, $parentTask, array(), $calendar);
                 $parentTaskScheduler->defineDates();
                 $parentTaskScheduler->sync();
                 $result = DependenceTable::createLink($this->getId(), $parentId, $linkType, array('TASK_DATA' => $this->getData(false), 'PARENT_TASK_DATA' => $parentTask->getData(false)));
                 if (!$result->isSuccess()) {
                     $errors = array_merge($errors, $result->getErrorMessages());
                 }
             }
             if (!empty($errors)) {
                 $exceptionInfo['ERROR'] = $errors;
                 throw new ActionFailedException(Loc::getMessage('TASK_CANT_ADD_LINK'), $exceptionInfo);
             }
             return;
         }
     }
     throw new ActionNotAllowedException(Loc::getMessage('TASK_CANT_ADD_LINK'), $exceptionInfo);
 }
Ejemplo n.º 2
0
 /**
  * This method is deprecated. Use CTaskItem::update() instead.
  * @deprecated
  */
 public function Update($ID, $arFields, $arParams = array('CORRECT_DATE_PLAN_DEPENDENT_TASKS' => true, 'CORRECT_DATE_PLAN' => true, 'THROTTLE_MESSAGES' => false))
 {
     global $DB, $USER, $USER_FIELD_MANAGER, $APPLICATION;
     if (!isset($arParams['CORRECT_DATE_PLAN'])) {
         $arParams['CORRECT_DATE_PLAN'] = true;
     }
     if (!isset($arParams['CORRECT_DATE_PLAN_DEPENDENT_TASKS'])) {
         $arParams['CORRECT_DATE_PLAN_DEPENDENT_TASKS'] = true;
     }
     if (!isset($arParams['THROTTLE_MESSAGES'])) {
         $arParams['THROTTLE_MESSAGES'] = false;
     }
     $this->lastOperationResultData = array();
     if (isset($arFields['META::EVENT_GUID'])) {
         $eventGUID = $arFields['META::EVENT_GUID'];
         unset($arFields['META::EVENT_GUID']);
     } else {
         $eventGUID = sha1(uniqid('AUTOGUID', true));
     }
     $bWasFatalError = false;
     $ID = intval($ID);
     if ($ID < 1) {
         return false;
     }
     $userID = null;
     $bCheckRightsOnFiles = false;
     // for backward compatibility
     if (!is_array($arParams)) {
         $arParams = array();
     }
     if (isset($arParams['USER_ID']) && $arParams['USER_ID'] > 0) {
         $userID = (int) $arParams['USER_ID'];
     }
     if (isset($arParams['CHECK_RIGHTS_ON_FILES'])) {
         if ($arParams['CHECK_RIGHTS_ON_FILES'] === 'Y' || $arParams['CHECK_RIGHTS_ON_FILES'] === true) {
             $bCheckRightsOnFiles = true;
         } else {
             $bCheckRightsOnFiles = false;
         }
     }
     if (!isset($arParams['CORRECT_DATE_PLAN_DEPENDENT_TASKS'])) {
         $arParams['CORRECT_DATE_PLAN_DEPENDENT_TASKS'] = true;
     }
     if (!isset($arParams['CORRECT_DATE_PLAN'])) {
         $arParams['CORRECT_DATE_PLAN'] = true;
     }
     if ($userID === null) {
         $userID = is_object($USER) ? intval($USER->GetID()) : 1;
     }
     $rsTask = CTasks::GetByID($ID, false);
     if ($arTask = $rsTask->Fetch()) {
         // check if there are userfields in $arFields
         $hasUfs = false;
         foreach ($arFields as $fld => $value) {
             $fld = trim($fld);
             if (strpos($fld, 'UF_') == 0) {
                 $hasUfs = true;
                 break;
             }
         }
         if ($this->CheckFields($arFields, $ID, $userID)) {
             $okay = $hasUfs ? $USER_FIELD_MANAGER->CheckFields("TASKS_TASK", $ID, $arFields) : true;
             if ($okay) {
                 $scheduler = null;
                 unset($arFields["ID"]);
                 $arBinds = array("DESCRIPTION" => $arFields["DESCRIPTION"], "DECLINE_REASON" => $arFields["DECLINE_REASON"]);
                 $time = time() + CTasksTools::getTimeZoneOffset();
                 $arFields["CHANGED_BY"] = $userID;
                 $arFields["CHANGED_DATE"] = date($DB->DateFormatToPHP(CSite::GetDateFormat("FULL")), $time);
                 $occurAsUserId = CTasksTools::getOccurAsUserId();
                 if (!$occurAsUserId) {
                     $occurAsUserId = $arFields["CHANGED_BY"] ? $arFields["CHANGED_BY"] : 1;
                 }
                 if (!$arFields["OUTLOOK_VERSION"]) {
                     $arFields["OUTLOOK_VERSION"] = ($arTask["OUTLOOK_VERSION"] ? $arTask["OUTLOOK_VERSION"] : 1) + 1;
                 }
                 // If new status code given AND new status code != current status => than update
                 if (isset($arFields["STATUS"]) && (int) $arTask['STATUS'] !== (int) $arFields['STATUS']) {
                     $arFields["STATUS_CHANGED_BY"] = $userID;
                     $arFields["STATUS_CHANGED_DATE"] = date($DB->DateFormatToPHP(CSite::GetDateFormat("FULL")), $time);
                     if ($arFields["STATUS"] == 5 || $arFields["STATUS"] == 4) {
                         $arFields["CLOSED_BY"] = $userID;
                         $arFields["CLOSED_DATE"] = date($DB->DateFormatToPHP(CSite::GetDateFormat("FULL")), $time);
                     } else {
                         $arFields["CLOSED_BY"] = false;
                         $arFields["CLOSED_DATE"] = false;
                         if ($arFields["STATUS"] == 3) {
                             $arFields["DATE_START"] = date($DB->DateFormatToPHP(CSite::GetDateFormat("FULL")), $time);
                         }
                     }
                 }
                 if ($arFields["REPLICATE"] == "Y") {
                     $arFields["REPLICATE_PARAMS"] = serialize($arFields["REPLICATE_PARAMS"]);
                 }
                 // when updating end or start date plan, we need to be sure the time is correct
                 if ((string) $arFields['START_DATE_PLAN'] != '' || (string) $arFields['END_DATE_PLAN'] != '') {
                     if ($arParams['CORRECT_DATE_PLAN']) {
                         /*
                         print_r('Try to update '.$ID.' to:'.PHP_EOL);
                         print_r($arFields['START_DATE_PLAN']->getInfoGmt().PHP_EOL);
                         print_r($arFields['END_DATE_PLAN']->getInfoGmt().PHP_EOL);
                         */
                         $arTaskDPCopy = $arTask;
                         if ((string) $arFields['START_DATE_PLAN'] == '') {
                             // start date will be dropped, scheduler should be informed about that
                             $arTaskDPCopy['START_DATE_PLAN'] = '';
                         }
                         if ((string) $arFields['END_DATE_PLAN'] == '') {
                             // end date will be dropped, scheduler should be informed about that
                             $arTaskDPCopy['END_DATE_PLAN'] = '';
                         }
                         $scheduler = new Scheduler($userID, $ID, $arTaskDPCopy);
                         $data = $scheduler->reScheduleTask($arFields);
                         /*
                         print_r('Actual moving '.$ID.' to:'.PHP_EOL);
                         print_r($data['START_DATE_PLAN']->getInfoGmt().PHP_EOL);
                         print_r($data['END_DATE_PLAN']->getInfoGmt().PHP_EOL);
                         */
                         // to database:
                         if ($data['START_DATE_PLAN']) {
                             if ($data['START_DATE_PLAN']->toString() != (string) $arTask['CREATED_DATE']) {
                                 $arFields['START_DATE_PLAN'] = $data['START_DATE_PLAN']->toString();
                             }
                             $data['START_DATE_PLAN_STRUCT'] = $data['START_DATE_PLAN']->getTimeStruct();
                             $data['START_DATE_PLAN'] = $data['START_DATE_PLAN']->toString();
                         }
                         if ($data['END_DATE_PLAN']) {
                             $arFields['END_DATE_PLAN'] = $data['END_DATE_PLAN']->toString();
                             $data['END_DATE_PLAN_STRUCT'] = $data['END_DATE_PLAN']->getTimeStruct();
                             $data['END_DATE_PLAN'] = $data['END_DATE_PLAN']->toString();
                         }
                         if (isset($data['DURATION_PLAN_SECONDS'])) {
                             $arFields['DURATION_PLAN_SECONDS'] = $data['DURATION_PLAN_SECONDS'];
                         }
                         unset($data['ID']);
                         unset($data['MATCH_WORK_TIME']);
                         $this->lastOperationResultData['SHIFT_RESULT'][$ID] = $data;
                     }
                 }
                 // END_DATE_PLAN will be dropped
                 if (isset($arFields['END_DATE_PLAN']) && (string) $arFields['END_DATE_PLAN'] == '') {
                     // duration is no longer adequate
                     $arFields['DURATION_PLAN'] = 0;
                 }
                 self::processDurationPlanFields($arFields, (string) $arFields['DURATION_TYPE'] != '' ? $arFields['DURATION_TYPE'] : $arTask['DURATION_TYPE']);
                 $arTaskCopy = $arTask;
                 // this will allow transfer data by pointer for speed-up
                 foreach (GetModuleEvents('tasks', 'OnBeforeTaskUpdate', true) as $arEvent) {
                     if (ExecuteModuleEventEx($arEvent, array($ID, &$arFields, &$arTaskCopy)) === false) {
                         $errmsg = GetMessage("TASKS_UNKNOWN_UPDATE_ERROR");
                         $errno = 'ERROR_UNKNOWN_UPDATE_TASK_ERROR';
                         if ($ex = $APPLICATION->getException()) {
                             $errmsg = $ex->getString();
                             $errno = $ex->getId();
                         }
                         $this->_errors[] = array('text' => $errmsg, 'id' => $errno);
                         return false;
                     }
                 }
                 $oTaskList = CTaskCountersProcessor::getInstance();
                 $oTaskList->onBeforeTaskUpdate($ID, $arTask, $arFields);
                 $strUpdate = $DB->PrepareUpdate("b_tasks", $arFields, "tasks");
                 $strSql = "UPDATE b_tasks SET " . $strUpdate . " WHERE ID=" . $ID;
                 $result = $DB->QueryBind($strSql, $arBinds, false, "File: " . __FILE__ . "<br>Line: " . __LINE__);
                 if ($result) {
                     CTaskCountersProcessor::onAfterTaskUpdate($ID, $arTask, $arFields);
                     $arParticipants = array_merge(array($arTask['CREATED_BY'], $arTask['RESPONSIBLE_ID']), (array) $arTask['ACCOMPLICES'], (array) $arTask['AUDITORS']);
                     if (isset($arFields['CREATED_BY'])) {
                         $arParticipants[] = $arFields['CREATED_BY'];
                     }
                     if (isset($arFields['RESPONSIBLE_ID'])) {
                         $arParticipants[] = $arFields['RESPONSIBLE_ID'];
                     }
                     if (isset($arFields['ACCOMPLICES'])) {
                         $arParticipants = array_merge($arParticipants, (array) $arFields['ACCOMPLICES']);
                     }
                     if (isset($arFields['AUDITORS'])) {
                         $arParticipants = array_merge($arParticipants, (array) $arFields['AUDITORS']);
                     }
                     $arParticipants = array_unique($arParticipants);
                     // Emit pull event
                     try {
                         $arPullRecipients = array();
                         foreach ($arParticipants as $userId) {
                             $arPullRecipients[] = (int) $userId;
                         }
                         $taskGroupId = 0;
                         // no group
                         $taskGroupIdBeforeUpdate = 0;
                         // no group
                         if (isset($arTask['GROUP_ID']) && $arTask['GROUP_ID'] > 0) {
                             $taskGroupId = (int) $arTask['GROUP_ID'];
                         }
                         // if $arFields['GROUP_ID'] not given, than it means,
                         // that group not changed during this update, so
                         // we must take existing group_id (from $arTask)
                         if (!array_key_exists('GROUP_ID', $arFields)) {
                             if (isset($arTask['GROUP_ID']) && $arTask['GROUP_ID'] > 0) {
                                 $taskGroupIdBeforeUpdate = (int) $arTask['GROUP_ID'];
                             } else {
                                 $taskGroupIdBeforeUpdate = 0;
                             }
                             // no group
                         } else {
                             if ($arFields['GROUP_ID'] > 0) {
                                 $taskGroupIdBeforeUpdate = (int) $arFields['GROUP_ID'];
                             } else {
                                 $taskGroupIdBeforeUpdate = 0;
                             }
                             // no group
                         }
                         $arPullData = array('TASK_ID' => (int) $ID, 'BEFORE' => array('GROUP_ID' => $taskGroupId), 'AFTER' => array('GROUP_ID' => $taskGroupIdBeforeUpdate), 'TS' => time(), 'event_GUID' => $eventGUID);
                         self::EmitPullWithTagPrefix($arPullRecipients, 'TASKS_GENERAL_', 'task_update', $arPullData);
                         self::EmitPullWithTag($arPullRecipients, 'TASKS_TASK_' . (int) $ID, 'task_update', $arPullData);
                     } catch (Exception $e) {
                         $bWasFatalError = true;
                         $this->_errors[] = 'at line ' . $e->GetLine() . ', ' . $e->GetMessage();
                     }
                     // changes log
                     $arTmp = array('arTask' => $arTask, 'arFields' => $arFields);
                     if (isset($arTask['DURATION_PLAN'])) {
                         $arTmp['arTask']['DURATION_PLAN_SECONDS'] = $arTask['DURATION_PLAN_SECONDS'];
                         unset($arTmp['arTask']['DURATION_PLAN']);
                     }
                     if (isset($arFields['DURATION_PLAN'])) {
                         // at this point, $arFields['DURATION_PLAN'] in seconds
                         $arTmp['arFields']['DURATION_PLAN_SECONDS'] = $arFields['DURATION_PLAN'];
                         unset($arTmp['arFields']['DURATION_PLAN']);
                     }
                     $arChanges = CTaskLog::GetChanges($arTmp['arTask'], $arTmp['arFields']);
                     unset($arTmp);
                     foreach ($arChanges as $key => $value) {
                         $arLogFields = array("TASK_ID" => $ID, "USER_ID" => $occurAsUserId, "CREATED_DATE" => $arFields["CHANGED_DATE"], "FIELD" => $key, "FROM_VALUE" => $value["FROM_VALUE"], "TO_VALUE" => $value["TO_VALUE"]);
                         $log = new CTaskLog();
                         $log->Add($arLogFields);
                     }
                     if (isset($arFields["ACCOMPLICES"]) && isset($arChanges["ACCOMPLICES"])) {
                         CTaskMembers::DeleteByTaskID($ID, "A");
                         CTasks::AddAccomplices($ID, $arFields["ACCOMPLICES"]);
                     }
                     if (isset($arFields["AUDITORS"]) && isset($arChanges["AUDITORS"])) {
                         CTaskMembers::DeleteByTaskID($ID, "U");
                         CTasks::AddAuditors($ID, $arFields["AUDITORS"]);
                     }
                     if (isset($arFields["FILES"]) && (isset($arChanges["NEW_FILES"]) || isset($arChanges["DELETED_FILES"]))) {
                         $arNotDeleteFiles = $arFields["FILES"];
                         CTaskFiles::DeleteByTaskID($ID, $arNotDeleteFiles);
                         CTasks::AddFiles($ID, $arFields["FILES"], array('USER_ID' => $userID, 'CHECK_RIGHTS_ON_FILES' => $bCheckRightsOnFiles));
                     }
                     if (isset($arFields["TAGS"]) && isset($arChanges["TAGS"])) {
                         CTaskTags::DeleteByTaskID($ID);
                         CTasks::AddTags($ID, $arTask["CREATED_BY"], $arFields["TAGS"], $userID);
                     }
                     if (isset($arFields["DEPENDS_ON"]) && isset($arChanges["DEPENDS_ON"])) {
                         CTaskDependence::DeleteByTaskID($ID);
                         CTasks::AddPrevious($ID, $arFields["DEPENDS_ON"]);
                     }
                     if ($hasUfs) {
                         $USER_FIELD_MANAGER->Update("TASKS_TASK", $ID, $arFields, $userID);
                     }
                     // tasks dependence
                     if ($arParams['CORRECT_DATE_PLAN'] && $arParams['CORRECT_DATE_PLAN_DEPENDENT_TASKS'] && (isset($arFields["START_DATE_PLAN"]) || isset($arFields["END_DATE_PLAN"]))) {
                         if ($scheduler === null) {
                             $scheduler = new Scheduler($userID, $ID, $arTask);
                         }
                         $relatedTaskUpdate = $scheduler->reScheduleRelatedTasks();
                         if (is_array($relatedTaskUpdate)) {
                             $relatedUpdateParams = $arParams;
                             $relatedUpdateParams['CORRECT_DATE_PLAN'] = false;
                             // no self-correction
                             $relatedUpdateParams['CORRECT_DATE_PLAN_DEPENDENT_TASKS'] = false;
                             // no sub-correction
                             foreach ($relatedTaskUpdate as $relatedTaskId => $relatedTaskData) {
                                 $relatedTaskData['START_DATE_PLAN_STRUCT'] = $relatedTaskData['START_DATE_PLAN']->getTimeStruct();
                                 // as struct
                                 $relatedTaskData['END_DATE_PLAN_STRUCT'] = $relatedTaskData['END_DATE_PLAN']->getTimeStruct();
                                 // as struct
                                 $relatedTaskData['START_DATE_PLAN'] = $relatedTaskData['START_DATE_PLAN']->toString();
                                 // as string, not object
                                 $relatedTaskData['END_DATE_PLAN'] = $relatedTaskData['END_DATE_PLAN']->toString();
                                 // as string, not object
                                 $relatedTask = new CTasks();
                                 $relatedTask->update($relatedTaskId, $relatedTaskData, $relatedUpdateParams);
                                 $this->lastOperationResultData['SHIFT_RESULT'][$relatedTaskId] = $relatedTaskData;
                             }
                         }
                     }
                     $notifArFields = array_merge($arFields, array('CHANGED_BY' => $occurAsUserId));
                     if (($status = intval($arFields["STATUS"])) && $status > 0 && $status < 8 && (int) $arTask['STATUS'] !== (int) $arFields['STATUS']) {
                         if ($status == 7) {
                             $arTask["DECLINE_REASON"] = $arFields["DECLINE_REASON"];
                         }
                         CTaskNotifications::SendStatusMessage($arTask, $status, $notifArFields);
                     }
                     CTaskNotifications::SendUpdateMessage($notifArFields, $arTask, false, $arParams);
                     CTaskComments::onAfterTaskUpdate($ID, $arTask, $arFields);
                     $arFields["ID"] = $ID;
                     $arMergedFields = array_merge($arTask, $arFields);
                     CTaskSync::UpdateItem($arFields, $arTask);
                     // MS Exchange
                     $arFields['META:PREV_FIELDS'] = $arTask;
                     try {
                         $lastEventName = '';
                         foreach (GetModuleEvents('tasks', 'OnTaskUpdate', true) as $arEvent) {
                             $lastEventName = $arEvent['TO_CLASS'] . '::' . $arEvent['TO_METHOD'] . '()';
                             ExecuteModuleEventEx($arEvent, array($ID, &$arFields, &$arTaskCopy));
                         }
                     } catch (Exception $e) {
                         CTaskAssert::logWarning('[0xee8999a8] exception in module event: ' . $lastEventName . '; at file: ' . $e->getFile() . ':' . $e->getLine() . ";\n");
                     }
                     unset($arFields['META:PREV_FIELDS']);
                     // clear cache
                     static::addCacheIdToClear("tasks_" . $ID);
                     if ($arTask["GROUP_ID"]) {
                         static::addCacheIdToClear("tasks_group_" . $arTask["GROUP_ID"]);
                     }
                     if ($arFields['GROUP_ID'] && $arFields['GROUP_ID'] != $arTask['GROUP_ID']) {
                         static::addCacheIdToClear("tasks_group_" . $arFields["GROUP_ID"]);
                     }
                     foreach ($arParticipants as $userId) {
                         static::addCacheIdToClear("tasks_user_" . $userId);
                     }
                     static::clearCache();
                     if ($bWasFatalError) {
                         soundex('push&pull: bWasFatalError === true');
                     }
                     $this->previousData = $arTask;
                     return true;
                 }
             } else {
                 $e = $APPLICATION->GetException();
                 foreach ($e->messages as $msg) {
                     $this->_errors[] = $msg;
                 }
             }
         }
     }
     if (sizeof($this->_errors) == 0) {
         $this->_errors[] = array("text" => GetMessage("TASKS_UNKNOWN_UPDATE_ERROR"), "id" => "ERROR_UNKNOWN_UPDATE_TASK_ERROR");
     }
     return false;
 }