class FileStorage

Same name in this branch
  1. 10 core/modules/file/src/FileStorage.php \Drupal\file\FileStorage
  2. 10 core/lib/Drupal/Core/Config/FileStorage.php \Drupal\Core\Config\FileStorage
Same name and namespace in other branches
  1. 9 core/modules/file/src/FileStorage.php \Drupal\file\FileStorage
  2. 9 core/lib/Drupal/Core/Config/FileStorage.php \Drupal\Core\Config\FileStorage
  3. 9 core/lib/Drupal/Component/PhpStorage/FileStorage.php \Drupal\Component\PhpStorage\FileStorage
  4. 8.9.x core/modules/file/src/FileStorage.php \Drupal\file\FileStorage
  5. 8.9.x core/lib/Drupal/Core/Config/FileStorage.php \Drupal\Core\Config\FileStorage
  6. 8.9.x core/lib/Drupal/Component/PhpStorage/FileStorage.php \Drupal\Component\PhpStorage\FileStorage
  7. 11.x core/modules/file/src/FileStorage.php \Drupal\file\FileStorage
  8. 11.x core/lib/Drupal/Core/Config/FileStorage.php \Drupal\Core\Config\FileStorage
  9. 11.x core/lib/Drupal/Component/PhpStorage/FileStorage.php \Drupal\Component\PhpStorage\FileStorage

Stores the code as regular PHP files.

Hierarchy

Expanded class hierarchy of FileStorage

2 files declare their use of FileStorage
FileStorageReadOnlyTest.php in core/tests/Drupal/Tests/Component/PhpStorage/FileStorageReadOnlyTest.php
FileStorageTest.php in core/tests/Drupal/Tests/Component/PhpStorage/FileStorageTest.php

File

core/lib/Drupal/Component/PhpStorage/FileStorage.php, line 10

Namespace

Drupal\Component\PhpStorage
View source
class FileStorage implements PhpStorageInterface {
    
    /**
     * The directory where the files should be stored.
     *
     * @var string
     */
    protected $directory;
    
    /**
     * Constructs this FileStorage object.
     *
     * @param array $configuration
     *   An associative array, containing at least these two keys:
     *   - directory: The directory where the files should be stored.
     *   - bin: The storage bin. Multiple storage objects can be instantiated with
     *     the same configuration, but for different bins..
     */
    public function __construct(array $configuration) {
        $this->directory = $configuration['directory'] . '/' . $configuration['bin'];
    }
    
    /**
     * {@inheritdoc}
     */
    public function exists($name) {
        return file_exists($this->getFullPath($name));
    }
    
    /**
     * {@inheritdoc}
     */
    public function load($name) {
        // The FALSE returned on failure is enough for the caller to handle this,
        // we do not want a warning too.
        return @(include_once $this->getFullPath($name)) !== FALSE;
    }
    
    /**
     * {@inheritdoc}
     */
    public function save($name, $code) {
        $path = $this->getFullPath($name);
        $directory = dirname($path);
        $this->ensureDirectory($directory);
        return (bool) file_put_contents($path, $code);
    }
    
    /**
     * Ensures the directory exists, has the right permissions, and a .htaccess.
     *
     * For compatibility with open_basedir, the requested directory is created
     * using a recursion logic that is based on the relative directory path/tree:
     * It works from the end of the path recursively back towards the root
     * directory, until an existing parent directory is found. From there, the
     * subdirectories are created.
     *
     * @param string $directory
     *   The directory path.
     * @param int $mode
     *   The mode, permissions, the directory should have.
     */
    protected function ensureDirectory($directory, $mode = 0777) {
        if ($this->createDirectory($directory, $mode)) {
            FileSecurity::writeHtaccess($directory);
        }
    }
    
    /**
     * Ensures the requested directory exists and has the right permissions.
     *
     * For compatibility with open_basedir, the requested directory is created
     * using a recursion logic that is based on the relative directory path/tree:
     * It works from the end of the path recursively back towards the root
     * directory, until an existing parent directory is found. From there, the
     * subdirectories are created.
     *
     * @param string $directory
     *   The directory path.
     * @param int $mode
     *   The mode, permissions, the directory should have.
     *
     * @return bool
     *   TRUE if the directory exists or has been created, FALSE otherwise.
     */
    protected function createDirectory($directory, $mode = 0777) {
        // If the directory exists already, there's nothing to do.
        if (is_dir($directory)) {
            return TRUE;
        }
        // If the parent directory doesn't exist, try to create it.
        $parent_exists = is_dir($parent = dirname($directory));
        if (!$parent_exists) {
            $parent_exists = $this->createDirectory($parent, $mode);
        }
        // If parent exists, try to create the directory and ensure to set its
        // permissions, because mkdir() obeys the umask of the current process.
        if ($parent_exists) {
            // We hide warnings and ignore the return because there may have been a
            // race getting here and the directory could already exist.
            @mkdir($directory);
            // Only try to chmod() if the subdirectory could be created.
            if (is_dir($directory)) {
                // Avoid writing permissions if possible.
                if (fileperms($directory) !== $mode) {
                    return chmod($directory, $mode);
                }
                return TRUE;
            }
            else {
                // Something failed and the directory doesn't exist.
                trigger_error('mkdir(): Permission Denied', E_USER_WARNING);
            }
        }
        return FALSE;
    }
    
    /**
     * {@inheritdoc}
     */
    public function delete($name) {
        $path = $this->getFullPath($name);
        if (file_exists($path)) {
            return $this->unlink($path);
        }
        return FALSE;
    }
    
    /**
     * {@inheritdoc}
     */
    public function getFullPath($name) {
        return $this->directory . '/' . $name;
    }
    
    /**
     * {@inheritdoc}
     */
    public function writeable() {
        @trigger_error(__METHOD__ . '() is deprecated in drupal:10.1.0 and will be removed from drupal:11.0.0. There is no replacement. See https://www.drupal.org/node/3155413', E_USER_DEPRECATED);
        return TRUE;
    }
    
    /**
     * {@inheritdoc}
     */
    public function deleteAll() {
        return $this->unlink($this->directory);
    }
    
    /**
     * Deletes files and/or directories in the specified path.
     *
     * If the specified path is a directory the method will
     * call itself recursively to process the contents. Once the contents have
     * been removed the directory will also be removed.
     *
     * @param string $path
     *   A string containing either a file or directory path.
     *
     * @return bool
     *   TRUE for success or if path does not exist, FALSE in the event of an
     *   error.
     */
    protected function unlink($path) {
        if (file_exists($path)) {
            if (is_dir($path)) {
                // Ensure the folder is writable.
                @chmod($path, 0777);
                foreach (new \DirectoryIterator($path) as $fileinfo) {
                    if (!$fileinfo->isDot()) {
                        $this->unlink($fileinfo->getPathName());
                    }
                }
                return @rmdir($path);
            }
            // Windows needs the file to be writable.
            @chmod($path, 0700);
            return @unlink($path);
        }
        // If there's nothing to delete return TRUE anyway.
        return TRUE;
    }
    
    /**
     * {@inheritdoc}
     */
    public function listAll() {
        $names = [];
        if (file_exists($this->directory)) {
            foreach (new \DirectoryIterator($this->directory) as $fileinfo) {
                if (!$fileinfo->isDot()) {
                    $name = $fileinfo->getFilename();
                    if ($name != '.htaccess') {
                        $names[] = $name;
                    }
                }
            }
        }
        return $names;
    }
    
    /**
     * {@inheritdoc}
     */
    public function garbageCollection() {
    }

}

Members

Title Sort descending Modifiers Object type Summary Overriden Title Overrides
FileStorage::$directory protected property The directory where the files should be stored.
FileStorage::createDirectory protected function Ensures the requested directory exists and has the right permissions.
FileStorage::delete public function Deletes PHP code from storage. Overrides PhpStorageInterface::delete 1
FileStorage::deleteAll public function Removes all files in this bin. Overrides PhpStorageInterface::deleteAll
FileStorage::ensureDirectory protected function Ensures the directory exists, has the right permissions, and a .htaccess.
FileStorage::exists public function Checks whether the PHP code exists in storage. Overrides PhpStorageInterface::exists 1
FileStorage::garbageCollection public function Performs garbage collection on the storage. Overrides PhpStorageInterface::garbageCollection 1
FileStorage::getFullPath public function Gets the full file path. Overrides PhpStorageInterface::getFullPath 1
FileStorage::listAll public function Lists all the files in the storage. Overrides PhpStorageInterface::listAll
FileStorage::load public function Loads PHP code from storage. Overrides PhpStorageInterface::load 1
FileStorage::save public function Saves PHP code to storage. Overrides PhpStorageInterface::save 1
FileStorage::unlink protected function Deletes files and/or directories in the specified path.
FileStorage::writeable public function Whether this is a writable storage. Overrides PhpStorageInterface::writeable
FileStorage::__construct public function Constructs this FileStorage object. 1

Buggy or inaccurate documentation? Please file an issue. Need support? Need help programming? Connect with the Drupal community.