/home/ivoiecob/email.hirewise-va.com/vendor/afterlogic/dav/lib/DAV/CalDAV/Schedule/Plugin.php
<?php

namespace Afterlogic\DAV\CalDAV\Schedule;

use Sabre\VObject\ITip\Message;
use Sabre\VObject\Component\VCalendar;
use Sabre\VObject\ITip;
use Sabre\CalDAV\ICalendarObject;

class Plugin extends \Sabre\CalDAV\Schedule\Plugin
{
    protected $customSignificantChangeProperties = [
        'SUMMARY', 
        'DESCRIPTION', 
        'LOCATION',
        'ATTENDEE'
    ];

    /**
     * Event handler for the 'schedule' event.
     *
     * This handler attempts to look at local accounts to deliver the
     * scheduling object.
     */
    public function scheduleLocalDelivery(\Sabre\VObject\ITip\Message $iTipMessage)
    {
        // $aclPlugin = $this->server->getPlugin('acl');

        // // Local delivery is not available if the ACL plugin is not loaded.
        // if (!$aclPlugin) {
        //     return;
        // }

        // $caldavNS = '{'.self::NS_CALDAV.'}';

        // $principalUri = $aclPlugin->getPrincipalByUri($iTipMessage->recipient);
        // if (!$principalUri) {
        //     $iTipMessage->scheduleStatus = '3.7;Could not find principal.';

        //     return;
        // }

        // // We found a principal URL, now we need to find its inbox.
        // // Unfortunately we may not have sufficient privileges to find this, so
        // // we are temporarily turning off ACL to let this come through.
        // //
        // // Once we support PHP 5.5, this should be wrapped in a try..finally
        // // block so we can ensure that this privilege gets added again after.
        // $this->server->removeListener('propFind', [$aclPlugin, 'propFind']);

        // $result = $this->server->getProperties(
        //     $principalUri,
        //     [
        //         '{DAV:}principal-URL',
        //          $caldavNS.'calendar-home-set',
        //          $caldavNS.'schedule-inbox-URL',
        //          $caldavNS.'schedule-default-calendar-URL',
        //         '{http://sabredav.org/ns}email-address',
        //     ]
        // );

        // // Re-registering the ACL event
        // $this->server->on('propFind', [$aclPlugin, 'propFind'], 20);

        // if (!isset($result[$caldavNS.'schedule-inbox-URL'])) {
        //     $iTipMessage->scheduleStatus = '5.2;Could not find local inbox';

        //     return;
        // }
        // if (!isset($result[$caldavNS.'calendar-home-set'])) {
        //     $iTipMessage->scheduleStatus = '5.2;Could not locate a calendar-home-set';

        //     return;
        // }
        // if (!isset($result[$caldavNS.'schedule-default-calendar-URL'])) {
        //     $iTipMessage->scheduleStatus = '5.2;Could not find a schedule-default-calendar-URL property';

        //     return;
        // }

        // $calendarPath = $result[$caldavNS.'schedule-default-calendar-URL']->getHref();
        // $homePath = $result[$caldavNS.'calendar-home-set']->getHref();
        // $inboxPath = $result[$caldavNS.'schedule-inbox-URL']->getHref();

        // if ('REPLY' === $iTipMessage->method) {
        //     $privilege = 'schedule-deliver-reply';
        // } else {
        //     $privilege = 'schedule-deliver-invite';
        // }

        // if (!$aclPlugin->checkPrivileges($inboxPath, $caldavNS.$privilege, \Sabre\DAVACL\Plugin::R_PARENT, false)) {
        //     $iTipMessage->scheduleStatus = '3.8;insufficient privileges: '.$privilege.' is required on the recipient schedule inbox.';

        //     return;
        // }

        // // Next, we're going to find out if the item already exits in one of
        // // the users' calendars.
        // $uid = $iTipMessage->uid;

        // $newFileName = 'sabredav-'.\Sabre\DAV\UUIDUtil::getUUID().'.ics';

        // $user = basename($principalUri);
        // $home = \Afterlogic\DAV\Server::getNodeForPath($homePath, $user);
        // $inbox = \Afterlogic\DAV\Server::getNodeForPath($inboxPath, $user);

        // $currentObject = null;
        // $objectNode = null;
        // $oldICalendarData = null;
        // $isNewNode = false;

        // $home->init();
        // $result = $home->getCalendarObjectByUID($uid);
        // if ($result) {
        //     // There was an existing object, we need to update probably.
        //     $objectPath = $homePath.'/'.$result;
        //     $objectNode = \Afterlogic\DAV\Server::getNodeForPath($objectPath, $user);
        //     $oldICalendarData = $objectNode->get();
        //     $currentObject = \Sabre\VObject\Reader::read($oldICalendarData);
        // } else {
        //     $isNewNode = true;
        // }

        // $broker = new \Sabre\VObject\ITip\Broker();
        // $broker->significantChangeProperties = array_merge(
        //     $broker->significantChangeProperties, 
        //     $this->customSignificantChangeProperties
        // );        
        // $newObject = $broker->processMessage($iTipMessage, $currentObject);

        // $inbox->createFile($newFileName, $iTipMessage->message->serialize());

        // if (!$newObject) {
        //     // We received an iTip message referring to a UID that we don't
        //     // have in any calendars yet, and processMessage did not give us a
        //     // calendarobject back.
        //     //
        //     // The implication is that processMessage did not understand the
        //     // iTip message.
        //     $iTipMessage->scheduleStatus = '5.0;iTip message was not processed by the server, likely because we didn\'t understand it.';

        //     return;
        // }

        // // Note that we are bypassing ACL on purpose by calling this directly.
        // // We may need to look a bit deeper into this later. Supporting ACL
        // // here would be nice.
        // if ($isNewNode) {
        //     $calendar = \Afterlogic\DAV\Server::getNodeForPath($calendarPath, $user);
        //     $calendar->createFile($newFileName, $newObject->serialize());
        // } else {
        //     // If the message was a reply, we may have to inform other
        //     // attendees of this attendees status. Therefore we're shooting off
        //     // another itipMessage.
        //     if ('REPLY' === $iTipMessage->method) {
        //         $this->processICalendarChange(
        //             $oldICalendarData,
        //             $newObject,
        //             [$iTipMessage->recipient],
        //             [$iTipMessage->sender]
        //         );
        //     }
        //     $objectNode->put($newObject->serialize());
        // }
        // $iTipMessage->scheduleStatus = '1.2;Message delivered locally';
    }
    
    public function scheduleLocalDeliveryParent(\Sabre\VObject\ITip\Message $iTipMessage)
    {
        parent::scheduleLocalDelivery($iTipMessage);
    }
    
    /**
    * This method is triggered before a file gets deleted.
    *
    * We use this event to make sure that when this happens, attendees get
    * cancellations, and organizers get 'DECLINED' statuses.
    *
    * @param string $path
    */
   public function beforeUnbind($path)
   {
       // FIXME: We shouldn't trigger this functionality when we're issuing a
       // MOVE. This is a hack.
       if ('MOVE' === $this->server->httpRequest->getMethod()) {
           return;
       }

       $node = $this->server->tree->getNodeForPath($path);

       if (!$node instanceof ICalendarObject || $node instanceof \Sabre\CalDAV\Schedule\ISchedulingObject) {
           return;
       }

       $reflector = new \ReflectionObject($this);
       $method = $reflector->getMethod('scheduleReply');
       $method->setAccessible(true);
       $scheduleReplyResult = $method->invoke($this, $this->server->httpRequest);

       if (!$scheduleReplyResult) {
           return;
       }

       $addresses = $this->getAddressesForPrincipal(
           $node->getOwner()
       );

       $broker = new ITip\Broker();
       $broker->significantChangeProperties = array_merge(
           $broker->significantChangeProperties, 
           $this->customSignificantChangeProperties
       );
       $messages = $broker->parseEvent(null, $addresses, $node->get());

       foreach ($messages as $message) {
           $this->deliver($message);
       }
   }

    /**
     * This method looks at an old iCalendar object, a new iCalendar object and
     * starts sending scheduling messages based on the changes.
     *
     * A list of addresses needs to be specified, so the system knows who made
     * the update, because the behavior may be different based on if it's an
     * attendee or an organizer.
     *
     * This method may update $newObject to add any status changes.
     *
     * @param VCalendar|string $oldObject
     * @param array            $ignore    any addresses to not send messages to
     * @param bool             $modified  a marker to indicate that the original object
     *                                    modified by this process
     */
    protected function processICalendarChange($oldObject, VCalendar $newObject, array $addresses, array $ignore = [], &$modified = false)
    {
        $broker = new ITip\Broker();
        $broker->significantChangeProperties = array_merge(
            $broker->significantChangeProperties, 
            $this->customSignificantChangeProperties
        );
        $messages = $broker->parseEvent($newObject, $addresses, $oldObject);

        if ($messages) {
            $modified = true;
        }

        foreach ($messages as $message) {
            if (in_array($message->recipient, $ignore)) {
                continue;
            }

            $this->deliver($message);

            if (isset($newObject->VEVENT->ORGANIZER) && ($newObject->VEVENT->ORGANIZER->getNormalizedValue() === $message->recipient)) {
                if ($message->scheduleStatus) {
                    $newObject->VEVENT->ORGANIZER['SCHEDULE-STATUS'] = $message->getScheduleStatus();
                }
                unset($newObject->VEVENT->ORGANIZER['SCHEDULE-FORCE-SEND']);
            } else {
                if (isset($newObject->VEVENT->ATTENDEE)) {
                    foreach ($newObject->VEVENT->ATTENDEE as $attendee) {
                        if ($attendee->getNormalizedValue() === $message->recipient) {
                            if ($message->scheduleStatus) {
                                $attendee['SCHEDULE-STATUS'] = $message->getScheduleStatus();
                            }
                            unset($attendee['SCHEDULE-FORCE-SEND']);
                            break;
                        }
                    }
                }
            }
        }
    }

    /**
     * Returns a list of addresses that are associated with a principal.
     *
     * @param string $principal
     * @return array
     */
    protected function getAddressesForPrincipal($principal)
    {
        $CUAS = '{' . self::NS_CALDAV . '}calendar-user-address-set';

        $properties = $this->server->getProperties(
            $principal,
            [$CUAS]
        );

        // If we can't find this information, we'll stop processing
        if (!isset($properties[$CUAS])) {
            return;
        }

        $addresses = $properties[$CUAS]->getHrefs();

        $iPos = strpos($principal, 'principals/');
        if ($iPos !== false) {
            $addresses[] = 'mailto:' . \trim(substr($principal, $iPos + 11), '/');
        }
        return $addresses;
    }
}