Overview

Packages

  • None
  • Share

Classes

  • Horde_Share_Base
  • Horde_Share_Datatree
  • Horde_Share_Kolab
  • Horde_Share_Object
  • Horde_Share_Object_Datatree
  • Horde_Share_Object_DataTree_Share
  • Horde_Share_Object_Kolab
  • Horde_Share_Object_Sql
  • Horde_Share_Object_Sqlng
  • Horde_Share_Sql
  • Horde_Share_Sqlng
  • Horde_Share_Translation
  • Overview
  • Package
  • Class
  • Tree
  1: <?php
  2: /**
  3:  * Horde_Share_Sql provides the SQL backend for the Horde share system.
  4:  *
  5:  * Copyright 2008-2012 Horde LLC (http://www.horde.org/)
  6:  *
  7:  * See the enclosed file COPYING for license information (LGPL). If you
  8:  * did not receive this file, see http://www.horde.org/licenses/lgpl21.
  9:  *
 10:  * @author  Duck <duck@obala.net>
 11:  * @author  Michael J. Rubinsky <mrubinsk@horde.org>
 12:  * @package Share
 13:  */
 14: 
 15: /**
 16:  * @package Share
 17:  */
 18: class Horde_Share_Sql extends Horde_Share_Base
 19: {
 20:     /* Share has user perms */
 21:     const SQL_FLAG_USERS = 1;
 22: 
 23:     /* Share has group perms */
 24:     const SQL_FLAG_GROUPS = 2;
 25: 
 26:     /* Serializable version */
 27:     const VERSION = 1;
 28: 
 29:     /**
 30:      * Handle for the current database connection.
 31:      *
 32:      * @var Horde_Db_Adapter
 33:      */
 34:     protected $_db;
 35: 
 36:     /**
 37:      * Main share table for the current scope.
 38:      *
 39:      * @var string
 40:      */
 41:     protected $_table;
 42: 
 43:     /**
 44:      * The Horde_Share_Object subclass to instantiate objects as
 45:      *
 46:      * @var string
 47:      */
 48:     protected $_shareObject = 'Horde_Share_Object_Sql';
 49: 
 50:     /**
 51:      *
 52:      * @see Horde_Share_Base::__construct()
 53:      */
 54:     public function __construct($app, $user, Horde_Perms_Base $perms,
 55:                                 Horde_Group_Base $groups)
 56:     {
 57:         parent::__construct($app, $user, $perms, $groups);
 58:         $this->_table = $this->_app . '_shares';
 59:     }
 60: 
 61:     /**
 62:      * Set the SQL table name to use for the current scope's share storage.
 63:      *
 64:      * @var string $table  The table name
 65:      */
 66:     public function setTable($table)
 67:     {
 68:         $this->_table = $table;
 69:     }
 70: 
 71:     /**
 72:      * Get storage table
 73:      *
 74:      * @return string
 75:      */
 76:     public function getTable()
 77:     {
 78:         return $this->_table;
 79:     }
 80: 
 81:     public function setStorage(Horde_Db_Adapter $db)
 82:     {
 83:         $this->_db = $db;
 84:     }
 85: 
 86:     /**
 87:      *
 88:      * @return Horde_Db_Adapter
 89:      */
 90:     public function getStorage()
 91:     {
 92:         return $this->_db;
 93:     }
 94: 
 95:     /**
 96:      * Finds out if the share has user set
 97:      *
 98:      * @param boolean
 99:      */
100:     protected function _hasUsers($share)
101:     {
102:         return $share['share_flags'] & self::SQL_FLAG_USERS;
103:     }
104: 
105:     /**
106:      * Finds out if the share has user set
107:      */
108:     protected function _hasGroups($share)
109:     {
110:         return $share['share_flags'] & self::SQL_FLAG_GROUPS;
111:     }
112: 
113:     /**
114:      * Get users permissions
115:      *
116:      * @param array $share Share data array
117:      *
118:      * @throws Horde_Share_Exception
119:      */
120:     protected function _getShareUsers(&$share)
121:     {
122:         if (!$this->_hasUsers($share)) {
123:             return;
124:         }
125: 
126:         try {
127:             $rows = $this->_db->selectAll('SELECT * FROM ' . $this->_table . '_users WHERE share_id = ?', array($share['share_id']));
128:         } catch (Horde_Db_Exception $e) {
129:             throw new Horde_Share_Exception($e->getMessage());
130:         }
131: 
132:         foreach ($rows as $row) {
133:             $share['perm']['users'][$row['user_uid']] = $this->_buildPermsFromRow($row);
134:         }
135:     }
136: 
137:     /**
138:      * Get groups permissions
139:      *
140:      * @param array $share Share data array
141:      *
142:      * @throws Horde_Share_Exception
143:      */
144:     protected function _getShareGroups(&$share)
145:     {
146:         if (!$this->_hasGroups($share)) {
147:             return;
148:         }
149: 
150:         try {
151:             $rows = $this->_db->selectAll('SELECT * FROM ' . $this->_table . '_groups WHERE share_id = ?', array($share['share_id']));
152:         } catch (Horde_Db_Exception $e) {
153:             throw new Horde_Share_Exception($e->getMessage());
154:         }
155: 
156:         foreach ($rows as $row) {
157:             $share['perm']['groups'][$row['group_uid']] = $this->_buildPermsFromRow($row);
158:         }
159:     }
160: 
161:     /**
162:      * Returns a Horde_Share_Object_sql object corresponding to the given
163:      * share name, with the details retrieved appropriately.
164:      *
165:      * @param string $name  The name of the share to retrieve.
166:      *
167:      * @return Horde_Share_Object  The requested share.
168:      * @throws Horde_Exception_NotFound
169:      * @throws Horde_Share_Exception
170:      */
171:     protected function _getShare($name)
172:     {
173:         try {
174:             $results = $this->_db->selectOne('SELECT * FROM ' . $this->_table . ' WHERE share_name = ?', array($name));
175:         } catch (Horde_Db_Exception $e) {
176:             throw new Horde_Share_Exception($e->getMessage());
177:         }
178:         if (!$results) {
179:             $this->_logger->err(sprintf('Share name %s not found', $name));
180:             throw new Horde_Exception_NotFound(sprintf('Share name %s not found', $name));
181:         }
182:         $data = $this->_fromDriverCharset($results);
183:         $this->_loadPermissions($data);
184: 
185:         return $this->_createObject($data);
186:     }
187: 
188:     protected function _createObject(array $data = array())
189:     {
190:         $object = new $this->_shareObject($data);
191:         $this->initShareObject($object);
192: 
193:         return $object;
194:     }
195: 
196:     /**
197:      * Helper function to load the permissions data into the share data
198:      *
199:      * @param array $data  Array of share attributes
200:      */
201:     protected function _loadPermissions(&$data)
202:     {
203:         $this->_getShareUsers($data);
204:         $this->_getShareGroups($data);
205:         $this->_getSharePerms($data);
206:     }
207: 
208:     protected function _getSharePerms(&$data)
209:     {
210:         $data['perm']['type'] = 'matrix';
211:         $data['perm']['default'] = isset($data['perm_default']) ? (int)$data['perm_default'] : 0;
212:         $data['perm']['guest'] = isset($data['perm_guest']) ? (int)$data['perm_guest'] : 0;
213:         $data['perm']['creator'] = isset($data['perm_creator']) ? (int)$data['perm_creator'] : 0;
214:         unset($data['perm_creator'], $data['perm_guest'], $data['perm_default']);
215:     }
216: 
217:     /**
218:      * Returns a Horde_Share_Object_sql object corresponding to the given
219:      * unique ID, with the details retrieved appropriately.
220:      *
221:      * @param integer $id  The id of the share to retrieve.
222:      *
223:      * @return Horde_Share_Object_sql  The requested share.
224:      * @throws Horde_Share_Exception, Horde_Exception_NotFound
225:      */
226:     protected function _getShareById($id)
227:     {
228:         try {
229:             $results = $this->_db->selectOne('SELECT * FROM ' . $this->_table . ' WHERE share_id = ?', array($id));
230:         } catch (Horde_Db_Exception $e) {
231:             throw new Horde_Share_Exception($e->getMessage());
232:         }
233:         if (!$results) {
234:             $this->_logger->err(sprintf('Share id %s not found', $id));
235:             throw new Horde_Exception_NotFound();
236:         }
237:         $data = $this->_fromDriverCharset($results);
238:         $this->_loadPermissions($data);
239: 
240:         return $this->_createObject($data);
241:     }
242: 
243:     /**
244:      * Returns an array of Horde_Share_Object objects corresponding
245:      * to the given set of unique IDs, with the details retrieved
246:      * appropriately.
247:      *
248:      * @param array $ids   The array of ids to retrieve.
249:      * @param string $key  The column name that should for the list keys.
250:      *
251:      * @return array  The requested shares.
252:      * @throws Horde_Share_Exception
253:      */
254:     protected function _getShares(array $ids)
255:     {
256:         try {
257:             $rows = $this->_db->selectAll('SELECT * FROM ' . $this->_table . ' WHERE share_id IN (' . str_repeat('?, ', count($ids) - 1) . '?)', $ids);
258:         } catch (Horde_Db_Exception $e) {
259:             throw new Horde_Share_Exception($e->getMessage());
260:         }
261: 
262:         $sharelist = array();
263:         foreach ($rows as $share) {
264:             $this->_loadPermissions($share);
265:             $sharelist[$share['share_name']] = $this->_createObject($share);
266:         }
267: 
268:         return $sharelist;
269:     }
270: 
271:     /**
272:      * Lists *all* shares for the current app/share, regardless of permissions.
273:      *
274:      * This is for admin functionality and scripting tools, and shouldn't be
275:      * called from user-level code!
276:      *
277:      * @return array  All shares for the current app/share.
278:      * @throws Horde_Share_Exception
279:      */
280:     public function listAllShares()
281:     {
282:         return $this->_listAllShares();
283:     }
284: 
285:     /**
286:      * Lists *all* shares for the current app/share, regardless of permissions.
287:      *
288:      * @return array  All shares for the current app/share.
289:      * @throws Horde_Share_Exception
290:      */
291:     protected function _listAllShares()
292:     {
293:         $shares = array();
294: 
295:         try {
296:             $rows = $this->_db->selectAll('SELECT * FROM ' . $this->_table . ' ORDER BY share_name ASC');
297:         } catch (Horde_Db_Exception $e) {
298:             throw new Horde_Share_Exception($e->getMessage());
299:         }
300: 
301:         foreach ($rows as $share) {
302:             $shares[(int)$share['share_id']] = $this->_fromDriverCharset($share);
303:         }
304: 
305:         // Get users permissions
306:         try {
307:             $rows = $this->_db->selectAll('SELECT * FROM ' . $this->_table . '_users');
308:         } catch (Horde_Db_Exception $e) {
309:             throw new Horde_Share_Exception($e);
310:         }
311:         foreach ($rows as $row) {
312:             $shares[$row['share_id']]['perm']['users'][$row['user_uid']] = $this->_buildPermsFromRow($row);
313:         }
314: 
315:         // Get groups permissions
316:         try {
317:             $rows = $this->_db->selectAll('SELECT * FROM ' . $this->_table . '_groups');
318:         } catch (Horde_Db_Exception $e) {
319:             throw new Horde_Share_Exception($e->getMessage());
320:         }
321:         foreach ($rows as $row) {
322:             $shares[$row['share_id']]['perm']['groups'][$row['group_uid']] = $this->_buildPermsFromRow($row);
323:         }
324: 
325:         $sharelist = array();
326:         foreach ($shares as $data) {
327:             $this->_getSharePerms($data);
328:             if (!empty($data['share_name'])) {
329:                 $sharelist[$data['share_name']] = $this->_createObject($data);
330:             } else {
331:                 $sharelist[] = $this->_createObject($data);
332:             }
333:         }
334: 
335:         return $sharelist;
336:     }
337: 
338:     /**
339:      * Returns an array of all shares that $userid has access to.
340:      *
341:      * @param string $userid  The userid of the user to check access for. An
342:      *                        empty value for the userid will only return shares
343:      *                        with guest access.
344:      * @param array $params   Additional parameters for the search.
345:      *<pre>
346:      *  'perm'          Require this level of permissions. Horde_Perms constant.
347:      *  'attribtues'    Restrict shares to these attributes. A hash or username.
348:      *  'from'          Offset. Start at this share
349:      *  'count'         Limit.  Only return this many.
350:      *  'sort_by'       Sort by attribute.
351:      *  'direction'     Sort by direction.
352:      *  'parent'        Start at this share in the hierarchy. Either share_id or
353:      *                  Horde_Share_Object
354:      *  'all_levels'    List all levels or just the direct children of parent?
355:      *</pre>
356:      *
357:      * @return array  The shares the user has access to.
358:      * @throws Horde_Share_Exception
359:      */
360:     public function listShares($userid, array $params = array())
361:     {
362:         $params = array_merge(array('perm' => Horde_Perms::SHOW,
363:                                     'attributes' => null,
364:                                     'from' => 0,
365:                                     'count' => 0,
366:                                     'sort_by' => null,
367:                                     'direction' => 0,
368:                                     'parent' => null,
369:                                     'all_levels' => true),
370:                               $params);
371:         $key = md5(serialize(array($userid, $params)));
372:         if (isset($this->_listcache[$key])) {
373:             return $this->_listcache[$key];
374:         }
375:         $shares = array();
376:         if (is_null($params['sort_by'])) {
377:             $sortfield = 's.share_id';
378:         } elseif ($params['sort_by'] == 'owner' || $params['sort_by'] == 'id') {
379:             $sortfield = 's.share_' . $params['sort_by'];
380:         } else {
381:             $sortfield = 's.attribute_' . $params['sort_by'];
382:         }
383: 
384:         $query = 'SELECT DISTINCT s.* '
385:             . $this->getShareCriteria($userid, $params['perm'], $params['attributes'], $params['parent'], $params['all_levels'])
386:             . ' ORDER BY ' . $sortfield
387:             . (($params['direction'] == 0) ? ' ASC' : ' DESC');
388: 
389:         $query = $this->_db->addLimitOffset($query, array('limit' => $params['count'], 'offset' => $params['from']));
390:         try {
391:             $rows = $this->_db->selectAll($query);
392:         } catch (Horde_Db_Exception $e) {
393:             throw new Horde_Share_Exception($e->getMessage());
394:         }
395: 
396:         $users = array();
397:         $groups = array();
398:         foreach ($rows as $share) {
399:             $shares[(int)$share['share_id']] = $this->_fromDriverCharset($share);
400:             if ($this->_hasUsers($share)) {
401:                 $users[] = (int)$share['share_id'];
402:             }
403:             if ($this->_hasGroups($share)) {
404:                 $groups[] = (int)$share['share_id'];
405:             }
406:         }
407: 
408:         // Get users permissions
409:         if (!empty($users)) {
410:             $query = 'SELECT share_id, user_uid, perm FROM ' . $this->_table
411:                      . '_users WHERE share_id IN (' . str_repeat('?,', count($users) - 1) . '?)';
412: 
413:             try {
414:                 $rows = $this->_db->selectAll($query, $users);
415:             } catch (Horde_Db_Exception $e) {
416:                 throw new Horde_Share_Exception($e->getMessage());
417:             }
418:             foreach ($rows as $share) {
419:                     $shares[$share['share_id']]['perm']['users'][$share['user_uid']] = (int)$share['perm'];
420:             }
421:         }
422: 
423:         // Get groups permissions
424:         if (!empty($groups)) {
425:             $query = 'SELECT share_id, group_uid, perm FROM ' . $this->_table
426:                      . '_groups WHERE share_id IN (' . str_repeat('?,', count($groups) - 1) . '?)';
427:             try {
428:                 $rows = $this->_db->selectAll($query, $groups);
429:             } catch (Horde_Db_Exception $e) {
430:                 throw new Horde_Share_Exception($e->getMessage());
431:             }
432:             foreach ($rows as $share) {
433:                 $shares[$share['share_id']]['perm']['groups'][$share['group_uid']] = (int)$share['perm'];
434:             }
435:         }
436: 
437:         $sharelist = array();
438:         foreach ($shares as $id => $data) {
439:             $this->_getSharePerms($data);
440:             $sharelist[$data['share_name']] = $this->_createObject($data);
441:         }
442:         unset($shares);
443: 
444:         // Run the results through the callback, if configured.
445:         if (!empty($this->_callbacks['list'])) {
446:             $sharelist = $this->runCallback('list', array($userid, $sharelist, $params));
447:         }
448: 
449:         $this->_listcache[$key] = $sharelist;
450: 
451:         return $sharelist;
452:     }
453: 
454:     /**
455:      * Return a list of users who have shares with the given permissions
456:      * for the current user.
457:      *
458:      * @param integer $perm       The level of permissions required.
459:      * @param mixed  $parent      The parent share to start looking in.
460:      *                            (Horde_Share_Object, share_id, or null)
461:      * @param boolean $allLevels  Return all levels, or just the direct
462:      *                            children of $parent? Defaults to all levels.
463:      * @param integer $from       The user to start listing at.
464:      * @param integer $count      The number of users to return.
465:      *
466:      * @return array  List of users.
467:      * @throws Horde_Share_Exception
468:      */
469:     public function listOwners($perm = Horde_Perms::SHOW, $parent = null, $allLevels = true,
470:                                $from = 0, $count = 0)
471:     {
472:         $sql = 'SELECT DISTINCT(s.share_owner) '
473:             . $this->getShareCriteria($this->_user, $perm, null, $parent, $allLevels);
474: 
475:         if ($count) {
476:             $sql = $this->_db->addLimitOffset($sql, array('limit' => $count, 'offset' => $from));
477:         }
478: 
479:         try {
480:             $allowners = $this->_db->selectValues($sql);
481:         } catch (Horde_Db_Exception $e) {
482:             throw new Horde_Share_Exception($e);
483:         }
484: 
485:         $owners = array();
486:         foreach ($allowners as $owner) {
487:             if ($this->countShares($this->_user, $perm, $owner, $parent, $allLevels)) {
488:                 $owners[] = $owner;
489:             }
490:         }
491: 
492:         return $owners;
493:     }
494: 
495:     /**
496:      * Count the number of users who have shares with the given permissions
497:      * for the current user.
498:      *
499:      * @param integer $perm       The level of permissions required.
500:      * @param mixed $parent       The parent share to start looking in.
501:      *                            (Horde_Share_Object, share_id, or null).
502:      * @param boolean $allLevels  Return all levels, or just the direct
503:      *                            children of $parent?
504:      *
505:      * @return integer  Number of users.
506:      * @throws Horde_Share_Exception
507:      */
508:     public function countOwners($perm = Horde_Perms::SHOW, $parent = null, $allLevels = true)
509:     {
510:         $sql = 'SELECT COUNT(DISTINCT(s.share_owner)) '
511:             . $this->getShareCriteria($this->_user, $perm, null, $parent, $allLevels);
512: 
513:         try {
514:             $results = $this->_db->selectValue($sql);
515:         } catch (Horde_Db_Exception $e) {
516:             throw new Horde_Share_Exception($e);
517:         }
518: 
519:         return $results;
520:     }
521: 
522:     /**
523:      * Returns a share's direct parent object.
524:      *
525:      * @param Horde_Share_Object $child  The share to get parent for.
526:      *
527:      * @return Horde_Share_Object The parent share, if it exists.
528:      */
529:     public function getParent(Horde_Share_Object $child)
530:     {
531:         $parents = $child->get('parents');
532: 
533:         // No parents, this is at the root.
534:         if (empty($parents)) {
535:             return null;
536:         }
537:         $parents = explode(':', $parents);
538: 
539:         return $this->getShareById(array_pop($parents));
540:     }
541: 
542:     /**
543:      * Returns an array of all shares that $userid has access to.
544:      *
545:      * @param string $userid     The userid of the user to check access for.
546:      * @param array  $params     See listShares().
547:      *
548:      * @return array  The shares the user has access to.
549:      */
550:     protected function _listShares($userid, array $params = array())
551:     {
552:         // We overwrite listShares(), this method is only implemented because
553:         // it's abstract in the base class.
554:     }
555: 
556:     /**
557:      * Returns an array of all system shares.
558:      *
559:      * @return array  All system shares.
560:      * @throws Horde_Share_Exception
561:      */
562:     public function listSystemShares()
563:     {
564:         $query = 'SELECT * FROM ' . $this->_table . ' WHERE share_owner IS NULL';
565:         try {
566:             $rows = $this->_db->selectAll($query);
567:         } catch (Horde_Db_Exception $e) {
568:             throw new Horde_Share_Exception($e->getMessage());;
569:         }
570: 
571:         $sharelist = array();
572:         foreach ($rows as $share) {
573:             $data = $this->_fromDriverCharset($share);
574:             $this->_getSharePerms($data);
575:             $sharelist[$data['share_name']] = $this->_createObject($data);
576:         }
577: 
578:         return $sharelist;
579:     }
580: 
581:     /**
582:      * Returns the count of all shares that $userid has access to.
583:      *
584:      * @param string  $userid      The userid of the user to check access for.
585:      * @param integer $perm        The level of permissions required.
586:      * @param mixed   $attributes  Restrict the shares counted to those
587:      *                             matching $attributes. An array of
588:      *                             attribute/values pairs or a share owner
589:      *                             username.
590:      * @param mixed  $parent      The share to start searching from
591:      *                            (Horde_Share_Object, share_id, or null)
592:      * @param boolean $allLevels  Return all levels, or just the direct
593:      *                            children of $parent?
594:      *
595:      * @return integer  Number of shares the user has access to.
596:      * @throws Horde_Share_Exception
597:      */
598:     public function countShares($userid, $perm = Horde_Perms::SHOW,
599:         $attributes = null, $parent = null, $allLevels = true)
600:     {
601:         $query = 'SELECT COUNT(DISTINCT s.share_id) '
602:             . $this->getShareCriteria($userid, $perm, $attributes, $parent, $allLevels);
603: 
604:         try {
605:             $this->_db->selectValue($query);
606:         } catch (Horde_Db_Exception $e) {
607:             throw new Horde_Share_Exception($e);
608:         }
609: 
610:         return $this->_db->selectValue($query);
611:     }
612: 
613:     /**
614:      * Returns a new share object.
615:      *
616:      * @param string $name   The share's name.
617:      *
618:      * @return Horde_Share_Object  A new share object
619:      * @throws InvalidArgumentException
620:      */
621:     protected function _newShare($name)
622:     {
623:         if (empty($name)) {
624:             throw new InvalidArgumentException('Share names must be non-empty');
625:         }
626: 
627:         return $this->_createObject(array('share_name' => $name));
628:     }
629: 
630:     /**
631:      * Adds a share to the shares system.
632:      *
633:      * The share must first be created with
634:      * Horde_Share_sql::_newShare(), and have any initial details added
635:      * to it, before this function is called.
636:      *
637:      * @param Horde_Share_Object $share  The new share object.
638:      */
639:     protected function _addShare(Horde_Share_Object $share)
640:     {
641:         $share->save();
642:     }
643: 
644:     /**
645:      * Removes a share from the shares system permanently.
646:      *
647:      * @param Horde_Share_Object $share  The share to remove.
648:      *
649:      * @throws Horde_Share_Exception
650:      */
651:     public function removeShare(Horde_Share_Object $share)
652:     {
653:         // First Remove Children
654:         foreach ($share->getChildren(null, null, true) as $child) {
655:             $this->removeShare($child);
656:         }
657: 
658:         // Run the results through the callback, if configured.
659:         $this->runCallback('remove', array($share));
660: 
661:         /* Remove share from the caches. */
662:         $id = $share->getId();
663:         unset($this->_shareMap[$id]);
664:         unset($this->_cache[$share->getName()]);
665: 
666:         /* Reset caches that depend on unknown criteria. */
667:         $this->expireListCache();
668: 
669:         $this->_removeShare($share);
670:     }
671: 
672:     /**
673:      * Removes a share from the shares system permanently.
674:      *
675:      * @param Horde_Share_Object $share  The share to remove.
676:      *
677:      * @return boolean
678:      * @throws Horde_Share_Exception
679:      */
680:     protected function _removeShare(Horde_Share_Object $share)
681:     {
682:         $params = array($share->getId());
683:         $tables = array($this->_table,
684:                         $this->_table . '_users',
685:                         $this->_table . '_groups');
686:         foreach ($tables as $table) {
687:             try {
688:                 $this->_db->delete('DELETE FROM ' . $table . ' WHERE share_id = ?', $params);
689:             } catch (Horde_Db_Exception $e) {
690:                 throw new Horde_Share_Exception($e->getMessage());
691:             }
692:         }
693:     }
694: 
695:     /**
696:      * Renames a share in the shares system.
697:      *
698:      * @param Horde_Share_Object $share  The share to rename.
699:      * @param string $name               The share's new name.
700:      *
701:      * @throws Horde_Share_Exception
702:      */
703:     protected function _renameShare(Horde_Share_Object $share, $name)
704:     {
705:         try {
706:             $this->_db->update(
707:                 'UPDATE ' . $this->_table . ' SET share_name = ? WHERE share_id = ?',
708:                 array($name, $share->getId()));
709:         } catch (Horde_Db_Exception $e) {
710:             throw new Horde_Share_Exception($e);
711:         }
712:     }
713: 
714:     /**
715:      * Checks if a share exists in the system.
716:      *
717:      * @param string $share  The share to check.
718:      *
719:      * @return boolean  True if the share exists.
720:      * @throws Horde_Share_Exception
721:      */
722:     protected function _exists($share)
723:     {
724:         try {
725:             return (boolean)$this->_db->selectOne('SELECT 1 FROM ' . $this->_table . ' WHERE share_name = ?', array($share));
726:         } catch (Horde_Db_Exception $e) {
727:             throw new Horde_Share_Exception($e);
728:         }
729:     }
730: 
731:     /**
732:      * Check that a share id exists in the system.
733:      *
734:      * @param integer $id  The share id
735:      *
736:      * @return boolean True if the share exists.
737:      */
738:     protected function _idExists($id)
739:     {
740:         try {
741:             return (boolean)$this->_db->selectOne('SELECT 1 FROM ' . $this->_table . ' WHERE share_id = ?', array($id));
742:         } catch (Horde_Db_Exception $e) {
743:             throw new Horde_Share_Exception($e);
744:         }
745:     }
746: 
747:     /**
748:      * Returns an array of criteria for querying shares.
749:      *
750:      * @TODO Make this method protected, like all the other drivers.
751:      *
752:      * @param string $userid      The userid of the user to check access for.
753:      * @param integer $perm       The level of permissions required. Set to null
754:      *                            to skip permission filtering.
755:      * @param mixed $attributes   Restrict the shares returned to those who
756:      *                            have these attribute values.
757:      * @param mixed $parent       The share to start searching in.
758:      *                            (A Horde_Share_Object, share_id or null)
759:      * @param boolean $allLevels  Return all levels, or just the direct
760:      *                            children of $parent? Defaults to all levels.
761:      *
762:      * @return string  The criteria string for fetching this user's shares.
763:      * @throws Horde_Share_Exception
764:      */
765:     public function getShareCriteria($userid, $perm = Horde_Perms::SHOW,
766:                                      $attributes = null, $parent = null,
767:                                      $allLevels = true)
768:     {
769:         $query = $where = '';
770:         if (!is_null($perm)) {
771:             list($query, $where) = $this->_getUserAndGroupCriteria($userid, $perm);
772:         }
773:         $query = ' FROM ' . $this->_table . ' s ' . $query;
774: 
775:         /* Convert to driver's keys */
776:         $attributes = $this->_toDriverKeys($attributes);
777: 
778:         /* ...and to driver charset */
779:         $attributes = $this->toDriverCharset($attributes);
780: 
781:         if (is_array($attributes)) {
782:             // Build attribute/key filter.
783:             if (!empty($where)) {
784:                 $where = ' (' . $where . ') ';
785:             }
786:             foreach ($attributes as $key => $value) {
787:                 if (is_array($value)) {
788:                     $value = array_map(array($this->_db, 'quote'), $value);
789:                     $where .= ' AND ' . $key . ' IN (' . implode(', ', $value) . ')';
790:                 } else {
791:                     $where .= ' AND ' . $key . ' = ' . $this->_db->quote($value);
792:                 }
793:             }
794:         } elseif (!empty($attributes)) {
795:             // Restrict to shares owned by the user specified
796:             $where = (!empty($where) ? ' (' . $where . ') AND ' : ' ') . 's.share_owner = ' . $this->_db->quote($attributes);
797:         }
798: 
799:         // See if we need to filter by parent or get the parent object
800:         if ($parent != null) {
801:             if (!($parent instanceof Horde_Share_Object)) {
802:                 $parent = $this->getShareById($parent);
803:             }
804: 
805:             // Need to append the parent's share id to the list of parents in
806:             // order to search the share_parents field.
807:             $parents = $parent->get('parents') . ':' . $parent->getId();
808:             if ($allLevels) {
809:                 $where_parent = '(share_parents = ' . $this->_db->quote($parents)
810:                     . ' OR share_parents LIKE ' . $this->_db->quote($parents . ':%') . ')';
811:             } else {
812:                 $where_parent = 's.share_parents = ' . $this->_db->quote($parents);
813:             }
814:         } elseif (!$allLevels) {
815:             // No parents, and we only want the root.
816:             $where_parent = "(s.share_parents = '' OR s.share_parents IS NULL)";
817:         }
818: 
819:         if (!empty($where_parent)) {
820:             if (empty($where)) {
821:                 $where = $where_parent;
822:             } else {
823:                 $where = '(' . $where . ') AND ' . $where_parent;
824:             }
825:         }
826: 
827:         return $query . ' WHERE ' . $where;
828:     }
829: 
830:     /**
831:      * Returns criteria statement fragments for querying shares.
832:      *
833:      * @param string  $userid  The userid of the user to check access for.
834:      * @param integer $perm    The level of permissions required.
835:      *
836:      * @return array  An array with query and where string fragments.
837:      */
838:     protected function _getUserAndGroupCriteria($userid,
839:                                                 $perm = Horde_Perms::SHOW)
840:     {
841:         $query = $where = '';
842: 
843:         if (empty($userid)) {
844:             $where = '(' . $this->_db->buildClause('s.perm_guest', '&', $perm) . ')';
845:         } else {
846:             // (owner == $userid)
847:             $where .= 's.share_owner = ' . $this->_db->quote($userid);
848: 
849:             // (name == perm_creator and val & $perm)
850:             $where .= ' OR (' . $this->_db->buildClause('s.perm_creator', '&', $perm) . ')';
851: 
852:             // (name == perm_creator and val & $perm)
853:             $where .= ' OR (' . $this->_db->buildClause('s.perm_default', '&', $perm) . ')';
854: 
855:             // (name == perm_users and key == $userid and val & $perm)
856:             $query .= ' LEFT JOIN ' . $this->_table . '_users u ON u.share_id = s.share_id';
857:             $where .= ' OR ( u.user_uid = ' .  $this->_db->quote($userid)
858:             . ' AND (' . $this->_db->buildClause('u.perm', '&', $perm) . '))';
859: 
860:             // If the user has any group memberships, check for those also.
861:             try {
862:                 $groups = $this->_groups->listGroups($userid);
863:                 if ($groups) {
864:                     // (name == perm_groups and key in ($groups) and val & $perm)
865:                     $ids = array_keys($groups);
866:                     $group_ids = array();
867:                     foreach ($ids as $id) {
868:                         $group_ids[] = $this->_db->quote((string)$id);
869:                     }
870:                     $query .= ' LEFT JOIN ' . $this->_table . '_groups g ON g.share_id = s.share_id';
871:                     $where .= ' OR (g.group_uid IN (' . implode(',', $group_ids)
872:                         . ') AND (' . $this->_db->buildClause('g.perm', '&', $perm) . '))';
873:                 }
874:             } catch (Horde_Group_Exception $e) {
875:                 $this->_logger->err($e);
876:             }
877:         }
878: 
879:         return array($query, $where);
880:     }
881: 
882:     /**
883:      * Builds a permission bit mask from the "perm" column.
884:      *
885:      * @param array $row     A data row including permission columns.
886:      *
887:      * @return integer  A permission mask.
888:      */
889:     protected function _buildPermsFromRow($row)
890:     {
891:         return (int)$row['perm'];
892:     }
893: 
894:     /**
895:      * Utility function to convert from the SQL server's charset.
896:      */
897:     protected function _fromDriverCharset($data)
898:     {
899:         foreach ($data as $key => &$value) {
900:             if (substr($key, 0, 9) == 'attribute') {
901:                 $value = Horde_String::convertCharset(
902:                     $value, $this->_db->getOption('charset'), 'UTF-8');
903:             }
904:         }
905: 
906:         return $data;
907:     }
908: 
909:     /**
910:      * Utility function to convert TO the SQL server's charset.
911:      *
912:      * @see Horde_Share#toDriverCharset
913:      */
914:     public function toDriverCharset($data)
915:     {
916:         if (!is_array($data)) {
917:             return $data;
918:         }
919: 
920:         foreach ($data as $key => &$value) {
921:             if (substr($key, 0, 9) == 'attribute') {
922:                 $value = Horde_String::convertCharset(
923:                     $value, 'UTF-8', $this->_db->getOption('charset'));
924:             }
925:         }
926: 
927:         return $data;
928:     }
929: 
930:     /**
931:      * Convert an array keyed on client keys to an array keyed on the driver
932:      * keys.
933:      *
934:      * @param array  $data  The client code keyed array.
935:      *
936:      * @return array  The driver keyed array.
937:      */
938:     protected function _toDriverKeys($data)
939:     {
940:         if (!is_array($data)) {
941:             return $data;
942:         }
943: 
944:         $driver_keys = array();
945:         foreach ($data as $key => $value) {
946:             if ($key == 'owner') {
947:                 $driver_keys['share_owner'] = $value;
948:             } else {
949:                 $driver_keys['attribute_' . $key] = $value;
950:             }
951:         }
952: 
953:         return $driver_keys;
954:     }
955: 
956: }
957: 
API documentation generated by ApiGen