ILIAS  release_5-3 Revision v5.3.23-19-g915713cf615
Local.php
Go to the documentation of this file.
1 <?php
2 
4 
7 use finfo as Finfo;
14 use LogicException;
17 use SplFileInfo;
18 
19 class Local extends AbstractAdapter
20 {
24  const SKIP_LINKS = 0001;
25 
29  const DISALLOW_LINKS = 0002;
30 
34  protected static $permissions = [
35  'file' => [
36  'public' => 0644,
37  'private' => 0600,
38  ],
39  'dir' => [
40  'public' => 0755,
41  'private' => 0700,
42  ]
43  ];
44 
48  protected $pathSeparator = DIRECTORY_SEPARATOR;
49 
53  protected $permissionMap;
54 
58  protected $writeFlags;
62  private $linkHandling;
63 
74  public function __construct($root, $writeFlags = LOCK_EX, $linkHandling = self::DISALLOW_LINKS, array $permissions = [])
75  {
76  $root = is_link($root) ? realpath($root) : $root;
77  $this->permissionMap = array_replace_recursive(static::$permissions, $permissions);
78  $this->ensureDirectory($root);
79 
80  if ( ! is_dir($root) || ! is_readable($root)) {
81  throw new LogicException('The root path ' . $root . ' is not readable.');
82  }
83 
84  $this->setPathPrefix($root);
85  $this->writeFlags = $writeFlags;
86  $this->linkHandling = $linkHandling;
87  }
88 
98  protected function ensureDirectory($root)
99  {
100  if ( ! is_dir($root)) {
101  $umask = umask(0);
102  @mkdir($root, $this->permissionMap['dir']['public'], true);
103  umask($umask);
104 
105  if ( ! is_dir($root)) {
106  throw new Exception(sprintf('Impossible to create the root directory "%s".', $root));
107  }
108  }
109  }
110 
114  public function has($path)
115  {
116  $location = $this->applyPathPrefix($path);
117 
118  return file_exists($location);
119  }
120 
124  public function write($path, $contents, Config $config)
125  {
126  $location = $this->applyPathPrefix($path);
127  $this->ensureDirectory(dirname($location));
128 
129  if (($size = file_put_contents($location, $contents, $this->writeFlags)) === false) {
130  return false;
131  }
132 
133  $type = 'file';
134  $result = compact('contents', 'type', 'size', 'path');
135 
136  if ($visibility = $config->get('visibility')) {
137  $result['visibility'] = $visibility;
138  $this->setVisibility($path, $visibility);
139  }
140 
141  return $result;
142  }
143 
147  public function writeStream($path, $resource, Config $config)
148  {
149  $location = $this->applyPathPrefix($path);
150  $this->ensureDirectory(dirname($location));
151  $stream = fopen($location, 'w+b');
152 
153  if ( ! $stream) {
154  return false;
155  }
156 
157  stream_copy_to_stream($resource, $stream);
158 
159  if ( ! fclose($stream)) {
160  return false;
161  }
162 
163  if ($visibility = $config->get('visibility')) {
164  $this->setVisibility($path, $visibility);
165  }
166 
167  $type = 'file';
168 
169  return compact('type', 'path', 'visibility');
170  }
171 
175  public function readStream($path)
176  {
177  $location = $this->applyPathPrefix($path);
178  $stream = fopen($location, 'rb');
179 
180  return ['type' => 'file', 'path' => $path, 'stream' => $stream];
181  }
182 
186  public function updateStream($path, $resource, Config $config)
187  {
188  return $this->writeStream($path, $resource, $config);
189  }
190 
194  public function update($path, $contents, Config $config)
195  {
196  $location = $this->applyPathPrefix($path);
197  $mimetype = Util::guessMimeType($path, $contents);
198  $size = file_put_contents($location, $contents, $this->writeFlags);
199 
200  if ($size === false) {
201  return false;
202  }
203 
204  $type = 'file';
205 
206  return compact('type', 'path', 'size', 'contents', 'mimetype');
207  }
208 
212  public function read($path)
213  {
214  $location = $this->applyPathPrefix($path);
215  $contents = file_get_contents($location);
216 
217  if ($contents === false) {
218  return false;
219  }
220 
221  return ['type' => 'file', 'path' => $path, 'contents' => $contents];
222  }
223 
227  public function rename($path, $newpath)
228  {
229  $location = $this->applyPathPrefix($path);
230  $destination = $this->applyPathPrefix($newpath);
231  $parentDirectory = $this->applyPathPrefix(Util::dirname($newpath));
232  $this->ensureDirectory($parentDirectory);
233 
234  return rename($location, $destination);
235  }
236 
240  public function copy($path, $newpath)
241  {
242  $location = $this->applyPathPrefix($path);
243  $destination = $this->applyPathPrefix($newpath);
244  $this->ensureDirectory(dirname($destination));
245 
246  return copy($location, $destination);
247  }
248 
252  public function delete($path)
253  {
254  $location = $this->applyPathPrefix($path);
255 
256  return unlink($location);
257  }
258 
262  public function listContents($directory = '', $recursive = false)
263  {
264  $result = [];
265  $location = $this->applyPathPrefix($directory);
266 
267  if ( ! is_dir($location)) {
268  return [];
269  }
270 
271  $iterator = $recursive ? $this->getRecursiveDirectoryIterator($location) : $this->getDirectoryIterator($location);
272 
273  foreach ($iterator as $file) {
274  $path = $this->getFilePath($file);
275 
276  if (preg_match('#(^|/|\\\\)\.{1,2}$#', $path)) {
277  continue;
278  }
279 
280  $result[] = $this->normalizeFileInfo($file);
281  }
282 
283  return array_filter($result);
284  }
285 
289  public function getMetadata($path)
290  {
291  $location = $this->applyPathPrefix($path);
292  $info = new SplFileInfo($location);
293 
294  return $this->normalizeFileInfo($info);
295  }
296 
300  public function getSize($path)
301  {
302  return $this->getMetadata($path);
303  }
304 
308  public function getMimetype($path)
309  {
310  $location = $this->applyPathPrefix($path);
311  $finfo = new Finfo(FILEINFO_MIME_TYPE);
312  $mimetype = $finfo->file($location);
313 
314  if (in_array($mimetype, ['application/octet-stream', 'inode/x-empty'])) {
316  }
317 
318  return ['path' => $path, 'type' => 'file', 'mimetype' => $mimetype];
319  }
320 
324  public function getTimestamp($path)
325  {
326  return $this->getMetadata($path);
327  }
328 
332  public function getVisibility($path)
333  {
334  $location = $this->applyPathPrefix($path);
335  clearstatcache(false, $location);
336  $permissions = octdec(substr(sprintf('%o', fileperms($location)), -4));
338 
339  return compact('path', 'visibility');
340  }
341 
345  public function setVisibility($path, $visibility)
346  {
347  $location = $this->applyPathPrefix($path);
348  $type = is_dir($location) ? 'dir' : 'file';
349  $success = chmod($location, $this->permissionMap[$type][$visibility]);
350 
351  if ($success === false) {
352  return false;
353  }
354 
355  return compact('path', 'visibility');
356  }
357 
361  public function createDir($dirname, Config $config)
362  {
363  $location = $this->applyPathPrefix($dirname);
364  $umask = umask(0);
365  $visibility = $config->get('visibility', 'public');
366 
367  if ( ! is_dir($location) && ! mkdir($location, $this->permissionMap['dir'][$visibility], true)) {
368  $return = false;
369  } else {
370  $return = ['path' => $dirname, 'type' => 'dir'];
371  }
372 
373  umask($umask);
374 
375  return $return;
376  }
377 
381  public function deleteDir($dirname)
382  {
383  $location = $this->applyPathPrefix($dirname);
384 
385  if ( ! is_dir($location)) {
386  return false;
387  }
388 
389  $contents = $this->getRecursiveDirectoryIterator($location, RecursiveIteratorIterator::CHILD_FIRST);
390 
392  foreach ($contents as $file) {
393  $this->guardAgainstUnreadableFileInfo($file);
394  $this->deleteFileInfoObject($file);
395  }
396 
397  return rmdir($location);
398  }
399 
404  {
405  switch ($file->getType()) {
406  case 'dir':
407  rmdir($file->getRealPath());
408  break;
409  case 'link':
410  unlink($file->getPathname());
411  break;
412  default:
413  unlink($file->getRealPath());
414  }
415  }
416 
426  protected function normalizeFileInfo(SplFileInfo $file)
427  {
428  if ( ! $file->isLink()) {
429  return $this->mapFileInfo($file);
430  }
431 
432  if ($this->linkHandling & self::DISALLOW_LINKS) {
433  throw NotSupportedException::forLink($file);
434  }
435  }
436 
444  protected function getFilePath(SplFileInfo $file)
445  {
446  $location = $file->getPathname();
447  $path = $this->removePathPrefix($location);
448 
449  return trim(str_replace('\\', '/', $path), '/');
450  }
451 
458  protected function getRecursiveDirectoryIterator($path, $mode = RecursiveIteratorIterator::SELF_FIRST)
459  {
460  return new RecursiveIteratorIterator(
461  new RecursiveDirectoryIterator($path, FilesystemIterator::SKIP_DOTS),
462  $mode
463  );
464  }
465 
471  protected function getDirectoryIterator($path)
472  {
473  $iterator = new DirectoryIterator($path);
474 
475  return $iterator;
476  }
477 
483  protected function mapFileInfo(SplFileInfo $file)
484  {
485  $normalized = [
486  'type' => $file->getType(),
487  'path' => $this->getFilePath($file),
488  ];
489 
490  $normalized['timestamp'] = $file->getMTime();
491 
492  if ($normalized['type'] === 'file') {
493  $normalized['size'] = $file->getSize();
494  }
495 
496  return $normalized;
497  }
498 
505  {
506  if ( ! $file->isReadable()) {
508  }
509  }
510 }
getMetadata($path)
Get all the meta data of a file or directory.array|false
Definition: Local.php:289
const VISIBILITY_PUBLIC
VISIBILITY_PUBLIC public visibility
getTimestamp($path)
Get the timestamp of a file.array|false
Definition: Local.php:324
$size
Definition: RandomTest.php:84
static detectByFilename($filename)
Definition: MimeType.php:61
static dirname($path)
Get a normalized dirname from a path.
Definition: Util.php:45
writeStream($path, $resource, Config $config)
Write a new file using a stream.Config objectarray|false false on failure file meta data on success ...
Definition: Local.php:147
mapFileInfo(SplFileInfo $file)
Definition: Local.php:483
$result
deleteFileInfoObject(SplFileInfo $file)
Definition: Local.php:403
$type
static guessMimeType($path, $content)
Guess MIME Type based on the path of the file and it&#39;s content.
Definition: Util.php:177
$location
Definition: buildRTE.php:44
normalizeFileInfo(SplFileInfo $file)
Normalize the file info.
Definition: Local.php:426
setVisibility($path, $visibility)
Set the visibility for a file.array|false file meta data
Definition: Local.php:345
$destination
updateStream($path, $resource, Config $config)
Update a file using a stream.Config objectarray|false false on failure file meta data on success ...
Definition: Local.php:186
has($path)
Check whether a file exists.array|bool|null
Definition: Local.php:114
getRecursiveDirectoryIterator($path, $mode=RecursiveIteratorIterator::SELF_FIRST)
Definition: Local.php:458
setPathPrefix($prefix)
Set the path prefix.
listContents($directory='', $recursive=false)
List contents of a directory.array
Definition: Local.php:262
$stream
PHP stream implementation.
__construct($root, $writeFlags=LOCK_EX, $linkHandling=self::DISALLOW_LINKS, array $permissions=[])
Constructor.
Definition: Local.php:74
getMimetype($path)
Get the mimetype of a file.array|false
Definition: Local.php:308
const VISIBILITY_PRIVATE
VISIBILITY_PRIVATE private visibility
deleteDir($dirname)
Delete a directory.
read($path)
Read a file.array|false
Definition: Local.php:212
$success
Definition: Utf8Test.php:86
createDir($dirname, Config $config)
Create a directory.directory name array|false
Definition: Local.php:361
guardAgainstUnreadableFileInfo(SplFileInfo $file)
Definition: Local.php:504
rename($path, $newpath)
Rename a file.bool
Definition: Local.php:227
getSize($path)
Get the size of a file.array|false
Definition: Local.php:300
Create styles array
The data for the language used.
ensureDirectory($root)
Ensure the root directory exists.
Definition: Local.php:98
getFilePath(SplFileInfo $file)
Get the normalized path from a SplFileInfo object.
Definition: Local.php:444
copy($path, $newpath)
Copy a file.bool
Definition: Local.php:240
update($path, $contents, Config $config)
Update a file.Config objectarray|false false on failure file meta data on success ...
Definition: Local.php:194
write($path, $contents, Config $config)
Write a new file.Config objectarray|false false on failure file meta data on success ...
Definition: Local.php:124
static forLink(SplFileInfo $file)
Create a new exception for a link.
readStream($path)
Read a file as a stream.array|false
Definition: Local.php:175
getVisibility($path)
Get the visibility of a file.array|false
Definition: Local.php:332
removePathPrefix($path)
Remove a path prefix.
if(!file_exists("$old.txt")) if($old===$new) if(file_exists("$new.txt")) $file
$info
Definition: index.php:5
get($key, $default=null)
Get a setting.
Definition: Config.php:35