1: <?php
2: /**
3: * Kronolith_Resource implementation to represent a group of similar resources.
4: *
5: * Copyright 2009-2012 Horde LLC (http://www.horde.org/)
6: *
7: * See the enclosed file COPYING for license information (GPL). If you
8: * did not receive this file, see http://www.horde.org/licenses/gpl.
9: *
10: * @author Michael J. Rubinsky <mrubinsk@horde.org>
11: * @package Kronolith
12: */
13: class Kronolith_Resource_Group extends Kronolith_Resource_Base
14: {
15: /**
16: *
17: * @var Kronolith_Driver_Resource
18: */
19: private $_driver;
20:
21: /**
22: * Local cache for event that accepts the invitation.
23: * @TODO: probably want to cache this in the session since we will typically
24: * need to do this twice: once when adding the resource to the
25: * attendees form, and once when actually saving the event.
26: *
27: * @var Kronolith_Resource_Single
28: */
29: private $_selectedResource;
30:
31: /**
32: * Const'r
33: *
34: * @param $params
35: *
36: * @return Kronolith_Resource
37: */
38: public function __construct($params)
39: {
40: $params['resource_type'] = 'Group';
41: parent::__construct($params);
42: $this->_driver = $this->getDriver();
43: }
44:
45: /**
46: * Override the get method to see if we have a selected resource. If so,
47: * return the resource's property value, otherwise, return the group's
48: * property value.
49: *
50: * @param string $property The property to get.
51: *
52: * @return mixed The requested property's value.
53: */
54: public function get($property)
55: {
56: if (empty($this->_selectedResource)) {
57: return parent::get($property);
58: } else {
59: return $this->_selectedResource->get($property);
60: }
61: }
62:
63: public function getId()
64: {
65: if (!empty($this->_selectedResource)) {
66: return $this->_selectedResource->getId();
67: } else {
68: return parent::getId();
69: }
70: }
71:
72: /**
73: * Determine if the resource is free during the time period for the
74: * supplied event.
75: *
76: * @param mixed $event Either a Kronolith_Event object or an array
77: * containing start and end times.
78: *
79: *
80: * @return boolean
81: * @throws Kronolith_Exception
82: */
83: public function isFree($event)
84: {
85: if (is_array($event)) {
86: $start = $event['start'];
87: $end = $event['end'];
88: } else {
89: $start = $event->start;
90: $end = $event->end;
91: }
92:
93: /* Get all resources that are included in this category */
94: $resources = $this->get('members');
95:
96: /* Iterate over all resources until one with no conflicts is found */
97: foreach ($resources as $resource_id) {
98: $conflict = false;
99: $resource = $this->_driver->getResource($resource_id);
100: $busy = Kronolith::getDriver('Resource', $resource->get('calendar'))
101: ->listEvents($start, $end, true);
102:
103: /* No events at all during time period for requested event */
104: if (!count($busy)) {
105: $this->_selectedResource = $resource;
106: return true;
107: }
108:
109: /* Check for conflicts, ignoring the conflict if it's for the
110: * same event that is passed. */
111: if (!is_array($event)) {
112: $uid = $event->uid;
113: } else {
114: $uid = 0;
115: }
116:
117: foreach ($busy as $events) {
118: foreach ($events as $e) {
119: if (!($e->status == Kronolith::STATUS_CANCELLED ||
120: $e->status == Kronolith::STATUS_FREE) &&
121: $e->uid !== $uid) {
122:
123: if (!($e->start->compareDateTime($end) >= 0) &&
124: !($e->end->compareDateTime($start) <= 0)) {
125:
126: // Not free, continue to the next resource
127: $conflict = true;
128: break;
129: }
130: }
131: }
132: }
133:
134: if (!$conflict) {
135: /* No conflict detected for this resource */
136: $this->_selectedResource = $resource;
137: return true;
138: }
139: }
140:
141: /* No resource found without conflicts */
142: return false;
143: }
144:
145: /**
146: * Adds $event to an available member resource's calendar.
147: *
148: * @param $event
149: *
150: * @return void
151: */
152: public function addEvent($event)
153: {
154: throw new Horde_Exception('Events should be added to the Single resource object, not directly to the Group object.');
155: }
156:
157: /**
158: * Remove this event from resource's calendar
159: *
160: * @param $event
161: * @return unknown_type
162: */
163: public function removeEvent($event)
164: {
165: throw new Horde_Exception('Unsupported');
166: }
167:
168: /**
169: * Obtain the freebusy information for this resource.
170: *
171: * @return unknown_type
172: */
173: public function getFreeBusy($startstamp = null, $endstamp = null, $asObject = false)
174: {
175: throw new Horde_Exception('Unsupported');
176: }
177:
178: public function setId($id)
179: {
180: if (empty($this->_id)) {
181: $this->_id = $id;
182: } else {
183: throw new Horde_Exception('Resource already exists. Cannot change the id.');
184: }
185: }
186:
187: /**
188: * Group resources only make sense for RESPONSETYPE_AUTO
189: *
190: * @see lib/Resource/Kronolith_Resource_Base#getResponseType()
191: */
192: public function getResponseType()
193: {
194: return Kronolith_Resource::RESPONSETYPE_AUTO;
195: }
196:
197: }