final move of files
[web.mtrack] / Zend / Search / Lucene / Storage / Directory / Filesystem.php
1 <?php
2 /**
3  * Zend Framework
4  *
5  * LICENSE
6  *
7  * This source file is subject to the new BSD license that is bundled
8  * with this package in the file LICENSE.txt.
9  * It is also available through the world-wide-web at this URL:
10  * http://framework.zend.com/license/new-bsd
11  * If you did not receive a copy of the license and are unable to
12  * obtain it through the world-wide-web, please send an email
13  * to license@zend.com so we can send you a copy immediately.
14  *
15  * @category   Zend
16  * @package    Zend_Search_Lucene
17  * @subpackage Storage
18  * @copyright  Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
19  * @license    http://framework.zend.com/license/new-bsd     New BSD License
20  * @version    $Id: Filesystem.php 16541 2009-07-07 06:59:03Z bkarwin $
21  */
22
23
24 /** Zend_Search_Lucene_Storage_Directory */
25 require_once 'Zend/Search/Lucene/Storage/Directory.php';
26
27 /** Zend_Search_Lucene_Storage_File_Filesystem */
28 require_once 'Zend/Search/Lucene/Storage/File/Filesystem.php';
29
30
31 /**
32  * FileSystem implementation of Directory abstraction.
33  *
34  * @category   Zend
35  * @package    Zend_Search_Lucene
36  * @subpackage Storage
37  * @copyright  Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
38  * @license    http://framework.zend.com/license/new-bsd     New BSD License
39  */
40 class Zend_Search_Lucene_Storage_Directory_Filesystem extends Zend_Search_Lucene_Storage_Directory
41 {
42     /**
43      * Filesystem path to the directory
44      *
45      * @var string
46      */
47     protected $_dirPath = null;
48
49     /**
50      * Cache for Zend_Search_Lucene_Storage_File_Filesystem objects
51      * Array: filename => Zend_Search_Lucene_Storage_File object
52      *
53      * @var array
54      * @throws Zend_Search_Lucene_Exception
55      */
56     protected $_fileHandlers;
57
58     /**
59      * Default file permissions
60      *
61      * @var integer
62      */
63     protected static $_defaultFilePermissions = 0666;
64
65
66     /**
67      * Get default file permissions
68      *
69      * @return integer
70      */
71     public static function getDefaultFilePermissions()
72     {
73         return self::$_defaultFilePermissions;
74     }
75
76     /**
77      * Set default file permissions
78      *
79      * @param integer $mode
80      */
81     public static function setDefaultFilePermissions($mode)
82     {
83         self::$_defaultFilePermissions = $mode;
84     }
85
86
87     /**
88      * Utility function to recursive directory creation
89      *
90      * @param string $dir
91      * @param integer $mode
92      * @param boolean $recursive
93      * @return boolean
94      */
95
96     public static function mkdirs($dir, $mode = 0777, $recursive = true)
97     {
98         if (($dir === null) || $dir === '') {
99             return false;
100         }
101         if (is_dir($dir) || $dir === '/') {
102             return true;
103         }
104         if (self::mkdirs(dirname($dir), $mode, $recursive)) {
105             return mkdir($dir, $mode);
106         }
107         return false;
108     }
109
110
111     /**
112      * Object constructor
113      * Checks if $path is a directory or tries to create it.
114      *
115      * @param string $path
116      * @throws Zend_Search_Lucene_Exception
117      */
118     public function __construct($path)
119     {
120         if (!is_dir($path)) {
121             if (file_exists($path)) {
122                 require_once 'Zend/Search/Lucene/Exception.php';
123                 throw new Zend_Search_Lucene_Exception('Path exists, but it\'s not a directory');
124             } else {
125                 if (!self::mkdirs($path)) {
126                     require_once 'Zend/Search/Lucene/Exception.php';
127                     throw new Zend_Search_Lucene_Exception("Can't create directory '$path'.");
128                 }
129             }
130         }
131         $this->_dirPath = $path;
132         $this->_fileHandlers = array();
133     }
134
135
136     /**
137      * Closes the store.
138      *
139      * @return void
140      */
141     public function close()
142     {
143         foreach ($this->_fileHandlers as $fileObject) {
144             $fileObject->close();
145         }
146
147         $this->_fileHandlers = array();
148     }
149
150
151     /**
152      * Returns an array of strings, one for each file in the directory.
153      *
154      * @return array
155      */
156     public function fileList()
157     {
158         $result = array();
159
160         $dirContent = opendir( $this->_dirPath );
161         while (($file = readdir($dirContent)) !== false) {
162             if (($file == '..')||($file == '.'))   continue;
163
164             if( !is_dir($this->_dirPath . '/' . $file) ) {
165                 $result[] = $file;
166             }
167         }
168         closedir($dirContent);
169
170         return $result;
171     }
172
173     /**
174      * Creates a new, empty file in the directory with the given $filename.
175      *
176      * @param string $filename
177      * @return Zend_Search_Lucene_Storage_File
178      * @throws Zend_Search_Lucene_Exception
179      */
180     public function createFile($filename)
181     {
182         if (isset($this->_fileHandlers[$filename])) {
183             $this->_fileHandlers[$filename]->close();
184         }
185         unset($this->_fileHandlers[$filename]);
186         $this->_fileHandlers[$filename] = new Zend_Search_Lucene_Storage_File_Filesystem($this->_dirPath . '/' . $filename, 'w+b');
187
188         // Set file permissions, but don't care about any possible failures, since file may be already
189         // created by anther user which has to care about right permissions
190         @chmod($this->_dirPath . '/' . $filename, self::$_defaultFilePermissions);
191
192         return $this->_fileHandlers[$filename];
193     }
194
195
196     /**
197      * Removes an existing $filename in the directory.
198      *
199      * @param string $filename
200      * @return void
201      * @throws Zend_Search_Lucene_Exception
202      */
203     public function deleteFile($filename)
204     {
205         if (isset($this->_fileHandlers[$filename])) {
206             $this->_fileHandlers[$filename]->close();
207         }
208         unset($this->_fileHandlers[$filename]);
209
210         global $php_errormsg;
211         $trackErrors = ini_get('track_errors'); ini_set('track_errors', '1');
212         if (!@unlink($this->_dirPath . '/' . $filename)) {
213             ini_set('track_errors', $trackErrors);
214             require_once 'Zend/Search/Lucene/Exception.php';
215             throw new Zend_Search_Lucene_Exception('Can\'t delete file: ' . $php_errormsg);
216         }
217         ini_set('track_errors', $trackErrors);
218     }
219
220     /**
221      * Purge file if it's cached by directory object
222      *
223      * Method is used to prevent 'too many open files' error
224      *
225      * @param string $filename
226      * @return void
227      */
228     public function purgeFile($filename)
229     {
230         if (isset($this->_fileHandlers[$filename])) {
231             $this->_fileHandlers[$filename]->close();
232         }
233         unset($this->_fileHandlers[$filename]);
234     }
235
236
237     /**
238      * Returns true if a file with the given $filename exists.
239      *
240      * @param string $filename
241      * @return boolean
242      */
243     public function fileExists($filename)
244     {
245         return isset($this->_fileHandlers[$filename]) ||
246                file_exists($this->_dirPath . '/' . $filename);
247     }
248
249
250     /**
251      * Returns the length of a $filename in the directory.
252      *
253      * @param string $filename
254      * @return integer
255      */
256     public function fileLength($filename)
257     {
258         if (isset( $this->_fileHandlers[$filename] )) {
259             return $this->_fileHandlers[$filename]->size();
260         }
261         return filesize($this->_dirPath .'/'. $filename);
262     }
263
264
265     /**
266      * Returns the UNIX timestamp $filename was last modified.
267      *
268      * @param string $filename
269      * @return integer
270      */
271     public function fileModified($filename)
272     {
273         return filemtime($this->_dirPath .'/'. $filename);
274     }
275
276
277     /**
278      * Renames an existing file in the directory.
279      *
280      * @param string $from
281      * @param string $to
282      * @return void
283      * @throws Zend_Search_Lucene_Exception
284      */
285     public function renameFile($from, $to)
286     {
287         global $php_errormsg;
288
289         if (isset($this->_fileHandlers[$from])) {
290             $this->_fileHandlers[$from]->close();
291         }
292         unset($this->_fileHandlers[$from]);
293
294         if (isset($this->_fileHandlers[$to])) {
295             $this->_fileHandlers[$to]->close();
296         }
297         unset($this->_fileHandlers[$to]);
298
299         if (file_exists($this->_dirPath . '/' . $to)) {
300             if (!unlink($this->_dirPath . '/' . $to)) {
301                 require_once 'Zend/Search/Lucene/Exception.php';
302                 throw new Zend_Search_Lucene_Exception('Delete operation failed');
303             }
304         }
305
306         $trackErrors = ini_get('track_errors');
307         ini_set('track_errors', '1');
308
309         $success = @rename($this->_dirPath . '/' . $from, $this->_dirPath . '/' . $to);
310         if (!$success) {
311             ini_set('track_errors', $trackErrors);
312             require_once 'Zend/Search/Lucene/Exception.php';
313             throw new Zend_Search_Lucene_Exception($php_errormsg);
314         }
315
316         ini_set('track_errors', $trackErrors);
317
318         return $success;
319     }
320
321
322     /**
323      * Sets the modified time of $filename to now.
324      *
325      * @param string $filename
326      * @return void
327      */
328     public function touchFile($filename)
329     {
330         return touch($this->_dirPath .'/'. $filename);
331     }
332
333
334     /**
335      * Returns a Zend_Search_Lucene_Storage_File object for a given $filename in the directory.
336      *
337      * If $shareHandler option is true, then file handler can be shared between File Object
338      * requests. It speed-ups performance, but makes problems with file position.
339      * Shared handler are good for short atomic requests.
340      * Non-shared handlers are useful for stream file reading (especial for compound files).
341      *
342      * @param string $filename
343      * @param boolean $shareHandler
344      * @return Zend_Search_Lucene_Storage_File
345      */
346     public function getFileObject($filename, $shareHandler = true)
347     {
348         $fullFilename = $this->_dirPath . '/' . $filename;
349
350         if (!$shareHandler) {
351             return new Zend_Search_Lucene_Storage_File_Filesystem($fullFilename);
352         }
353
354         if (isset( $this->_fileHandlers[$filename] )) {
355             $this->_fileHandlers[$filename]->seek(0);
356             return $this->_fileHandlers[$filename];
357         }
358
359         $this->_fileHandlers[$filename] = new Zend_Search_Lucene_Storage_File_Filesystem($fullFilename);
360         return $this->_fileHandlers[$filename];
361     }
362 }
363