1<?php
2/**
3 * Base class for Kronolith resources. Partially presents a Horde_Share_Object
4 * interface.
5 *
6 * Copyright 2009-2017 Horde LLC (http://www.horde.org/)
7 *
8 * See the enclosed file COPYING for license information (GPL). If you
9 * did not receive this file, see http://www.horde.org/licenses/gpl.
10 *
11 * @author Michael J Rubinsky <mrubinsk@horde.org>
12 * @package Kronolith
13 */
14abstract class Kronolith_Resource_Base
15{
16    /**
17     * Instance copy of parameters
18     * Contains:
19     *<pre>
20     *   -:name          - Display name of resource.
21     *   -:calendar      - The calendar associated with this resource.
22     *   -:description   - Resource description.
23     *   -:email         - An email address for the resource. (Currently not used)
24     *   -:members       - Member resources, if this is a group.
25     *   -:response_type - A RESPONSETYPE_* constant
26     *</pre>
27     * @var array
28     */
29    protected $_params = array();
30
31    /**
32     * Resource's internal id
33     *
34     * @var integer
35     */
36    protected $_id = '';
37
38    /**
39     * Const'r
40     *
41     * @param array $params
42     *
43     * @return Kronolith_Resource_Base
44     */
45    public function __construct(array $params = array())
46    {
47        if (!empty($params['id'])) {
48            // Existing resource
49            $this->_id = $params['id'];
50        }
51
52        // Names are required.
53        if (empty($params['name'])) {
54            throw new BadMethodCallException('Required \'name\' attribute missing from resource calendar');
55        }
56        $this->_params = array_merge(
57            array('description' => '',
58                  'response_type' => Kronolith_Resource::RESPONSETYPE_MANUAL,
59                  'members' => '',
60                  'calendar' => '',
61                  'email' => ''
62            ),
63            $params
64        );
65    }
66
67    /**
68     * Obtain the resource's internal identifier.
69     *
70     * @return string The id.
71     */
72    public function getId()
73    {
74        return $this->_id;
75    }
76
77    /**
78     * Allow setting of properties
79     *
80     * @param string $property  The property to set
81     * @param mixed $value      The value to set to
82     *
83     * @return void
84     */
85    public function set($property, $value)
86    {
87        $this->_params[$property] = $value;
88    }
89
90    /**
91     * Return permission for the specified user for this Resource.
92     *
93     * @param string $user         The user to check for.
94     * @param integer $permission  The permission to check.
95     * @param $restrict
96     *
97     * @return boolean
98     */
99    public function hasPermission($user, $permission = Horde_Perms::READ, $restrict = null)
100    {
101        if (($permission & (Horde_Perms::EDIT | Horde_Perms::DELETE)) &&
102            !$GLOBALS['registry']->isAdmin() &&
103            !$GLOBALS['injector']->getInstance('Horde_Core_Perms')->hasAppPermission('resource_management')) {
104            return false;
105        }
106
107        return true;
108    }
109
110    /**
111     * Implemented to stand in as a share object.
112     *
113     * @param string $property  The property to get
114     *
115     * @return mixed  The value of $property
116     */
117    public function get($property)
118    {
119        $property = str_replace('resource_', '', $property);
120        if ($property == 'type' && empty($this->_params['type'])) {
121            return ($this instanceof Kronolith_Resource_Single) ? 'Single' : 'Group';
122        }
123        if (!array_key_exists($property, $this->_params)) {
124            throw new LogicException(sprintf('The property \'%s\' does not exist', $property));
125        }
126        return $this->_params[$property];
127    }
128
129    /**
130     * Save resource to storage.
131     *
132     * @return Kronolith_Resource_Base
133     */
134    public function save()
135    {
136        return $this->getDriver()->save($this);
137    }
138
139    /**
140     * Get a storage driver instance for the resource.
141     *
142     * @return Kronolith_Driver_Resource_* object.
143     */
144    public function getDriver()
145    {
146        if (!$this->get('calendar')) {
147            return Kronolith::getDriver('Resource');
148        } else {
149            return Kronolith::getDriver('Resource', $this->get('calendar'));
150        }
151    }
152
153    /**
154     * Check availability and return an appropriate Kronolith response code.
155     *
156     * @param Kronolith_Event $event  The event to check on
157     *
158     * @return integer Kronolith::RESPONSE* constant
159     */
160    public function getResponse(Kronolith_Event $event)
161    {
162        switch($this->getResponseType()) {
163        case Kronolith_Resource::RESPONSETYPE_ALWAYS_ACCEPT:
164            return Kronolith::RESPONSE_ACCEPTED;
165        case Kronolith_Resource::RESPONSETYPE_AUTO:
166            if ($this->isFree($event)) {
167                return Kronolith::RESPONSE_ACCEPTED;
168            } else {
169                return Kronolith::RESPONSE_DECLINED;
170            }
171        case Kronolith_Resource::RESPONSETYPE_ALWAYS_DECLINE:
172            return Kronolith::RESPONSE_DECLINED;
173        case Kronolith_Resource::RESPONSETYPE_NONE:
174        case Kronolith_Resource::RESPONSETYPE_MANUAL:
175            return Kronolith::RESPONSE_NONE;
176        }
177    }
178
179    /**
180     * Return this resource's parameters in a hash.
181     *
182     * @return array  A hash suitable for JSON encoding.
183     */
184    public function toJson()
185    {
186        return $this->_params;
187    }
188
189    /**
190     * Determine if event is free for specified time
191     *
192     * @param Kronolith_Event $event  The event we want to check the
193     *                                resource's availability for.
194     *
195     * @return boolean  True if the resource is free, false if not.
196     */
197    abstract public function isFree(Kronolith_Event $event);
198
199    /**
200     * Adds $event to this resource's calendar - thus blocking the time
201     * for any other event.
202     *
203     * @param Kronolith_Event $event  The event to add to this resource's
204     *                                calendar, thus blocking it's availability.
205     *
206     * @throws Kronolith_Exception
207     */
208    abstract public function addEvent(Kronolith_Event $event);
209
210    /**
211     * Remove this event from resource's calendar
212     *
213     * @param Kronolith_Event $event  The event to remove from the resource's
214     *                                calendar.
215     */
216    abstract public function removeEvent(Kronolith_Event $event);
217
218    /**
219     * Obtain the freebusy information for this resource.  Takes into account
220     * if this is a group of resources or not. (Returns the cumulative FB info
221     * for all the resources in the group.
222     *
223     * @param integer $startstamp  The starting timestamp of the fb interval.
224     * @param integer $endstamp    The ending timestamp of the fb interval.
225     * @param boolean $asObject    Return the fb info as an object?
226     * @param boolean $json        Return the fb info as JSON?
227     *
228     * @return mixed string|Horde_Icalendar_Vfreebusy  The Freebusy object or
229     *                                                 the iCalendar text.
230     */
231    abstract public function getFreeBusy($startstamp = null, $endstamp = null, $asObject = false, $json = false);
232
233    /**
234     * Sets the current resource's id. Must not be an existing resource.
235     *
236     * @param integer $id  The id for this resource
237     *
238     * @throws Kronolith_Exception
239     */
240    abstract public function setId($id);
241
242    /**
243     * Get ResponseType for this resource.
244     *
245     * @return integer  The response type for this resource. A
246     *                  Kronolith_Resource::RESPONSE_TYPE_* constant.
247     */
248    abstract public function getResponseType();
249
250}
251