Overview

Packages

  • Vfs

Classes

  • Horde_Vfs
  • Horde_Vfs_Base
  • Horde_Vfs_Browser
  • Horde_Vfs_Exception
  • Horde_Vfs_File
  • Horde_Vfs_Ftp
  • Horde_Vfs_Gc
  • Horde_Vfs_Horde
  • Horde_Vfs_Kolab
  • Horde_Vfs_ListItem
  • Horde_Vfs_Musql
  • Horde_Vfs_Object
  • Horde_Vfs_Smb
  • Horde_Vfs_Sql
  • Horde_Vfs_SqlFile
  • Horde_Vfs_Ssh2
  • Horde_Vfs_Translation
  • Overview
  • Package
  • Class
  • Tree
  1: <?php
  2: /**
  3:  * VFS implementation for Horde's database abstraction layer.
  4:  *
  5:  * Required values for $params:
  6:  * - db: A Horde_Db_Adapter object.
  7:  *
  8:  * Optional values:
  9:  * - table: (string) The name of the vfs table in 'database'. Defaults to
 10:  *          'horde_vfs'.
 11:  *
 12:  * The table structure for the VFS can be created with the horde-db-migrate
 13:  * script from the Horde_Db package.
 14:  *
 15:  * Copyright 2002-2012 Horde LLC (http://www.horde.org/)
 16:  *
 17:  * See the enclosed file COPYING for license information (LGPL). If you
 18:  * did not receive this file, see http://www.horde.org/licenses/lgpl21.
 19:  *
 20:  * @author   Chuck Hagenbuch <chuck@horde.org>
 21:  * @author   Jan Schneider <jan@horde.org>
 22:  * @category Horde
 23:  * @license  http://www.horde.org/licenses/lgpl21 LGPL 2.1
 24:  * @package  VFS
 25:  */
 26: class Horde_Vfs_Sql extends Horde_Vfs_Base
 27: {
 28:     /* File value for vfs_type column. */
 29:     const FILE = 1;
 30: 
 31:     /* Folder value for vfs_type column. */
 32:     const FOLDER = 2;
 33: 
 34:     /**
 35:      * Handle for the current database connection.
 36:      *
 37:      * @var Horde_Db
 38:      */
 39:     protected $_db = false;
 40: 
 41:     /**
 42:      * Constructor.
 43:      *
 44:      * @param array $params  A hash containing connection parameters.
 45:      */
 46:     public function __construct($params = array())
 47:     {
 48:         $params = array_merge(array('table' => 'horde_vfs'), $params);
 49:         parent::__construct($params);
 50:         $this->_db = $this->_params['db'];
 51:         unset($this->_params['db']);
 52:     }
 53: 
 54:     /**
 55:      * Retrieves the filesize from the VFS.
 56:      *
 57:      * @param string $path  The pathname to the file.
 58:      * @param string $name  The filename to retrieve.
 59:      *
 60:      * @return integer  The file size.
 61:      * @throws Horde_Vfs_Exception
 62:      */
 63:     public function size($path, $name)
 64:     {
 65:         $length_op = $this->_getFileSizeOp();
 66:         $sql = sprintf(
 67:             'SELECT %s(vfs_data) FROM %s WHERE vfs_path = ? AND vfs_name = ?',
 68:             $length_op,
 69:             $this->_params['table']
 70:         );
 71:         $values = array($this->_convertPath($path), $name);
 72:         try {
 73:             $size = $this->_db->selectValue($sql, $values);
 74:         } catch (Horde_Db_Exception $e) {
 75:             throw new Horde_Vfs_Exception($e);
 76:         }
 77: 
 78:         if ($size === false) {
 79:             throw new Horde_Vfs_Exception(sprintf('Unable to check file size of "%s/%s".', $path, $name));
 80:         }
 81: 
 82:         return $size;
 83:     }
 84: 
 85:     /**
 86:      * Returns the size of a file.
 87:      *
 88:      * @param string $path  The path of the file.
 89:      * @param string $name  The filename.
 90:      *
 91:      * @return integer  The size of the folder in bytes.
 92:      * @throws Horde_Vfs_Exception
 93:      */
 94:     public function getFolderSize($path = null, $name = null)
 95:     {
 96:         try {
 97:             $where = null;
 98:             $params = array();
 99:             if (strlen($path)) {
100:                 $where = 'WHERE vfs_path = ? OR vfs_path LIKE ?';
101:                 $path = $this->_convertPath($path);
102:                 $params = array($path, $path . '/%');
103:             }
104:             $sql = sprintf('SELECT SUM(%s(vfs_data)) FROM %s %s',
105:                            $this->_getFileSizeOp(),
106:                            $this->_params['table'],
107:                            $where);
108:             $size = $this->_db->selectValue($sql, $params);
109:         } catch (Horde_Db_Exception $e) {
110:             throw new Horde_Vfs_Exception($e);
111:         }
112: 
113:         return (int)$size;
114:     }
115: 
116:     /**
117:      * Retrieves a file from the VFS.
118:      *
119:      * @param string $path  The pathname to the file.
120:      * @param string $name  The filename to retrieve.
121:      *
122:      * @return string  The file data.
123:      * @throws Horde_Vfs_Exception
124:      */
125:     public function read($path, $name)
126:     {
127:         return $this->_readBlob($this->_params['table'], 'vfs_data', array(
128:             'vfs_path' => $this->_convertPath($path),
129:             'vfs_name' => $name
130:         ));
131:     }
132: 
133:     /**
134:      * Retrieves a part of a file from the VFS. Particularly useful
135:      * when reading large files which would exceed the PHP memory
136:      * limits if they were stored in a string.
137:      *
138:      * @param string  $path       The pathname to the file.
139:      * @param string  $name       The filename to retrieve.
140:      * @param integer $offset     The offset of the part. (The new offset will
141:      *                            be stored in here).
142:      * @param integer $length     The length of the part. If the length = -1,
143:      *                            the whole part after the offset is
144:      *                            retrieved. If more bytes are given as exists
145:      *                            after the given offset. Only the available
146:      *                            bytes are read.
147:      * @param integer $remaining  The bytes that are left, after the part that
148:      *                            is retrieved.
149:      *
150:      * @return string  The file data.
151:      * @throws Horde_Vfs_Exception
152:      */
153:     public function readByteRange($path, $name, &$offset, $length, &$remaining)
154:     {
155:         $data = $this->_readBlob($this->_params['table'], 'vfs_data', array(
156:             'vfs_path' => $this->_convertPath($path),
157:             'vfs_name' => $name
158:         ));
159: 
160:         // Calculate how many bytes MUST be read, so the remainging
161:         // bytes and the new offset can be calculated correctly.
162:         $size = strlen ($data);
163:         if ($length == -1 || (($length + $offset) > $size)) {
164:             $length = $size - $offset;
165:         }
166:         if ($remaining < 0) {
167:             $remaining = 0;
168:         }
169: 
170:         $data = substr($data, $offset, $length);
171:         $offset = $offset + $length;
172:         $remaining = $size - $offset;
173: 
174:         return $data;
175:     }
176: 
177:     /**
178:      * Stores a file in the VFS.
179:      *
180:      * @param string $path         The path to store the file in.
181:      * @param string $name         The filename to use.
182:      * @param string $tmpFile      The temporary file containing the data to
183:      *                             be stored.
184:      * @param boolean $autocreate  Automatically create directories?
185:      *
186:      * @throws Horde_Vfs_Exception
187:      */
188:     public function write($path, $name, $tmpFile, $autocreate = false)
189:     {
190:         /* Don't need to check quota here since it will be checked when
191:          * writeData() is called. */
192:         return $this->writeData($path,
193:                                 $name,
194:                                 file_get_contents($tmpFile),
195:                                 $autocreate);
196:     }
197: 
198:     /**
199:      * Store a file in the VFS from raw data.
200:      *
201:      * @param string $path         The path to store the file in.
202:      * @param string $name         The filename to use.
203:      * @param string $data         The file data.
204:      * @param boolean $autocreate  Automatically create directories?
205:      *
206:      * @throws Horde_Vfs_Exception
207:      */
208:     public function writeData($path, $name, $data, $autocreate = false)
209:     {
210:         $this->_checkQuotaWrite('string', $data);
211: 
212:         $path = $this->_convertPath($path);
213: 
214:         /* Check to see if the data already exists. */
215:         try {
216:             $sql = sprintf('SELECT vfs_id FROM %s WHERE vfs_path %s AND vfs_name = ?',
217:                            $this->_params['table'],
218:                            (!strlen($path) && $this->_db->dbsyntax == 'oci8') ? ' IS NULL' : ' = ' . $this->_db->quote($path));
219:             $values = array($name);
220:             $id = $this->_db->selectValue($sql, $values);
221:         } catch (Horde_Db_Exception $e) {
222:             throw new Horde_Vfs_Exception($e);
223:         }
224: 
225:         if ($id) {
226:             $this->_updateBlob($this->_params['table'], 'vfs_data', $data,
227:                                array('vfs_id' => $id),
228:                                array('vfs_modified' => time()));
229:             return;
230:         }
231: 
232:         /* Check to see if the folder already exists. */
233:         $dirs = explode('/', $path);
234:         $path_name = array_pop($dirs);
235:         $parent = implode('/', $dirs);
236:         if (!$this->isFolder($parent, $path_name)) {
237:             if (!$autocreate) {
238:                 throw new Horde_Vfs_Exception(sprintf('Folder "%s" does not exist', $path));
239:             }
240: 
241:             $this->autocreatePath($path);
242:         }
243: 
244:         return $this->_insertBlob($this->_params['table'], 'vfs_data', $data, array(
245:             'vfs_type' => self::FILE,
246:             'vfs_path' => $path,
247:             'vfs_name' => $name,
248:             'vfs_modified' => time(),
249:             'vfs_owner' => $this->_params['user']
250:         ));
251:     }
252: 
253:     /**
254:      * Delete a file from the VFS.
255:      *
256:      * @param string $path  The path to store the file in.
257:      * @param string $name  The filename to use.
258:      *
259:      * @throws Horde_Vfs_Exception
260:      */
261:     public function deleteFile($path, $name)
262:     {
263:         $this->_checkQuotaDelete($path, $name);
264: 
265:         $path = $this->_convertPath($path);
266: 
267:         try {
268:             $sql = sprintf('DELETE FROM %s WHERE vfs_type = ? AND vfs_path = ? AND vfs_name = ?',
269:                            $this->_params['table']);
270:             $values = array(self::FILE, $path, $name);
271:             $result = $this->_db->delete($sql, $values);
272:         } catch (Horde_Db_Exception $e) {
273:             throw new Horde_Vfs_Exception($e);
274:         }
275: 
276:         if ($result == 0) {
277:             throw new Horde_Vfs_Exception('Unable to delete VFS file.');
278:         }
279: 
280:         return $result;
281:     }
282: 
283:     /**
284:      * Rename a file or folder in the VFS.
285:      *
286:      * @param string $oldpath  The old path to the file.
287:      * @param string $oldname  The old filename.
288:      * @param string $newpath  The new path of the file.
289:      * @param string $newname  The new filename.
290:      *
291:      * @throws Horde_Vfs_Exception
292:      */
293:     public function rename($oldpath, $oldname, $newpath, $newname)
294:     {
295:         if (strpos($newpath, '/') === false) {
296:             $parent = '';
297:             $path = $newpath;
298:         } else {
299:             list($parent, $path) = explode('/', $newpath, 2);
300:         }
301: 
302:         if (!$this->isFolder($parent, $path)) {
303:             $this->autocreatePath($newpath);
304:         }
305: 
306:         $oldpath = $this->_convertPath($oldpath);
307:         $newpath = $this->_convertPath($newpath);
308: 
309:         $sql  = 'UPDATE ' . $this->_params['table']
310:             . ' SET vfs_path = ?, vfs_name = ?, vfs_modified = ? WHERE vfs_path = ? AND vfs_name = ?';
311:         $values = array($newpath, $newname, time(), $oldpath, $oldname);
312: 
313:         try {
314:             $result = $this->_db->update($sql, $values);
315:         } catch (Horde_Db_Exception $e) {
316:             throw new Horde_Vfs_Exception($e);
317:         }
318: 
319:         if ($result == 0) {
320:             throw new Horde_Vfs_Exception('Unable to rename VFS file.');
321:         }
322: 
323:         $this->_recursiveRename($oldpath, $oldname, $newpath, $newname);
324:     }
325: 
326:     /**
327:      * Creates a folder on the VFS.
328:      *
329:      * @param string $path  Holds the path of directory to create folder.
330:      * @param string $name  Holds the name of the new folder.
331:      *
332:      * @throws Horde_Vfs_Exception
333:      */
334:     public function createFolder($path, $name)
335:     {
336:         $sql = 'INSERT INTO ' . $this->_params['table']
337:             . ' (vfs_type, vfs_path, vfs_name, vfs_modified, vfs_owner) VALUES (?, ?, ?, ?, ?)';
338:         $values = array(self::FOLDER, $this->_convertPath($path), $name, time(), $this->_params['user']);
339: 
340:         try {
341:             $this->_db->insert($sql, $values);
342:         } catch (Horde_Db_Exception $e) {
343:             throw new Horde_Vfs_Exception($e);
344:         }
345:     }
346: 
347:     /**
348:      * Delete a folder from the VFS.
349:      *
350:      * @param string $path        The path of the folder.
351:      * @param string $name        The folder name to use.
352:      * @param boolean $recursive  Force a recursive delete?
353:      *
354:      * @throws Horde_Vfs_Exception
355:      */
356:     public function deleteFolder($path, $name, $recursive = false)
357:     {
358:         $path = $this->_convertPath($path);
359:         $folderPath = $this->_getNativePath($path, $name);
360: 
361:         /* Check if not recursive and fail if directory not empty */
362:         if (!$recursive) {
363:             $folderList = $this->listFolder($folderPath, null, true);
364:             if (!empty($folderList)) {
365:                 throw new Horde_Vfs_Exception(sprintf('Unable to delete %s, the directory is not empty', $path . '/' . $name));
366:             }
367:         }
368: 
369:         /* Remember the size of the folder. */
370:         if (!is_null($this->_vfsSize)) {
371:             $size = $this->getFolderSize($folderPath);
372:         }
373: 
374:         /* First delete everything below the folder, so if error we get no
375:          * orphans. */
376:         try {
377:             $sql = sprintf('DELETE FROM %s WHERE vfs_path %s',
378:                            $this->_params['table'],
379:                            (!strlen($folderPath) && $this->_db->dbsyntax == 'oci8') ? ' IS NULL' : ' LIKE ' . $this->_db->quote($this->_getNativePath($folderPath, '%')));
380:             $this->_db->delete($sql);
381:         } catch (Horde_Db_Exception $e) {
382:             $this->_vfsSize = null;
383:             throw new Horde_Vfs_Exception('Unable to delete VFS recursively: ' . $e->getMessage());
384:         }
385: 
386:         /* Now delete everything inside the folder. */
387:         try {
388:             $sql = sprintf('DELETE FROM %s WHERE vfs_path %s',
389:                            $this->_params['table'],
390:                            (!strlen($path) && $this->_db->dbsyntax == 'oci8') ? ' IS NULL' : ' = ' . $this->_db->quote($folderPath));
391:             $this->_db->delete($sql);
392:         } catch (Horde_Db_Exception $e) {
393:             $this->_vfsSize = null;
394:             throw new Horde_Vfs_Exception('Unable to delete VFS directory: ' . $e->getMessage());
395:         }
396: 
397:         /* All ok now delete the actual folder */
398:         try {
399:             $sql = sprintf('DELETE FROM %s WHERE vfs_path %s AND vfs_name = ?',
400:                            $this->_params['table'],
401:                            (!strlen($path) && $this->_db->dbsyntax == 'oci8') ? ' IS NULL' : ' = ' . $this->_db->quote($path));
402:             $values = array($name);
403:             $this->_db->delete($sql, $values);
404:         } catch (Horde_Db_Exception $e) {
405:             $this->_vfsSize = null;
406:             throw new Horde_Vfs_Exception('Unable to delete VFS directory: ' . $e->getMessage());
407:         }
408: 
409:         /* Update VFS size. */
410:         if (!is_null($this->_vfsSize)) {
411:             $this->_vfsSize -= $size;
412:         }
413:     }
414: 
415:     /**
416:      * Return a list of the contents of a folder.
417:      *
418:      * @param string $path       The directory path.
419:      * @param mixed $filter      String/hash of items to filter based on
420:      *                           filename.
421:      * @param boolean $dotfiles  Show dotfiles?
422:      * @param boolean $dironly   Show directories only?
423:      *
424:      * @return array  File list.
425:      * @throws Horde_Vfs_Exception
426:      */
427:     protected function _listFolder($path, $filter = null, $dotfiles = true,
428:                                    $dironly = false)
429:     {
430:         $path = $this->_convertPath($path);
431: 
432:         try {
433:             // Fix for Oracle not differentiating between '' and NULL.
434:             if (!strlen($path) &&
435:                 ($this->_db->adapterName() == 'Oracle' ||
436:                  $this->_db->adapterName() == 'PDO_Oracle')) {
437:                 $where = 'vfs_path IS NULL';
438:             } else {
439:                 $where = 'vfs_path = ' . $this->_db->quote($path);
440:             }
441: 
442:             $length_op = $this->_getFileSizeOp();
443:             $sql = sprintf('SELECT vfs_name, vfs_type, %s(vfs_data) length, vfs_modified, vfs_owner FROM %s WHERE %s',
444:                            $length_op,
445:                            $this->_params['table'],
446:                            $where);
447:             $fileList = $this->_db->select($sql);
448:         } catch (Horde_Db_Exception $e) {
449:             throw new Horde_Vfs_Exception($e);
450:         }
451: 
452:         $files = array();
453:         foreach ($fileList as $line) {
454:             // Filter out dotfiles if they aren't wanted.
455:             if (!$dotfiles && substr($line['vfs_name'], 0, 1) == '.') {
456:                 continue;
457:             }
458: 
459:             $file['name'] = $line['vfs_name'];
460: 
461:             if ($line['vfs_type'] == self::FILE) {
462:                 $name = explode('.', $line['vfs_name']);
463: 
464:                 if (count($name) == 1) {
465:                     $file['type'] = '**none';
466:                 } else {
467:                     $file['type'] = Horde_String::lower($name[count($name) - 1]);
468:                 }
469: 
470:                 $file['size'] = $line['length'];
471:             } elseif ($line['vfs_type'] == self::FOLDER) {
472:                 $file['type'] = '**dir';
473:                 $file['size'] = -1;
474:             }
475: 
476:             $file['date'] = $line['vfs_modified'];
477:             $file['owner'] = $line['vfs_owner'];
478:             $file['perms'] = '';
479:             $file['group'] = '';
480: 
481:             // filtering
482:             if ($this->_filterMatch($filter, $file['name'])) {
483:                 unset($file);
484:                 continue;
485:             }
486:             if ($dironly && $file['type'] !== '**dir') {
487:                 unset($file);
488:                 continue;
489:             }
490: 
491:             $files[$file['name']] = $file;
492:             unset($file);
493:         }
494: 
495:         return $files;
496:     }
497: 
498:     /**
499:      * Returns a sorted list of folders in specified directory.
500:      *
501:      * @param string $path         The path of the directory to get the
502:      *                             directory list for.
503:      * @param mixed $filter        String/hash of items to filter based on
504:      *                             folderlist.
505:      * @param boolean $dotfolders  Include dotfolders?
506:      *
507:      * @return array  Folder list.
508:      * @throws Horde_Vfs_Exception
509:      */
510:     public function listFolders($path = '', $filter = array(),
511:                                 $dotfolders = true)
512:     {
513:         $path = $this->_convertPath($path);
514: 
515:         $sql  = 'SELECT vfs_name, vfs_path FROM ' . $this->_params['table']
516:             . ' WHERE vfs_path = ? AND vfs_type = ?';
517:         $values = array($path, self::FOLDER);
518: 
519:         try {
520:             $folderList = $this->_db->select($sql, $values);
521:         } catch (Horde_Db_Exception $e) {
522:             throw new Horde_Vfs_Exception($e);
523:         }
524: 
525:         $folders = array();
526:         foreach ($folderList as $line) {
527:             // Filter out dotfolder if they aren't wanted.
528:             if (!$dotfolders && substr($line['vfs_name'], 0, 1) == '.') {
529:                 continue;
530:             }
531: 
532:             $folder['val'] = $this->_getNativePath($line['vfs_path'], $line['vfs_name']);
533:             $folder['abbrev'] = '';
534:             $folder['label'] = '';
535: 
536:             $count = substr_count($folder['val'], '/');
537: 
538:             $x = 0;
539:             while ($x < $count) {
540:                 $folder['abbrev'] .= '    ';
541:                 $folder['label'] .= '    ';
542:                 $x++;
543:             }
544: 
545:             $folder['abbrev'] .= $line['vfs_name'];
546:             $folder['label'] .= $line['vfs_name'];
547: 
548:             $strlen = Horde_String::length($folder['label']);
549:             if ($strlen > 26) {
550:                 $folder['abbrev'] = substr($folder['label'], 0, ($count * 4));
551:                 $length = (29 - ($count * 4)) / 2;
552:                 $folder['abbrev'] .= substr($folder['label'], ($count * 4), $length);
553:                 $folder['abbrev'] .= '...';
554:                 $folder['abbrev'] .= substr($folder['label'], -1 * $length, $length);
555:             }
556: 
557:             $found = false;
558:             foreach ($filter as $fltr) {
559:                 if ($folder['val'] == $fltr) {
560:                     $found = true;
561:                 }
562:             }
563: 
564:             if (!$found) {
565:                 $folders[$folder['val']] = $folder;
566:             }
567:         }
568: 
569:         ksort($folders);
570:         return $folders;
571:     }
572: 
573:     /**
574:      * Garbage collect files in the VFS storage system.
575:      *
576:      * @param string $path   The VFS path to clean.
577:      * @param integer $secs  The minimum amount of time (in seconds) required
578:      *                       before a file is removed.
579:      *
580:      * @throws Horde_Vfs_Exception
581:      */
582:     public function gc($path, $secs = 345600)
583:     {
584:         $sql = 'DELETE FROM ' . $this->_params['table']
585:             . ' WHERE vfs_type = ? AND vfs_modified < ? AND (vfs_path = ? OR vfs_path LIKE ?)';
586:         $values = array(
587:             self::FILE,
588:             time() - $secs,
589:             $this->_convertPath($path),
590:             $this->_convertPath($path) . '/%'
591:         );
592: 
593:         try {
594:             $this->_db->delete($sql, $values);
595:         } catch (Horde_Db_Exception $e) {
596:             throw new Horde_Vfs_Exception($e);
597:         }
598:     }
599: 
600:     /**
601:      * Renames all child paths.
602:      *
603:      * @param string $path  The path of the folder to rename.
604:      * @param string $name  The foldername to use.
605:      *
606:      * @throws Horde_Vfs_Exception
607:      */
608:     protected function _recursiveRename($oldpath, $oldname, $newpath, $newname)
609:     {
610:         $oldpath = $this->_convertPath($oldpath);
611:         $newpath = $this->_convertPath($newpath);
612: 
613:         $sql  = 'SELECT vfs_name FROM ' . $this->_params['table']
614:             . ' WHERE vfs_type = ? AND vfs_path = ?';
615:         $values = array(self::FOLDER, $this->_getNativePath($oldpath, $oldname));
616: 
617:         try {
618:             $folderList = $this->_db->selectValues($sql, $values);
619:         } catch (Horde_Db_Exception $e) {
620:             throw new Horde_Vfs_Exception($e);
621:         }
622: 
623:         foreach ($folderList as $folder) {
624:             $this->_recursiveRename($this->_getNativePath($oldpath, $oldname), $folder, $this->_getNativePath($newpath, $newname), $folder);
625:         }
626: 
627:         $sql = 'UPDATE ' . $this->_params['table']
628:             . ' SET vfs_path = ? WHERE vfs_path = ?';
629:         $values = array($this->_getNativePath($newpath, $newname), $this->_getNativePath($oldpath, $oldname));
630: 
631:         try {
632:             $this->_db->update($sql, $values);
633:         } catch (Horde_Db_Exception $e) {
634:             throw new Horde_Vfs_Exception($e);
635:         }
636:     }
637: 
638:     /**
639:      * Return a full filename on the native filesystem, from a VFS
640:      * path and name.
641:      *
642:      * @param string $path  The VFS file path.
643:      * @param string $name  The VFS filename.
644:      *
645:      * @return string  The full native filename.
646:      */
647:     protected function _getNativePath($path, $name)
648:     {
649:         if (!strlen($path)) {
650:             return $name;
651:         }
652: 
653:         if (isset($this->_params['home']) &&
654:             preg_match('|^~/?(.*)$|', $path, $matches)) {
655:             $path = $this->_params['home'] . '/' . $matches[1];
656:         }
657: 
658:         return $path . '/' . $name;
659:     }
660: 
661:     /**
662:      * Read file data from the SQL VFS backend.
663:      *
664:      * @param string $table    The VFS table name.
665:      * @param string $field    TODO
666:      * @param array $criteria  TODO
667:      *
668:      * @return mixed  TODO
669:      * @throws Horde_Vfs_Exception
670:      */
671:     protected function _readBlob($table, $field, $criteria)
672:     {
673:         if (!count($criteria)) {
674:             throw new Horde_Vfs_Exception('You must specify the fetch criteria');
675:         }
676: 
677:         $where = '';
678:         foreach ($criteria as $key => $value) {
679:             if (!empty($where)) {
680:                 $where .= ' AND ';
681:             }
682:             $where .= $key . ' = ' . $this->_db->quote($value);
683:         }
684: 
685:         $sql = sprintf('SELECT %s FROM %s WHERE %s',
686:                        $field, $table, $where);
687: 
688:         try {
689:             $result = $this->_db->selectValue($sql);
690:             $columns = $this->_db->columns($table);
691:         } catch (Horde_Db_Exception $e) {
692:             throw new Horde_Vfs_Exception($e);
693:         }
694: 
695:         if ($result === false) {
696:             throw new Horde_Vfs_Exception('Unable to load SQL data.');
697:         }
698: 
699:         return $columns[$field]->binaryToString($result);
700:     }
701: 
702:     /**
703:      * TODO
704:      *
705:      * @param string $table       TODO
706:      * @param string $field       TODO
707:      * @param string $data        TODO
708:      * @param string $attributes  TODO
709:      *
710:      * @return mixed  TODO
711:      * @throws Horde_Vfs_Exception
712:      */
713:     protected function _insertBlob($table, $field, $data, $attributes)
714:     {
715:         $fields = $values = array();
716:         foreach ($attributes as $key => $value) {
717:             $fields[] = $key;
718:             $values[] = $value;
719:         }
720:         $values[] = new Horde_Db_Value_Binary($data);
721: 
722:         $query = sprintf('INSERT INTO %s (%s, %s) VALUES (%s)',
723:                          $table,
724:                          implode(', ', $fields),
725:                          $field,
726:                          '?' . str_repeat(', ?', count($fields)));
727: 
728:         /* Execute the query. */
729:         try {
730:             $this->_db->insert($query, $values);
731:         } catch (Horde_Db_Exception $e) {
732:             throw new Horde_Vfs_Exception($e);
733:         }
734:     }
735: 
736:     /**
737:      * TODO
738:      *
739:      * @param string $table      TODO
740:      * @param string $field      TODO
741:      * @param string $data       TODO
742:      * @param string $where      TODO
743:      * @param array $alsoupdate  TODO
744:      *
745:      * @return mixed  TODO
746:      * @throws Horde_Vfs_Exception
747:      */
748:     protected function _updateBlob($table, $field, $data, $where, $alsoupdate)
749:     {
750:         $updatestring = '';
751:         $values = array();
752:         foreach ($alsoupdate as $key => $value) {
753:             $updatestring .= $key . ' = ?, ';
754:             $values[] = $value;
755:         }
756:         $updatestring .= $field . ' = ?';
757:         $values[] = new Horde_Db_Value_Binary($data);
758: 
759:         $wherestring = '';
760:         foreach ($where as $key => $value) {
761:             if (!empty($wherestring)) {
762:                 $wherestring .= ' AND ';
763:             }
764:             $wherestring .= $key . ' = ?';
765:             $values[] = $value;
766:         }
767: 
768:         $query = sprintf('UPDATE %s SET %s WHERE %s',
769:                          $table,
770:                          $updatestring,
771:                          $wherestring);
772: 
773:         /* Execute the query. */
774:         try {
775:             $this->_db->update($query, $values);
776:         } catch (Horde_Db_Exception $e) {
777:             throw new Horde_Vfs_Exception($e);
778:         }
779:     }
780: 
781:     /**
782:      * Converts the path name from regular filesystem form to the internal
783:      * format needed to access the file in the database.
784:      *
785:      * Namely, we will treat '/' as a base directory as this is pretty much
786:      * the standard way to access base directories over most filesystems.
787:      *
788:      * @param string $path  A VFS path.
789:      *
790:      * @return string  The path with any surrouding slashes stripped off.
791:      */
792:     protected function _convertPath($path)
793:     {
794:         return trim($path, '/');
795:     }
796: 
797:     /**
798:      * TODO
799:      *
800:      * @return string  TODO
801:      */
802:     protected function _getFileSizeOp()
803:     {
804:         switch ($this->_db->adapterName()) {
805:         case 'Oracle':
806:         case 'PDO_Oracle':
807:             return 'LENGTHB';
808: 
809:         case 'PostgreSQL':
810:         case 'PDO_PostgreSQL':
811:             return 'OCTET_LENGTH';
812: 
813:         default:
814:             return 'LENGTH';
815:         }
816:     }
817: 
818:     /**
819:      * Horde_Vfs_Sql override of isFolder() to check for root folder.
820:      *
821:      * @param string $path  Path to possible folder
822:      * @param string $name  Name of possible folder
823:      *
824:      * @return boolean  True if $path/$name is a folder
825:      */
826:     public function isFolder($path, $name)
827:     {
828:         return (($path == '') && ($name == ''))
829:             // The root of VFS is always a folder.
830:             ? true
831:             : parent::isFolder($path, $name);
832:     }
833: 
834: }
835: 
API documentation generated by ApiGen