1: <?php
2: /**
3: * Horde specific wrapper for Horde_Share drivers. Adds Horde hook calls etc...
4: *
5: * Copyright 2002-2012 Horde LLC (http://www.horde.org/)
6: *
7: * See the enclosed file COPYING for license information (LGPL). If you did
8: * not receive this file, see http://opensource.org/licenses/lgpl-2.1.php
9: *
10: * @author Michael J. Rubinsky <mrubinsk@horde.org>
11: * @category Horde
12: * @license http://opensource.org/licenses/lgpl-2.1.php LGPL
13: * @package Core
14: */
15: class Horde_Core_Share_Driver
16: {
17: /**
18: * The composed Horde_Share driver
19: *
20: * @var Horde_Share_Base
21: */
22: protected $_share;
23:
24: /**
25: * Maps the concrete share class to the required storage adapter.
26: *
27: * @var array
28: */
29: protected $_storageMap = array(
30: 'Horde_Share_Sql' => 'Horde_Db_Adapter',
31: 'Horde_Share_Sqlng' => 'Horde_Db_Adapter',
32: 'Horde_Share_Sql_Hierarchical' => 'Horde_Db_Adapter',
33: 'Horde_Share_Kolab' => 'Horde_Kolab_Storage');
34:
35: /**
36: */
37: public function __construct(Horde_Share_Base $share)
38: {
39: $this->_share = $share;
40: $this->_share->setStorage($GLOBALS['injector']->getInstance($this->_storageMap[get_class($this->_share)]));
41: $this->_share->addCallback('add', array($this, 'shareAddCallback'));
42: $this->_share->addCallback('modify', array($this, 'shareModifyCallback'));
43: $this->_share->addCallback('remove', array($this, 'shareRemoveCallback'));
44: $this->_share->addCallback('list', array($this, 'shareListCallback'));
45:
46: if (Horde::hookExists('share_init')) {
47: Horde::callHook('share_init', array($this, $this->_share->getApp()));
48: }
49: }
50:
51: /**
52: * Delegate method calls to the composed share object.
53: *
54: * @param string $method The method name
55: * @param array $args The method arguments
56: *
57: * @return mixed The result of the method call
58: */
59: public function __call($method, $args)
60: {
61: return call_user_func_array(array($this->_share, $method), $args);
62: }
63:
64: /**
65: * Lock an item belonging to a share, or an entire share itself.
66: *
67: * @param Horde_Lock $locks The lock object
68: * @param Horde_Share_Object $share The share object
69: * @param string $uid The uid of a specific object to lock,
70: * if null, entire share is locked.
71: *
72: * @return mixed A lock ID on sucess, false if:
73: * - The share is already locked,
74: * - The item is already locked,
75: * - A share lock was requested and an item is already
76: * locked in the share.
77: */
78: public function lock(Horde_Lock $locks, $uid = null)
79: {
80: $shareid = $this->_share->getId();
81:
82: // Default parameters.
83: $locktype = Horde_Lock::TYPE_EXCLUSIVE;
84: $timeout = 600;
85: $itemscope = $this->_share->getShareOb()->getApp() . ':' . $shareid;
86:
87: if (!empty($uid)) {
88: // Check if the share is locked. Share locks are placed at app scope
89: try {
90: $result = $locks->getLocks($this->_share->getShareOb()->getApp(), $shareid, $locktype);
91: } catch (Horde_Lock_Exception $e) {
92: throw new Horde_Exception_Wrapped($e);
93: }
94: if (!empty($result)) {
95: // Lock found.
96: return false;
97: }
98:
99: // Try to place the item lock at app:shareid scope.
100: return $locks->setLock($GLOBALS['registry']->getAuth(),
101: $itemscope,
102: $uid,
103: $timeout,
104: $locktype);
105: } else {
106: // Share lock requested. Check for locked items.
107: try {
108: $result = $locks->getLocks($itemscope, null, $locktype);
109: } catch (Horde_Lock_Exception $e) {
110: throw new Horde_Exception_Wrapped($e);
111: }
112: if (!empty($result)) {
113: // Lock found.
114: return false;
115: }
116:
117: // Try to place the share lock
118: return $locks->setLock($GLOBALS['registry']->getAuth(),
119: $this->_share->getShareOb()->getApp(),
120: $shareid,
121: $timeout,
122: $locktype);
123: }
124: }
125:
126: /**
127: * Removes the lock for a lock ID.
128: *
129: * @param Horde_Lock $locks The lock object
130: * @param string $lockid The lock ID as generated by a previous call
131: * to lock().
132: *
133: * @return boolean
134: */
135: public function unlock(Horde_Lock $locks, $lockid)
136: {
137: return $locks->clearLock($lockid);
138: }
139:
140: /**
141: * Checks for existing locks.
142: *
143: * First this checks for share locks and if none exists, checks for item
144: * locks (if item_uid defined). It will return the first lock found.
145: *
146: * @param Horde_Lock $locks The lock object.
147: * @param string $item_uid A uid of an item from this share.
148: *
149: * @return array Hash with the found lock information in 'lock' and the
150: * lock type ('share' or 'item') in 'type', or an empty
151: * array if there are no locks.
152: */
153: public function checkLocks(Horde_Lock $locks, $item_uid = null)
154: {
155: $shareid = $this->_share->getId();
156: $locktype = Horde_Lock::TYPE_EXCLUSIVE;
157:
158: // Check for share locks
159: try {
160: $result = $locks->getLocks($this->_share->getShareOb()->getApp(), $shareid, $locktype);
161: } catch (Horde_Lock_Exception $e) {
162: Horde::logMessage($e, 'ERR');
163: throw new Horde_Exception_Wrapped($e);
164: }
165:
166: if (empty($result) && !empty($item_uid)) {
167: // Check for item locks
168: $locktargettype = 'item';
169: try {
170: $result = $locks->getLocks($this->_share->getShareOb()->getApp() . ':' . $shareid, $item_uid, $locktype);
171: } catch (Horde_Lock_Exception $e) {
172: Horde::logMessage($e, 'ERR');
173: throw new Horde_Exception($e->getMessage());
174: }
175: } else {
176: $locktargettype = 'share';
177: }
178:
179: if (empty($result)) {
180: return array();
181: }
182:
183: return array('type' => $locktargettype,
184: 'lock' => reset($result));
185: }
186:
187: /**
188: * share_list callback
189: *
190: * @param string $userid The userid listShares was called with
191: * @param array $shares The result of the listShares() call
192: * @param array $params The params that listShares() was called with
193: *
194: * @return array An array of share objects
195: */
196: public function shareListCallback($userid, $shares, $params = array())
197: {
198: if (Horde::hookExists('share_list')) {
199: $params = new Horde_Support_Array($params);
200: return Horde::callHook('share_list', array($userid, $params['perm'], $params['attributes'], $shares));
201: }
202:
203: return $shares;
204: }
205:
206: /**
207: * Adds the share_add hook before delegating to the share object.
208: *
209: * @param Horde_Share_Object The share object being added
210: */
211: public function shareAddCallback(Horde_Share_Object $share)
212: {
213: try {
214: Horde::callHook('share_add', array($share));
215: } catch (Horde_Exception_HookNotSet $e) {
216: }
217: }
218:
219: /**
220: * Calls the share_remove hook before delegating to the share object.
221: *
222: * @see Horde_Share_Base::removeShare()
223: */
224: public function shareRemoveCallback(Horde_Share_Object $share)
225: {
226: try {
227: Horde::callHook('share_remove', array($share));
228: } catch (Horde_Exception_HookNotSet $e) {
229: }
230: }
231:
232: public function shareModifyCallback(Horde_Share_Object $share)
233: {
234: try {
235: Horde::callHook('share_modify', array($share));
236: } catch (Horde_Exception_HookNotSet $e) {
237: }
238: }
239:
240: }