PK 1=Rt;B B phpdoc.dist.xmlnu ٘
* root * \- Core * |- badlocation.php * |- AbstractFactory * | |- test.php * | |- other.php * | \- Invalid.csv * \- AnEmptyFolder ** Arrays will become directories with their key as directory name, and * strings becomes files with their key as file name and their value as file * content. * * @param string $rootDirName name of root directory * @param int $permissions file permissions of root directory * @param array $structure directory structure to add under root directory * @return vfsDirectory * @since 0.7.0 * @see https://github.com/mikey179/vfsStream/issues/14 * @see https://github.com/mikey179/vfsStream/issues/20 */ public static function setup($rootDirName = 'root', $permissions = null, array $structure = array()) { StreamWrapper::register(); return self::create($structure, StreamWrapper::setRoot(self::newDirectory($rootDirName, $permissions))); } /** * creates vfsStream directory structure from an array and adds it to given base dir * * Assumed $structure contains an array like this: *
* array('Core' = array('AbstractFactory' => array('test.php' => 'some text content',
* 'other.php' => 'Some more text content',
* 'Invalid.csv' => 'Something else',
* ),
* 'AnEmptyFolder' => array(),
* 'badlocation.php' => 'some bad content',
* )
* )
*
* the resulting directory tree will look like this:
* * baseDir * \- Core * |- badlocation.php * |- AbstractFactory * | |- test.php * | |- other.php * | \- Invalid.csv * \- AnEmptyFolder ** Arrays will become directories with their key as directory name, and * strings becomes files with their key as file name and their value as file * content. * * If no baseDir is given it will try to add the structure to the existing * root directory without replacing existing childs except those with equal * names. * * @param array $structure directory structure to add under root directory * @param vfsDirectory $baseDir base directory to add structure to * @return vfsDirectory * @throws \InvalidArgumentException * @since 0.10.0 * @see https://github.com/mikey179/vfsStream/issues/14 * @see https://github.com/mikey179/vfsStream/issues/20 */ public static function create(array $structure, vfsDirectory $baseDir = null) { if (null === $baseDir) { $baseDir = StreamWrapper::getRoot(); } if (null === $baseDir) { throw new \InvalidArgumentException('No baseDir given and no root directory set.'); } return self::addStructure($structure, $baseDir); } /** * helper method to create subdirectories recursively * * @param array $structure subdirectory structure to add * @param vfsDirectory $baseDir directory to add the structure to * @return vfsDirectory */ protected static function addStructure(array $structure, vfsDirectory $baseDir) { foreach ($structure as $name => $data) { $name = (string) $name; if (is_array($data) === true) { self::addStructure($data, self::newDirectory($name)->at($baseDir)); } elseif (is_string($data) === true) { $matches = null; preg_match('/^\[(.*)\]$/', $name, $matches); if ($matches !== array()) { self::newBlock($matches[1])->withContent($data)->at($baseDir); } else { self::newFile($name)->withContent($data)->at($baseDir); } } elseif ($data instanceof FileContent) { self::newFile($name)->withContent($data)->at($baseDir); } elseif ($data instanceof vfsFile) { $baseDir->addChild($data); } } return $baseDir; } /** * copies the file system structure from given path into the base dir * * If no baseDir is given it will try to add the structure to the existing * root directory without replacing existing childs except those with equal * names. * File permissions are copied as well. * Please note that file contents will only be copied if their file size * does not exceed the given $maxFileSize which defaults to 1024 KB. In case * the file is larger file content will be mocked, see * https://github.com/mikey179/vfsStream/wiki/MockingLargeFiles. * * @param string $path path to copy the structure from * @param vfsDirectory $baseDir directory to add the structure to * @param int $maxFileSize maximum file size of files to copy content from * @return vfsDirectory * @throws \InvalidArgumentException * @since 0.11.0 * @see https://github.com/mikey179/vfsStream/issues/4 */ public static function copyFromFileSystem($path, vfsDirectory $baseDir = null, $maxFileSize = 1048576) { if (null === $baseDir) { $baseDir = StreamWrapper::getRoot(); } if (null === $baseDir) { throw new \InvalidArgumentException('No baseDir given and no root directory set.'); } $dir = new \DirectoryIterator($path); foreach ($dir as $fileinfo) { switch (filetype($fileinfo->getPathname())) { case 'file': if ($fileinfo->getSize() <= $maxFileSize) { $content = file_get_contents($fileinfo->getPathname()); } else { $content = new LargeFileContent($fileinfo->getSize()); } self::newFile( $fileinfo->getFilename(), octdec(substr(sprintf('%o', $fileinfo->getPerms()), -4)) ) ->withContent($content) ->at($baseDir); break; case 'dir': if (!$fileinfo->isDot()) { self::copyFromFileSystem( $fileinfo->getPathname(), self::newDirectory( $fileinfo->getFilename(), octdec(substr(sprintf('%o', $fileinfo->getPerms()), -4)) )->at($baseDir), $maxFileSize ); } break; case 'block': self::newBlock( $fileinfo->getFilename(), octdec(substr(sprintf('%o', $fileinfo->getPerms()), -4)) )->at($baseDir); break; } } return $baseDir; } /** * returns a new file with given name * * @param string $name name of file to create * @param int $permissions permissions of file to create * @return vfsFile */ public static function newFile($name, $permissions = null) { return new vfsFile($name, $permissions); } /** * returns a new directory with given name * * If the name contains slashes, a new directory structure will be created. * The returned directory will always be the parent directory of this * directory structure. * * @param string $name name of directory to create * @param int $permissions permissions of directory to create * @return vfsDirectory */ public static function newDirectory($name, $permissions = null) { if ('/' === substr($name, 0, 1)) { $name = substr($name, 1); } $firstSlash = strpos($name, '/'); if (false === $firstSlash) { return new vfsDirectory($name, $permissions); } $ownName = substr($name, 0, $firstSlash); $subDirs = substr($name, $firstSlash + 1); $directory = new vfsDirectory($ownName, $permissions); if (is_string($subDirs) && strlen($subDirs) > 0) { self::newDirectory($subDirs, $permissions)->at($directory); } return $directory; } /** * returns a new block with the given name * * @param string $name name of the block device * @param int $permissions permissions of block to create * @return vfsBlock */ public static function newBlock($name, $permissions = null) { return new vfsBlock($name, $permissions); } /** * returns current user * * If the system does not support posix_getuid() the current user will be root (0). * * @return int */ public static function getCurrentUser() { return function_exists('posix_getuid') ? posix_getuid() : self::OWNER_ROOT; } /** * returns current group * * If the system does not support posix_getgid() the current group will be root (0). * * @return int */ public static function getCurrentGroup() { return function_exists('posix_getgid') ? posix_getgid() : self::GROUP_ROOT; } /** * use visitor to inspect a content structure * * If the given content is null it will fall back to use the current root * directory of the stream wrapper. * * Returns given visitor for method chaining comfort. * * @param vfsStreamVisitor $visitor the visitor who inspects * @param vfsStreamContent $content directory structure to inspect * @return vfsStreamVisitor * @throws \InvalidArgumentException * @since 0.10.0 * @see https://github.com/mikey179/vfsStream/issues/10 */ public static function inspect(vfsStreamVisitor $visitor, vfsStreamContent $content = null) { if (null !== $content) { return $visitor->visit($content); } $root = StreamWrapper::getRoot(); if (null === $root) { throw new \InvalidArgumentException('No content given and no root directory set.'); } return $visitor->visitDirectory($root); } /** * sets quota to given amount of bytes * * @param int $bytes * @since 1.1.0 */ public static function setQuota($bytes) { StreamWrapper::setQuota(new Quota($bytes)); } /** * checks if vfsStream lists dotfiles in directory listings * * @return bool * @since 1.3.0 */ public static function useDotfiles() { return self::$dotFiles; } /** * disable dotfiles in directory listings * * @since 1.3.0 */ public static function disableDotfiles() { self::$dotFiles = false; } /** * enable dotfiles in directory listings * * @since 1.3.0 */ public static function enableDotfiles() { self::$dotFiles = true; } } class_alias('bovigo\vfs\vfsStream', 'org\bovigo\vfs\vfsStream'); PK 1=RA src/DotDirectory.phpnu ٘ type = vfsStreamContent::TYPE_DIR; parent::__construct($name, $permissions); } /** * returns default permissions for concrete implementation * * @return int * @since 0.8.0 */ protected function getDefaultPermissions() { return 0777; } /** * returns size of directory * * The size of a directory is always 0 bytes. To calculate the summarized * size of all children in the directory use sizeSummarized(). * * @return int */ public function size() { return 0; } /** * returns summarized size of directory and its children * * @return int */ public function sizeSummarized() { $size = 0; foreach ($this->children as $child) { if ($child->getType() === vfsStreamContent::TYPE_DIR) { $size += $child->sizeSummarized(); } else { $size += $child->size(); } } return $size; } /** * renames the content * * @param string $newName * @throws vfsStreamException */ public function rename($newName) { if (strstr($newName, '/') !== false) { throw new vfsStreamException('Directory name can not contain /.'); } parent::rename($newName); } /** * sets parent path * * @param string $parentPath * @internal only to be set by parent * @since 1.2.0 */ public function setParentPath($parentPath) { parent::setParentPath($parentPath); foreach ($this->children as $child) { $child->setParentPath($this->path()); } } /** * adds child to the directory * * @param vfsStreamContent $child */ public function addChild(vfsStreamContent $child) { $child->setParentPath($this->path()); $this->children[$child->getName()] = $child; $this->updateModifications(); } /** * removes child from the directory * * @param string $name * @return bool */ public function removeChild($name) { foreach ($this->children as $key => $child) { if ($child->appliesTo($name)) { $child->setParentPath(null); unset($this->children[$key]); $this->updateModifications(); return true; } } return false; } /** * updates internal timestamps */ protected function updateModifications() { $time = time(); $this->lastAttributeModified = $time; $this->lastModified = $time; } /** * checks whether the container contains a child with the given name * * @param string $name * @return bool */ public function hasChild($name) { return ($this->getChild($name) !== null); } /** * returns the child with the given name * * @param string $name * @return vfsStreamContent */ public function getChild($name) { $childName = $this->getRealChildName($name); foreach ($this->children as $child) { if ($child->getName() === $childName) { return $child; } if ($child->appliesTo($childName) === true && $child->hasChild($childName) === true) { return $child->getChild($childName); } } return null; } /** * helper method to detect the real child name * * @param string $name * @return string */ protected function getRealChildName($name) { if ($this->appliesTo($name) === true) { return self::getChildName($name, $this->name); } return $name; } /** * helper method to calculate the child name * * @param string $name * @param string $ownName * @return string */ protected static function getChildName($name, $ownName) { if ($name === $ownName) { return $name; } return substr($name, strlen($ownName) + 1); } /** * checks whether directory contains any children * * @return bool * @since 0.10.0 */ public function hasChildren() { return (count($this->children) > 0); } /** * returns a list of children for this directory * * @return vfsStreamContent[] */ public function getChildren() { return array_values($this->children); } /** * returns iterator for the children * * @return vfsDirectoryIterator */ public function getIterator() { return new vfsDirectoryIterator($this->children); } /** * checks whether dir is a dot dir * * @return bool */ public function isDot() { if ('.' === $this->name || '..' === $this->name) { return true; } return false; } } class_alias('bovigo\vfs\vfsDirectory', 'org\bovigo\vfs\vfsStreamDirectory'); PK 1=R%+ + src/vfsBlock.phpnu ٘ type = vfsStreamContent::TYPE_BLOCK; } } class_alias('bovigo\vfs\vfsBlock', 'org\bovigo\vfs\vfsStreamBlock'); PK 1=R=o src/vfsDirectoryIterator.phpnu ٘ children = $children; if (vfsStream::useDotfiles()) { array_unshift($this->children, new DotDirectory('.'), new DotDirectory('..')); } reset($this->children); } /** * resets children pointer */ public function rewind() { reset($this->children); } /** * returns the current child * * @return vfsStreamContent */ public function current() { $child = current($this->children); if (false === $child) { return null; } return $child; } /** * returns the name of the current child * * @return string */ public function key() { $child = current($this->children); if (false === $child) { return null; } return $child->getName(); } /** * iterates to next child */ public function next() { next($this->children); } /** * checks if the current value is valid * * @return bool */ public function valid() { return (false !== current($this->children)); } } class_alias('bovigo\vfs\vfsDirectoryIterator', 'org\bovigo\vfs\vfsStreamContainerIterator'); PK 1=REU" " src/BasicFile.phpnu ٘ name = "{$name}"; $time = time(); if (null === $permissions) { $permissions = $this->getDefaultPermissions() & ~vfsStream::umask(); } $this->lastAccessed = $time; $this->lastAttributeModified = $time; $this->lastModified = $time; $this->permissions = $permissions; $this->user = vfsStream::getCurrentUser(); $this->group = vfsStream::getCurrentGroup(); } /** * returns default permissions for concrete implementation * * @return int * @since 0.8.0 */ protected abstract function getDefaultPermissions(); /** * returns the file name of the content * * @return string */ public function getName() { return $this->name; } /** * renames the content * * @param string $newName */ public function rename($newName) { $this->name = "{$newName}"; } /** * checks whether the container can be applied to given name * * @param string $name * @return bool */ public function appliesTo($name) { if ($name === $this->name) { return true; } $segment_name = $this->name.'/'; return (strncmp($segment_name, $name, strlen($segment_name)) == 0); } /** * returns the type of the container * * @return int */ public function getType() { return $this->type; } /** * sets the last modification time of the stream content * * @param int $filemtime * @return $this */ public function lastModified($filemtime) { $this->lastModified = $filemtime; return $this; } /** * returns the last modification time of the stream content * * @return int */ public function filemtime() { return $this->lastModified; } /** * sets last access time of the stream content * * @param int $fileatime * @return $this * @since 0.9 */ public function lastAccessed($fileatime) { $this->lastAccessed = $fileatime; return $this; } /** * returns the last access time of the stream content * * @return int * @since 0.9 */ public function fileatime() { return $this->lastAccessed; } /** * sets the last attribute modification time of the stream content * * @param int $filectime * @return $this * @since 0.9 */ public function lastAttributeModified($filectime) { $this->lastAttributeModified = $filectime; return $this; } /** * returns the last attribute modification time of the stream content * * @return int * @since 0.9 */ public function filectime() { return $this->lastAttributeModified; } /** * adds content to given container * * @param vfsStreamContainer $container * @return $this */ public function at(vfsStreamContainer $container) { $container->addChild($this); return $this; } /** * change file mode to given permissions * * @param int $permissions * @return $this */ public function chmod($permissions) { $this->permissions = $permissions; $this->lastAttributeModified = time(); clearstatcache(); return $this; } /** * returns permissions * * @return int */ public function getPermissions() { return $this->permissions; } /** * checks whether content is readable * * @param int $user id of user to check for * @param int $group id of group to check for * @return bool */ public function isReadable($user, $group) { if ($this->user === $user) { $check = 0400; } elseif ($this->group === $group) { $check = 0040; } else { $check = 0004; } return (bool) ($this->permissions & $check); } /** * checks whether content is writable * * @param int $user id of user to check for * @param int $group id of group to check for * @return bool */ public function isWritable($user, $group) { if ($this->user === $user) { $check = 0200; } elseif ($this->group === $group) { $check = 0020; } else { $check = 0002; } return (bool) ($this->permissions & $check); } /** * checks whether content is executable * * @param int $user id of user to check for * @param int $group id of group to check for * @return bool */ public function isExecutable($user, $group) { if ($this->user === $user) { $check = 0100; } elseif ($this->group === $group) { $check = 0010; } else { $check = 0001; } return (bool) ($this->permissions & $check); } /** * change owner of file to given user * * @param int $user * @return $this */ public function chown($user) { $this->user = $user; $this->lastAttributeModified = time(); return $this; } /** * checks whether file is owned by given user * * @param int $user * @return bool */ public function isOwnedByUser($user) { return $this->user === $user; } /** * returns owner of file * * @return int */ public function getUser() { return $this->user; } /** * change owner group of file to given group * * @param int $group * @return $this */ public function chgrp($group) { $this->group = $group; $this->lastAttributeModified = time(); return $this; } /** * checks whether file is owned by group * * @param int $group * @return bool */ public function isOwnedByGroup($group) { return $this->group === $group; } /** * returns owner group of file * * @return int */ public function getGroup() { return $this->group; } /** * sets parent path * * @param string $parentPath * @internal only to be set by parent * @since 1.2.0 */ public function setParentPath($parentPath) { $this->parentPath = $parentPath; } /** * returns path to this content * * @return string * @since 1.2.0 */ public function path() { if (null === $this->parentPath) { return $this->name; } return $this->parentPath . '/' . $this->name; } /** * returns complete vfsStream url for this content * * @return string * @since 1.2.0 */ public function url() { return vfsStream::url($this->path()); } } class_alias('bovigo\vfs\BasicFile', 'org\bovigo\vfs\vfsStreamAbstractContent'); PK 1=RsGv v src/StreamWrapper.phpnu ٘ getName() === $path) { return self::$root; } if ($this->isInRoot($path) && self::$root->hasChild($path) === true) { return self::$root->getChild($path); } return null; } /** * helper method to detect whether given path is in root path * * @param string $path * @return bool */ private function isInRoot($path) { return substr($path, 0, strlen(self::$root->getName())) === self::$root->getName(); } /** * returns content for given path but only when it is of given type * * @param string $path * @param int $type * @return vfsStreamContent */ protected function getContentOfType($path, $type) { $content = $this->getContent($path); if (null !== $content && $content->getType() === $type) { return $content; } return null; } /** * splits path into its dirname and the basename * * @param string $path * @return string[] */ protected function splitPath($path) { $lastSlashPos = strrpos($path, '/'); if (false === $lastSlashPos) { return array('dirname' => '', 'basename' => $path); } return array('dirname' => substr($path, 0, $lastSlashPos), 'basename' => substr($path, $lastSlashPos + 1) ); } /** * helper method to resolve a path from /foo/bar/. to /foo/bar * * @param string $path * @return string */ protected function resolvePath($path) { $newPath = array(); foreach (explode('/', $path) as $pathPart) { if ('.' !== $pathPart) { if ('..' !== $pathPart) { $newPath[] = $pathPart; } elseif (count($newPath) > 1) { array_pop($newPath); } } } return implode('/', $newPath); } /** * open the stream * * @param string $path the path to open * @param string $mode mode for opening * @param string $options options for opening * @param string $opened_path full path that was actually opened * @return bool */ public function stream_open($path, $mode, $options, $opened_path) { $extended = ((strstr($mode, '+') !== false) ? (true) : (false)); $mode = str_replace(array('t', 'b', '+'), '', $mode); if (in_array($mode, array('r', 'w', 'a', 'x', 'c')) === false) { if (($options & STREAM_REPORT_ERRORS) === STREAM_REPORT_ERRORS) { trigger_error('Illegal mode ' . $mode . ', use r, w, a, x or c, flavoured with t, b and/or +', E_USER_WARNING); } return false; } $this->mode = $this->calculateMode($mode, $extended); $path = $this->resolvePath(vfsStream::path($path)); $this->content = $this->getContentOfType($path, vfsStreamContent::TYPE_FILE); if (null !== $this->content) { if (self::WRITE === $mode) { if (($options & STREAM_REPORT_ERRORS) === STREAM_REPORT_ERRORS) { trigger_error('File ' . $path . ' already exists, can not open with mode x', E_USER_WARNING); } return false; } if ( (self::TRUNCATE === $mode || self::APPEND === $mode) && $this->content->isWritable(vfsStream::getCurrentUser(), vfsStream::getCurrentGroup()) === false ) { return false; } if (self::TRUNCATE === $mode) { $this->content->openWithTruncate(); } elseif (self::APPEND === $mode) { $this->content->openForAppend(); } else { if (!$this->content->isReadable(vfsStream::getCurrentUser(), vfsStream::getCurrentGroup())) { if (($options & STREAM_REPORT_ERRORS) === STREAM_REPORT_ERRORS) { trigger_error('Permission denied', E_USER_WARNING); } return false; } $this->content->open(); } return true; } $content = $this->createFile($path, $mode, $options); if (false === $content) { return false; } $this->content = $content; return true; } /** * creates a file at given path * * @param string $path the path to open * @param string $mode mode for opening * @param string $options options for opening * @return bool */ private function createFile($path, $mode = null, $options = null) { $names = $this->splitPath($path); if (empty($names['dirname']) === true) { if (($options & STREAM_REPORT_ERRORS) === STREAM_REPORT_ERRORS) { trigger_error('File ' . $names['basename'] . ' does not exist', E_USER_WARNING); } return false; } $dir = $this->getContentOfType($names['dirname'], vfsStreamContent::TYPE_DIR); if (null === $dir) { if (($options & STREAM_REPORT_ERRORS) === STREAM_REPORT_ERRORS) { trigger_error('Directory ' . $names['dirname'] . ' does not exist', E_USER_WARNING); } return false; } elseif ($dir->hasChild($names['basename']) === true) { if (($options & STREAM_REPORT_ERRORS) === STREAM_REPORT_ERRORS) { trigger_error('Directory ' . $names['dirname'] . ' already contains a director named ' . $names['basename'], E_USER_WARNING); } return false; } if (self::READ === $mode) { if (($options & STREAM_REPORT_ERRORS) === STREAM_REPORT_ERRORS) { trigger_error('Can not open non-existing file ' . $path . ' for reading', E_USER_WARNING); } return false; } if ($dir->isWritable(vfsStream::getCurrentUser(), vfsStream::getCurrentGroup()) === false) { if (($options & STREAM_REPORT_ERRORS) === STREAM_REPORT_ERRORS) { trigger_error('Can not create new file in non-writable path ' . $names['dirname'], E_USER_WARNING); } return false; } return vfsStream::newFile($names['basename'])->at($dir); } /** * calculates the file mode * * @param string $mode opening mode: r, w, a or x * @param bool $extended true if + was set with opening mode * @return int */ protected function calculateMode($mode, $extended) { if (true === $extended) { return self::ALL; } if (self::READ === $mode) { return self::READONLY; } return self::WRITEONLY; } /** * closes the stream * * @see https://github.com/mikey179/vfsStream/issues/40 */ public function stream_close() { $this->content->lock($this, LOCK_UN); } /** * read the stream up to $count bytes * * @param int $count amount of bytes to read * @return string */ public function stream_read($count) { if (self::WRITEONLY === $this->mode) { return ''; } if ($this->content->isReadable(vfsStream::getCurrentUser(), vfsStream::getCurrentGroup()) === false) { return ''; } return $this->content->read($count); } /** * writes data into the stream * * @param string $data * @return int amount of bytes written */ public function stream_write($data) { if (self::READONLY === $this->mode) { return 0; } if ($this->content->isWritable(vfsStream::getCurrentUser(), vfsStream::getCurrentGroup()) === false) { return 0; } if (self::$quota->isLimited()) { $data = substr($data, 0, self::$quota->spaceLeft(self::$root->sizeSummarized())); } return $this->content->write($data); } /** * truncates a file to a given length * * @param int $size length to truncate file to * @return bool * @since 1.1.0 */ public function stream_truncate($size) { if (self::READONLY === $this->mode) { return false; } if ($this->content->isWritable(vfsStream::getCurrentUser(), vfsStream::getCurrentGroup()) === false) { return false; } if ($this->content->getType() !== vfsStreamContent::TYPE_FILE) { return false; } if (self::$quota->isLimited() && $this->content->size() < $size) { $maxSize = self::$quota->spaceLeft(self::$root->sizeSummarized()); if (0 === $maxSize) { return false; } if ($size > $maxSize) { $size = $maxSize; } } return $this->content->truncate($size); } /** * sets metadata like owner, user or permissions * * @param string $path * @param int $option * @param mixed $var * @return bool * @since 1.1.0 */ public function stream_metadata($path, $option, $var) { $path = $this->resolvePath(vfsStream::path($path)); $content = $this->getContent($path); switch ($option) { case STREAM_META_TOUCH: if (null === $content) { $content = $this->createFile($path, null, STREAM_REPORT_ERRORS); // file creation may not be allowed at provided path if (false === $content) { return false; } } $currentTime = time(); $content->lastModified(((isset($var[0])) ? ($var[0]) : ($currentTime))) ->lastAccessed(((isset($var[1])) ? ($var[1]) : ($currentTime))); return true; case STREAM_META_OWNER_NAME: return false; case STREAM_META_OWNER: if (null === $content) { return false; } return $this->doPermChange($path, $content, function() use ($content, $var) { $content->chown($var); } ); case STREAM_META_GROUP_NAME: return false; case STREAM_META_GROUP: if (null === $content) { return false; } return $this->doPermChange($path, $content, function() use ($content, $var) { $content->chgrp($var); } ); case STREAM_META_ACCESS: if (null === $content) { return false; } return $this->doPermChange($path, $content, function() use ($content, $var) { $content->chmod($var); } ); default: return false; } } /** * executes given permission change when necessary rights allow such a change * * @param string $path * @param BasicFile $content * @param \Closure $change * @return bool */ private function doPermChange($path, BasicFile $content, \Closure $change) { if (!$content->isOwnedByUser(vfsStream::getCurrentUser())) { return false; } if (self::$root->getName() !== $path) { $names = $this->splitPath($path); $parent = $this->getContent($names['dirname']); if (!$parent->isWritable(vfsStream::getCurrentUser(), vfsStream::getCurrentGroup())) { return false; } } $change(); return true; } /** * checks whether stream is at end of file * * @return bool */ public function stream_eof() { return $this->content->eof(); } /** * returns the current position of the stream * * @return int */ public function stream_tell() { return $this->content->getBytesRead(); } /** * seeks to the given offset * * @param int $offset * @param int $whence * @return bool */ public function stream_seek($offset, $whence) { return $this->content->seek($offset, $whence); } /** * flushes unstored data into storage * * @return bool */ public function stream_flush() { return true; } /** * returns status of stream * * @return array */ public function stream_stat() { $fileStat = array('dev' => 0, 'ino' => 0, 'mode' => $this->content->getType() | $this->content->getPermissions(), 'nlink' => 0, 'uid' => $this->content->getUser(), 'gid' => $this->content->getGroup(), 'rdev' => 0, 'size' => $this->content->size(), 'atime' => $this->content->fileatime(), 'mtime' => $this->content->filemtime(), 'ctime' => $this->content->filectime(), 'blksize' => -1, 'blocks' => -1 ); return array_merge(array_values($fileStat), $fileStat); } /** * retrieve the underlaying resource * * Please note that this method always returns false as there is no * underlaying resource to return. * * @param int $cast_as * @since 0.9.0 * @see https://github.com/mikey179/vfsStream/issues/3 * @return bool */ public function stream_cast($cast_as) { return false; } /** * set lock status for stream * * @param int $operation * @return bool * @since 0.10.0 * @see https://github.com/mikey179/vfsStream/issues/6 * @see https://github.com/mikey179/vfsStream/issues/31 * @see https://github.com/mikey179/vfsStream/issues/40 */ public function stream_lock($operation) { if ((LOCK_NB & $operation) == LOCK_NB) { $operation = $operation - LOCK_NB; } return $this->content->lock($this, $operation); } /** * sets options on the stream * * @param int $option key of option to set * @param int $arg1 * @param int $arg2 * @return bool * @since 0.10.0 * @see https://github.com/mikey179/vfsStream/issues/15 * @see http://www.php.net/manual/streamwrapper.stream-set-option.php */ public function stream_set_option($option, $arg1, $arg2) { switch ($option) { case STREAM_OPTION_BLOCKING: // break omitted case STREAM_OPTION_READ_TIMEOUT: // break omitted case STREAM_OPTION_WRITE_BUFFER: // break omitted default: // nothing to do here } return false; } /** * remove the data under the given path * * @param string $path * @return bool */ public function unlink($path) { $realPath = $this->resolvePath(vfsStream::path($path)); $content = $this->getContent($realPath); if (null === $content) { trigger_error('unlink(' . $path . '): No such file or directory', E_USER_WARNING); return false; } if ($content->getType() !== vfsStreamContent::TYPE_FILE) { trigger_error('unlink(' . $path . '): Operation not permitted', E_USER_WARNING); return false; } return $this->doUnlink($realPath); } /** * removes a path * * @param string $path * @return bool */ protected function doUnlink($path) { if (self::$root->getName() === $path) { // delete root? very brave. :) self::$root = null; clearstatcache(); return true; } $names = $this->splitPath($path); $content = $this->getContent($names['dirname']); if (!$content->isWritable(vfsStream::getCurrentUser(), vfsStream::getCurrentGroup())) { return false; } clearstatcache(); return $content->removeChild($names['basename']); } /** * rename from one path to another * * @param string $path_from * @param string $path_to * @return bool * @author Benoit Aubuchon */ public function rename($path_from, $path_to) { $srcRealPath = $this->resolvePath(vfsStream::path($path_from)); $dstRealPath = $this->resolvePath(vfsStream::path($path_to)); $srcContent = $this->getContent($srcRealPath); if (null == $srcContent) { trigger_error(' No such file or directory', E_USER_WARNING); return false; } $dstNames = $this->splitPath($dstRealPath); $dstParentContent = $this->getContent($dstNames['dirname']); if (null == $dstParentContent) { trigger_error('No such file or directory', E_USER_WARNING); return false; } if (!$dstParentContent->isWritable(vfsStream::getCurrentUser(), vfsStream::getCurrentGroup())) { trigger_error('Permission denied', E_USER_WARNING); return false; } if ($dstParentContent->getType() !== vfsStreamContent::TYPE_DIR) { trigger_error('Target is not a directory', E_USER_WARNING); return false; } // remove old source first, so we can rename later // (renaming first would lead to not being able to remove the old path) if (!$this->doUnlink($srcRealPath)) { return false; } $dstContent = $srcContent; // Renaming the filename $dstContent->rename($dstNames['basename']); // Copying to the destination $dstParentContent->addChild($dstContent); return true; } /** * creates a new directory * * @param string $path * @param int $mode * @param int $options * @return bool */ public function mkdir($path, $mode, $options) { $umask = vfsStream::umask(); if (0 < $umask) { $permissions = $mode & ~$umask; } else { $permissions = $mode; } $path = $this->resolvePath(vfsStream::path($path)); if (null !== $this->getContent($path)) { trigger_error('mkdir(): Path vfs://' . $path . ' exists', E_USER_WARNING); return false; } if (null === self::$root) { self::$root = vfsStream::newDirectory($path, $permissions); return true; } $maxDepth = count(explode('/', $path)); $names = $this->splitPath($path); $newDirs = $names['basename']; $dir = null; $i = 0; while ($dir === null && $i < $maxDepth) { $dir = $this->getContent($names['dirname']); $names = $this->splitPath($names['dirname']); if (null == $dir) { $newDirs = $names['basename'] . '/' . $newDirs; } $i++; } if (null === $dir || $dir->getType() !== vfsStreamContent::TYPE_DIR || $dir->isWritable(vfsStream::getCurrentUser(), vfsStream::getCurrentGroup()) === false) { return false; } $recursive = ((STREAM_MKDIR_RECURSIVE & $options) !== 0) ? (true) : (false); if (strpos($newDirs, '/') !== false && false === $recursive) { return false; } vfsStream::newDirectory($newDirs, $permissions)->at($dir); return true; } /** * removes a directory * * @param string $path * @param int $options * @return bool * @todo consider $options with STREAM_MKDIR_RECURSIVE */ public function rmdir($path, $options) { $path = $this->resolvePath(vfsStream::path($path)); $child = $this->getContentOfType($path, vfsStreamContent::TYPE_DIR); if (null === $child) { return false; } // can only remove empty directories if (count($child->getChildren()) > 0) { return false; } if (self::$root->getName() === $path) { // delete root? very brave. :) self::$root = null; clearstatcache(); return true; } $names = $this->splitPath($path); $dir = $this->getContentOfType($names['dirname'], vfsStreamContent::TYPE_DIR); if ($dir->isWritable(vfsStream::getCurrentUser(), vfsStream::getCurrentGroup()) === false) { return false; } clearstatcache(); return $dir->removeChild($child->getName()); } /** * opens a directory * * @param string $path * @param int $options * @return bool */ public function dir_opendir($path, $options) { $path = $this->resolvePath(vfsStream::path($path)); $this->dir = $this->getContentOfType($path, vfsStreamContent::TYPE_DIR); if (null === $this->dir || $this->dir->isReadable(vfsStream::getCurrentUser(), vfsStream::getCurrentGroup()) === false) { return false; } $this->dirIterator = $this->dir->getIterator(); return true; } /** * reads directory contents * * @return string */ public function dir_readdir() { $dir = $this->dirIterator->current(); if (null === $dir) { return false; } $this->dirIterator->next(); return $dir->getName(); } /** * reset directory iteration * * @return bool */ public function dir_rewinddir() { return $this->dirIterator->rewind(); } /** * closes directory * * @return bool */ public function dir_closedir() { $this->dirIterator = null; return true; } /** * returns status of url * * @param string $path path of url to return status for * @param int $flags flags set by the stream API * @return array */ public function url_stat($path, $flags) { $content = $this->getContent($this->resolvePath(vfsStream::path($path))); if (null === $content) { if (($flags & STREAM_URL_STAT_QUIET) != STREAM_URL_STAT_QUIET) { trigger_error(' No such file or directory: ' . $path, E_USER_WARNING); } return false; } $fileStat = array('dev' => 0, 'ino' => 0, 'mode' => $content->getType() | $content->getPermissions(), 'nlink' => 0, 'uid' => $content->getUser(), 'gid' => $content->getGroup(), 'rdev' => 0, 'size' => $content->size(), 'atime' => $content->fileatime(), 'mtime' => $content->filemtime(), 'ctime' => $content->filectime(), 'blksize' => -1, 'blocks' => -1 ); return array_merge(array_values($fileStat), $fileStat); } } class_alias('bovigo\vfs\StreamWrapper', 'org\bovigo\vfs\vfsStreamWrapper'); PK 1=Rh h src/Quota.phpnu ٘ amount = $amount; } /** * create with unlimited space * * @return Quota */ public static function unlimited() { return new self(self::UNLIMITED); } /** * checks if a quota is set * * @return bool */ public function isLimited() { return self::UNLIMITED < $this->amount; } /** * checks if given used space exceeda quota limit * * * @param int $usedSpace * @return int */ public function spaceLeft($usedSpace) { if (self::UNLIMITED === $this->amount) { return $usedSpace; } if ($usedSpace >= $this->amount) { return 0; } $spaceLeft = $this->amount - $usedSpace; if (0 >= $spaceLeft) { return 0; } return $spaceLeft; } } class_alias('bovigo\vfs\Quota', 'org\bovigo\vfs\Quota'); PK 1=RL Z' Z' src/vfsFile.phpnu ٘ content = new StringBasedFileContent(''); $this->type = vfsStreamContent::TYPE_FILE; parent::__construct($name, $permissions); } /** * returns default permissions for concrete implementation * * @return int * @since 0.8.0 */ protected function getDefaultPermissions() { return 0666; } /** * checks whether the container can be applied to given name * * @param string $name * @return bool */ public function appliesTo($name) { return ($name === $this->name); } /** * alias for withContent() * * @param string $content * @return vfsFile * @see withContent() */ public function setContent($content) { return $this->withContent($content); } /** * sets the contents of the file * * Setting content with this method does not change the time when the file * was last modified. * * @param string]FileContent $content * @return vfsFile * @throws \InvalidArgumentException */ public function withContent($content) { if (is_string($content)) { $this->content = new StringBasedFileContent($content); } elseif ($content instanceof FileContent) { $this->content = $content; } else { throw new InvalidArgumentException( sprintf( 'Given content must either be a string or an instance of %s', FileContent::class ) ); } return $this; } /** * returns the contents of the file * * Getting content does not change the time when the file * was last accessed. * * @return string */ public function getContent() { return $this->content->content(); } /** * simply open the file * * @since 0.9 */ public function open() { $this->content->seek(0, SEEK_SET); $this->lastAccessed = time(); } /** * open file and set pointer to end of file * * @since 0.9 */ public function openForAppend() { $this->content->seek(0, SEEK_END); $this->lastAccessed = time(); } /** * open file and truncate content * * @since 0.9 */ public function openWithTruncate() { $this->open(); $this->content->truncate(0); $time = time(); $this->lastAccessed = $time; $this->lastModified = $time; } /** * reads the given amount of bytes from content * * Using this method changes the time when the file was last accessed. * * @param int $count * @return string */ public function read($count) { $this->lastAccessed = time(); return $this->content->read($count); } /** * returns the content until its end from current offset * * Using this method changes the time when the file was last accessed. * * @return string * @deprecated since 1.3.0 */ public function readUntilEnd() { $this->lastAccessed = time(); return $this->content->readUntilEnd(); } /** * writes an amount of data * * Using this method changes the time when the file was last modified. * * @param string $data * @return int amount of written bytes */ public function write($data) { $this->lastModified = time(); return $this->content->write($data); } /** * Truncates a file to a given length * * @param int $size length to truncate file to * @return bool * @since 1.1.0 */ public function truncate($size) { $this->content->truncate($size); $this->lastModified = time(); return true; } /** * checks whether pointer is at end of file * * @return bool */ public function eof() { return $this->content->eof(); } /** * returns the current position within the file * * @return int * @deprecated since 1.3.0 */ public function getBytesRead() { return $this->content->bytesRead(); } /** * seeks to the given offset * * @param int $offset * @param int $whence * @return bool */ public function seek($offset, $whence) { return $this->content->seek($offset, $whence); } /** * returns size of content * * @return int */ public function size() { return $this->content->size(); } /** * locks file for * * @param resource|StreamWrapper $resource * @param int $operation * @return bool * @since 0.10.0 * @see https://github.com/mikey179/vfsStream/issues/6 * @see https://github.com/mikey179/vfsStream/issues/40 */ public function lock($resource, $operation) { if ((LOCK_NB & $operation) == LOCK_NB) { $operation = $operation - LOCK_NB; } // call to lock file on the same file handler firstly releases the lock $this->unlock($resource); if (LOCK_EX === $operation) { if ($this->isLocked()) { return false; } $this->setExclusiveLock($resource); } elseif(LOCK_SH === $operation) { if ($this->hasExclusiveLock()) { return false; } $this->addSharedLock($resource); } return true; } /** * Removes lock from file acquired by given resource * * @param resource|StreamWrapper $resource * @see https://github.com/mikey179/vfsStream/issues/40 */ public function unlock($resource) { if ($this->hasExclusiveLock($resource)) { $this->exclusiveLock = null; } if ($this->hasSharedLock($resource)) { unset($this->sharedLock[$this->getResourceId($resource)]); } } /** * Set exlusive lock on file by given resource * * @param resource|StreamWrapper $resource * @see https://github.com/mikey179/vfsStream/issues/40 */ protected function setExclusiveLock($resource) { $this->exclusiveLock = $this->getResourceId($resource); } /** * Add shared lock on file by given resource * * @param resource|StreamWrapper $resource * @see https://github.com/mikey179/vfsStream/issues/40 */ protected function addSharedLock($resource) { $this->sharedLock[$this->getResourceId($resource)] = true; } /** * checks whether file is locked * * @param resource|StreamWrapper $resource * @return bool * @since 0.10.0 * @see https://github.com/mikey179/vfsStream/issues/6 * @see https://github.com/mikey179/vfsStream/issues/40 */ public function isLocked($resource = null) { return $this->hasSharedLock($resource) || $this->hasExclusiveLock($resource); } /** * checks whether file is locked in shared mode * * @param resource|StreamWrapper $resource * @return bool * @since 0.10.0 * @see https://github.com/mikey179/vfsStream/issues/6 * @see https://github.com/mikey179/vfsStream/issues/40 */ public function hasSharedLock($resource = null) { if (null !== $resource) { return isset($this->sharedLock[$this->getResourceId($resource)]); } return !empty($this->sharedLock); } /** * Returns unique resource id * * @param resource|StreamWrapper $resource * @return string * @see https://github.com/mikey179/vfsStream/issues/40 */ public function getResourceId($resource) { if (is_resource($resource)) { $data = stream_get_meta_data($resource); $resource = $data['wrapper_data']; } return spl_object_hash($resource); } /** * checks whether file is locked in exclusive mode * * @param resource|StreamWrapper $resource * @return bool * @since 0.10.0 * @see https://github.com/mikey179/vfsStream/issues/6 * @see https://github.com/mikey179/vfsStream/issues/40 */ public function hasExclusiveLock($resource = null) { if (null !== $resource) { return $this->exclusiveLock === $this->getResourceId($resource); } return null !== $this->exclusiveLock; } } class_alias('bovigo\vfs\vfsFile', 'org\bovigo\vfs\vfsStreamFile'); PK 1=R,B\ \ src/visitor/Printer.phpnu ٘ out = $out; } /** * visit a file and process it * * @param vfsFile $file * @return Printer */ public function visitFile(vfsFile $file) { $this->printContent($file->getName()); return $this; } /** * visit a block device and process it * * @param vfsBlock $block * @return Printer */ public function visitBlockDevice(vfsBlock $block) { $name = '[' . $block->getName() . ']'; $this->printContent($name); return $this; } /** * visit a directory and process it * * @param vfsDirectory $dir * @return Printer */ public function visitDirectory(vfsDirectory $dir) { $this->printContent($dir->getName()); $this->depth++; foreach ($dir as $child) { $this->visit($child); } $this->depth--; return $this; } /** * helper method to print the content * * @param string $name */ protected function printContent($name) { fwrite($this->out, str_repeat(' ', $this->depth) . '- ' . $name . "\n"); } } class_alias('bovigo\vfs\visitor\Printer', 'org\bovigo\vfs\visitor\vfsStreamPrintVisitor'); PK 1=RČ w w src/visitor/vfsStreamVisitor.phpnu ٘ reset(); } /** * visit a file and process it * * @param vfsFile $file * @return StructureInspector */ public function visitFile(vfsFile $file) { $this->current[$file->getName()] = $file->getContent(); return $this; } /** * visit a block device and process it * * @param vfsBlock $block * @return StructureInspector */ public function visitBlockDevice(vfsBlock $block) { $this->current['[' . $block->getName() . ']'] = $block->getContent(); return $this; } /** * visit a directory and process it * * @param vfsDirectory $dir * @return StructureInspector */ public function visitDirectory(vfsDirectory $dir) { $this->current[$dir->getName()] = array(); $tmp =& $this->current; $this->current =& $tmp[$dir->getName()]; foreach ($dir as $child) { $this->visit($child); } $this->current =& $tmp; return $this; } /** * returns structure of visited contents * * @return array * @api */ public function getStructure() { return $this->structure; } /** * resets structure so visitor could be reused * * @return StructureInspector */ public function reset() { $this->structure = array(); $this->current =& $this->structure; return $this; } } class_alias('bovigo\vfs\visitor\StructureInspector', 'org\bovigo\vfs\visitor\vfsStreamStructureVisitor'); PK 1=R\+B B src/visitor/BaseVisitor.phpnu ٘ getType()) { case vfsStreamContent::TYPE_BLOCK: $this->visitBlockDevice($content); break; case vfsStreamContent::TYPE_FILE: $this->visitFile($content); break; case vfsStreamContent::TYPE_DIR: if (!$content->isDot()) { $this->visitDirectory($content); } break; default: throw new \InvalidArgumentException('Unknown content type ' . $content->getType() . ' for ' . $content->getName()); } return $this; } /** * visit a block device and process it * * @param vfsBlock $block * @return vfsStreamVisitor */ public function visitBlockDevice(vfsBlock $block) { return $this->visitFile($block); } } class_alias('bovigo\vfs\visitor\BaseVisitor', 'org\bovigo\vfs\visitor\vfsStreamAbstractVisitor'); PK 1=RU4 # src/content/SeekableFileContent.phpnu ٘ doRead($this->offset, $count); $this->offset += $count; return $data; } /** * actual reading of given byte count starting at given offset * * @param int $offset * @param int $count */ protected abstract function doRead($offset, $count); /** * seeks to the given offset * * @param int $offset * @param int $whence * @return bool */ public function seek($offset, $whence) { $newOffset = $this->offset; switch ($whence) { case SEEK_CUR: $newOffset += $offset; break; case SEEK_END: $newOffset = $this->size() + $offset; break; case SEEK_SET: $newOffset = $offset; break; default: return false; } if ($newOffset<0) { return false; } $this->offset = $newOffset; return true; } /** * checks whether pointer is at end of file * * @return bool */ public function eof() { return $this->size() <= $this->offset; } /** * writes an amount of data * * @param string $data * @return int amount of written bytes */ public function write($data) { $dataLength = strlen($data); $this->doWrite($data, $this->offset, $dataLength); $this->offset += $dataLength; return $dataLength; } /** * actual writing of data with specified length at given offset * * @param string $data * @param int $offset * @param int $length */ protected abstract function doWrite($data, $offset, $length); /** * for backwards compatibility with vfsStreamFile::bytesRead() * * @return int * @deprecated */ public function bytesRead() { return $this->offset; } /** * for backwards compatibility with vfsStreamFile::readUntilEnd() * * @return string * @deprecated */ public function readUntilEnd() { return substr($this->content(), $this->offset); } } class_alias('bovigo\vfs\content\SeekableFileContent', 'org\bovigo\vfs\content\SeekableFileContent'); PK 1=RX&wب src/content/LargeFileContent.phpnu ٘ size = $size; } /** * create large file with given size in kilobyte * * @param int $kilobyte * @return LargeFileContent */ public static function withKilobytes($kilobyte) { return new self($kilobyte * 1024); } /** * create large file with given size in megabyte * * @param int $megabyte * @return LargeFileContent */ public static function withMegabytes($megabyte) { return self::withKilobytes($megabyte * 1024); } /** * create large file with given size in gigabyte * * @param int $gigabyte * @return LargeFileContent */ public static function withGigabytes($gigabyte) { return self::withMegabytes($gigabyte * 1024); } /** * returns actual content * * @return string */ public function content() { return $this->doRead(0, $this->size); } /** * returns size of content * * @return int */ public function size() { return $this->size; } /** * actual reading of given byte count starting at given offset * * @param int $offset * @param int $count */ protected function doRead($offset, $count) { if (($offset + $count) > $this->size) { $count = $this->size - $offset; } $result = ''; for ($i = 0; $i < $count; $i++) { if (isset($this->content[$i + $offset])) { $result .= $this->content[$i + $offset]; } else { $result .= ' '; } } return $result; } /** * actual writing of data with specified length at given offset * * @param string $data * @param int $offset * @param int $length */ protected function doWrite($data, $offset, $length) { for ($i = 0; $i < $length; $i++) { $this->content[$i + $offset] = substr($data, $i, 1); } if ($offset >= $this->size) { $this->size += $length; } elseif (($offset + $length) > $this->size) { $this->size = $offset + $length; } } /** * Truncates a file to a given length * * @param int $size length to truncate file to * @return bool */ public function truncate($size) { $this->size = $size; foreach (array_filter(array_keys($this->content), function($pos) use ($size) { return $pos >= $size; } ) as $removePos) { unset($this->content[$removePos]); } return true; } } class_alias('bovigo\vfs\content\LargeFileContent', 'org\bovigo\vfs\content\LargeFileContent'); PK 1=RX:~ src/content/FileContent.phpnu ٘ content = $content; } /** * returns actual content * * @return string */ public function content() { return $this->content; } /** * returns size of content * * @return int */ public function size() { return strlen($this->content); } /** * actual reading of length starting at given offset * * @param int $offset * @param int $count */ protected function doRead($offset, $count) { return (string) substr($this->content, $offset, $count); } /** * actual writing of data with specified length at given offset * * @param string $data * @param int $offset * @param int $length */ protected function doWrite($data, $offset, $length) { $this->content = substr($this->content, 0, $offset) . $data . substr($this->content, $offset + $length); } /** * Truncates a file to a given length * * @param int $size length to truncate file to * @return bool */ public function truncate($size) { if ($size > $this->size()) { // Pad with null-chars if we're "truncating up" $this->content .= str_repeat("\0", $size - $this->size()); } else { $this->content = substr($this->content, 0, $size); } return true; } } class_alias('bovigo\vfs\content\StringBasedFileContent', 'org\bovigo\vfs\content\StringBasedFileContent'); PK 1=Rw^ ^ .gitattributesnu ٘ /docs export-ignore /examples export-ignore /.coveralls.yml export-ignore /.gitattributes export-ignore /.gitignore export-ignore /.travis.yml export-ignore /phpdoc.dist.xml export-ignore PK 1=R*^ phpunit.xml.distnu ٘