YetiForceCompany/YetiForceCRM

View on GitHub
modules/Calendar/actions/GetFreeTime.php

Summary

Maintainability
B
5 hrs
Test Coverage
F
0%
<?php

/**
 * Action to get free time for events.
 *
 * @copyright YetiForce S.A.
 * @license   YetiForce Public License 6.5 (licenses/LicenseEN.txt or yetiforce.com)
 * @author    Tomasz Kur <t.kur@yetiforce.com>
 * @author    Mariusz Krzaczkowski <m.krzaczkowski@yetiforce.com>
 * @author    Radosław Skrzypczak <r.skrzypczak@yetiforce.com>
 */
class Calendar_GetFreeTime_Action extends Vtiger_BasicAjax_Action
{
    /**
     * Function to check permission.
     *
     * @param \App\Request $request
     *
     * @throws \App\Exceptions\NoPermitted
     */
    public function checkPermission(App\Request $request)
    {
        $moduleName = $request->getModule();
        $userPrivilegesModel = Users_Privileges_Model::getCurrentUserPrivilegesModel();
        if (!$userPrivilegesModel->hasModulePermission($moduleName)) {
            throw new \App\Exceptions\NoPermitted('LBL_PERMISSION_DENIED', 406);
        }
    }

    /**
     * Function to get free time in day.
     *
     * @param string $day
     * @param string $activityType
     * @param int    $ownerId
     *
     * @throws \App\Exceptions\AppException
     *
     * @return array
     */
    public function getFreeTimeInDay(string $day, string $activityType, int $ownerId = null)
    {
        $currentUser = empty($ownerId) ? \App\User::getCurrentUserModel() : \App\User::getUserModel($ownerId);
        if (empty($activityType)) {
            $activityType = $currentUser->get('defaultactivitytype');
        }
        $typeByDuration = \App\Json::decode($currentUser->getDetail('othereventduration'));
        $typeByDuration = array_column($typeByDuration, 'duration', 'activitytype');
        $durationEvent = $typeByDuration[$activityType] ?? 0;
        $startWorkHour = $currentUser->getDetail('start_hour');
        $endWorkHour = $currentUser->getDetail('end_hour');
        $dbStartDateOject = DateTimeField::convertToDBTimeZone($day . ' ' . $startWorkHour, null, false);
        $dbEndDateObject = DateTimeField::convertToDBTimeZone($day . ' ' . $endWorkHour, null, false);
        $dbStartDateTime = $dbStartDateOject->format('Y-m-d H:i:s');
        $dbEndDateTime = $dbEndDateObject->format('Y-m-d H:i:s');
        $dbStartDate = $dbStartDateOject->format('Y-m-d');
        $dbEndDate = $dbEndDateObject->format('Y-m-d');
        $db = App\Db::getInstance();
        $startTime = $dbStartDateOject->format('H:i:s');
        if (\App\Fields\DateTime::getDiff($dbStartDateTime, $dbEndDateTime, 'minutes') < $durationEvent || strtotime($dbEndDateTime) < strtotime($dbStartDateTime)) {
            return [];
        }
        $dataReader = (new \App\Db\Query())->select(['date_start', 'time_start', 'time_end'])
            ->from('vtiger_activity')
            ->where([
                'and',
                ['deleted' => 0],
                ['smownerid' => $currentUser->getId()],
                ['and',
                    ['<>', 'status', 'PLL_POSTPONED'],
                    ['<>', 'status', 'PLL_CANCELLED'],
                    ['<>', 'status', 'PLL_COMPLETED']
                ],
                ['or',
                    ['and',
                        ['>=', new \yii\db\Expression('CONCAT(date_start, ' . $db->quoteValue(' ') . ', time_start)'), $dbStartDateTime],
                        ['<=', new \yii\db\Expression('CONCAT(date_start, ' . $db->quoteValue(' ') . ', time_start)'), $dbEndDateTime],
                    ],
                    ['and',
                        ['>=', new \yii\db\Expression('CONCAT(due_date, ' . $db->quoteValue(' ') . ', time_end)'), $dbStartDateTime],
                        ['<=', new \yii\db\Expression('CONCAT(due_date, ' . $db->quoteValue(' ') . ', time_end)'), $dbEndDateTime],
                    ],
                    ['and',
                        ['<', 'date_start', $dbStartDate],
                        ['>', 'due_date', $dbEndDate],
                    ],
                ]
            ])->orderBy(['time_start' => SORT_ASC])
            ->createCommand()->query();
        $recordsEndTime = '';
        while ($row = $dataReader->read()) {
            $date = new DateTime($row['date_start'] . ' ' . $startTime);
            $date->add(new DateInterval('PT' . $durationEvent . 'M0S'));
            $endHourFormat = date_format($date, 'H:i:s');
            $convertedStartTime = strtotime($startTime);
            if (strtotime($startWorkHour) <= $convertedStartTime &&
                $convertedStartTime >= strtotime($recordsEndTime) &&
                $convertedStartTime <= strtotime($row['time_start']) &&
                \App\Fields\DateTime::getDiff($startTime, $row['time_start'], 'minutes') >= $durationEvent &&
                strtotime($endWorkHour) >= strtotime($endHourFormat)) {
                $endTime = new DateTimeField($endHourFormat);
                $startTime = new DateTimeField($startTime);
                return ['day' => $day, 'time_start' => $startTime->getDisplayTime(), 'time_end' => $endTime->getDisplayTime()];
            }
            $startTime = $row['time_end'];
            if (empty($recordsEndTime) || strtotime($row['time_end']) > strtotime($recordsEndTime)) {
                $recordsEndTime = $row['time_end'];
            }
        }
        $dataReader->close();
        if (!empty($recordsEndTime)) {
            $startTime = $recordsEndTime;
        }
        $date = new DateTime($day . ' ' . $startTime);
        $date->add(new DateInterval('PT' . $durationEvent . 'M0S'));
        $formattedDate = strtotime(date_format($date, 'H:i:s'));
        if ($formattedDate > strtotime($endWorkHour) || $formattedDate < strtotime($startWorkHour)) {
            $date->add(new DateInterval('P1D'));
            while (\in_array(date_format($date, 'w'), App\Config::module('Calendar', 'HIDDEN_DAYS_IN_CALENDAR_VIEW'))) {
                $date->add(new DateInterval('P1D'));
            }
            return $this->getFreeTimeInDay(date_format($date, 'Y-m-d'), $activityType, $currentUser->getId());
        }
        $endTime = new DateTimeField(date_format($date, 'H:i:s'));
        $startTime = new DateTimeField($startTime);
        return ['day' => $day, 'time_start' => $startTime->getDisplayTime(), 'time_end' => $endTime->getDisplayTime()];
    }

    /** {@inheritdoc} */
    public function process(App\Request $request)
    {
        $dateStart = DateTimeField::convertToDBFormat($request->getByType('dateStart', 'DateInUserFormat'));
        $currentUser = $request->isEmpty('ownerId') ? \App\User::getCurrentUserModel() : \App\User::getUserModel($request->getInteger('ownerId'));
        $startWorkHour = $currentUser->getDetail('start_hour');
        $endWorkHour = $currentUser->getDetail('end_hour');
        $activityType = $request->getByType('activitytype', 'Standard');
        if (\App\Fields\DateTime::getDiff($startWorkHour, $endWorkHour, 'minutes') > 0) {
            $startDate = $this->getFreeTimeInDay($dateStart, $activityType, $currentUser->getId());
            $data['time_start'] = $startDate['time_start'];
            $data['date_start'] = $startDate['day'] ? DateTimeField::convertToUserFormat($startDate['day']) : null;
            $data['time_end'] = $startDate['time_end'];
        } else {
            $data['time_start'] = $startWorkHour;
            $data['date_start'] = $request->getByType('dateStart', 'DateInUserFormat');
            $data['time_end'] = $startWorkHour;
        }
        $response = new Vtiger_Response();
        $response->setResult($data);
        $response->emit();
    }
}