Code Coverage |
||||||||||
Classes and Traits |
Functions and Methods |
Lines |
||||||||
| Total | |
0.00% |
0 / 1 |
|
0.00% |
0 / 19 |
CRAP | |
0.00% |
0 / 152 |
| FileStorage | |
0.00% |
0 / 1 |
|
0.00% |
0 / 19 |
2756 | |
0.00% |
0 / 152 |
| __construct | |
0.00% |
0 / 1 |
2 | |
0.00% |
0 / 3 |
|||
| getFilePath | |
0.00% |
0 / 1 |
2 | |
0.00% |
0 / 2 |
|||
| getFileExtension | |
0.00% |
0 / 1 |
2 | |
0.00% |
0 / 2 |
|||
| ensureStorage | |
0.00% |
0 / 1 |
20 | |
0.00% |
0 / 10 |
|||
| exists | |
0.00% |
0 / 1 |
2 | |
0.00% |
0 / 2 |
|||
| read | |
0.00% |
0 / 1 |
12 | |
0.00% |
0 / 13 |
|||
| readMultiple | |
0.00% |
0 / 1 |
12 | |
0.00% |
0 / 8 |
|||
| write | |
0.00% |
0 / 1 |
20 | |
0.00% |
0 / 20 |
|||
| delete | |
0.00% |
0 / 1 |
12 | |
0.00% |
0 / 9 |
|||
| rename | |
0.00% |
0 / 1 |
6 | |
0.00% |
0 / 6 |
|||
| encode | |
0.00% |
0 / 1 |
2 | |
0.00% |
0 / 2 |
|||
| decode | |
0.00% |
0 / 1 |
6 | |
0.00% |
0 / 6 |
|||
| listAll | |
0.00% |
0 / 1 |
30 | |
0.00% |
0 / 15 |
|||
| deleteAll | |
0.00% |
0 / 1 |
56 | |
0.00% |
0 / 14 |
|||
| createCollection | |
0.00% |
0 / 1 |
2 | |
0.00% |
0 / 5 |
|||
| getCollectionName | |
0.00% |
0 / 1 |
2 | |
0.00% |
0 / 2 |
|||
| getAllCollectionNames | |
0.00% |
0 / 1 |
2 | |
0.00% |
0 / 4 |
|||
| getAllCollectionNamesHelper | |
0.00% |
0 / 1 |
90 | |
0.00% |
0 / 21 |
|||
| getCollectionDirectory | |
0.00% |
0 / 1 |
6 | |
0.00% |
0 / 8 |
|||
| <?php | |
| /** | |
| * @file | |
| * Contains \Drupal\Core\Config\FileStorage. | |
| */ | |
| namespace Drupal\Core\Config; | |
| use Drupal\Component\Serialization\Yaml; | |
| use Drupal\Component\Serialization\Exception\InvalidDataTypeException; | |
| /** | |
| * Defines the file storage. | |
| */ | |
| class FileStorage implements StorageInterface { | |
| /** | |
| * The storage collection. | |
| * | |
| * @var string | |
| */ | |
| protected $collection; | |
| /** | |
| * The filesystem path for configuration objects. | |
| * | |
| * @var string | |
| */ | |
| protected $directory = ''; | |
| /** | |
| * Constructs a new FileStorage. | |
| * | |
| * @param string $directory | |
| * A directory path to use for reading and writing of configuration files. | |
| * @param string $collection | |
| * (optional) The collection to store configuration in. Defaults to the | |
| * default collection. | |
| */ | |
| public function __construct($directory, $collection = StorageInterface::DEFAULT_COLLECTION) { | |
| $this->directory = $directory; | |
| $this->collection = $collection; | |
| } | |
| /** | |
| * Returns the path to the configuration file. | |
| * | |
| * @return string | |
| * The path to the configuration file. | |
| */ | |
| public function getFilePath($name) { | |
| return $this->getCollectionDirectory() . '/' . $name . '.' . static::getFileExtension(); | |
| } | |
| /** | |
| * Returns the file extension used by the file storage for all configuration files. | |
| * | |
| * @return string | |
| * The file extension. | |
| */ | |
| public static function getFileExtension() { | |
| return 'yml'; | |
| } | |
| /** | |
| * Check if the directory exists and create it if not. | |
| */ | |
| protected function ensureStorage() { | |
| $dir = $this->getCollectionDirectory(); | |
| $success = file_prepare_directory($dir, FILE_CREATE_DIRECTORY | FILE_MODIFY_PERMISSIONS); | |
| // Only create .htaccess file in root directory. | |
| if ($dir == $this->directory) { | |
| $success = $success && file_save_htaccess($this->directory, TRUE, TRUE); | |
| } | |
| if (!$success) { | |
| throw new StorageException('Failed to create config directory ' . $dir); | |
| } | |
| return $this; | |
| } | |
| /** | |
| * {@inheritdoc} | |
| */ | |
| public function exists($name) { | |
| return file_exists($this->getFilePath($name)); | |
| } | |
| /** | |
| * Implements Drupal\Core\Config\StorageInterface::read(). | |
| * | |
| * @throws \Drupal\Core\Config\UnsupportedDataTypeConfigException | |
| */ | |
| public function read($name) { | |
| if (!$this->exists($name)) { | |
| return FALSE; | |
| } | |
| $filepath = $this->getFilePath($name); | |
| $data = file_get_contents($filepath); | |
| try { | |
| $data = $this->decode($data); | |
| } | |
| catch (InvalidDataTypeException $e) { | |
| throw new UnsupportedDataTypeConfigException('Invalid data type in config ' . $name . ', found in file' . $filepath . ' : ' . $e->getMessage()); | |
| } | |
| return $data; | |
| } | |
| /** | |
| * {@inheritdoc} | |
| */ | |
| public function readMultiple(array $names) { | |
| $list = array(); | |
| foreach ($names as $name) { | |
| if ($data = $this->read($name)) { | |
| $list[$name] = $data; | |
| } | |
| } | |
| return $list; | |
| } | |
| /** | |
| * {@inheritdoc} | |
| */ | |
| public function write($name, array $data) { | |
| try { | |
| $data = $this->encode($data); | |
| } | |
| catch (InvalidDataTypeException $e) { | |
| throw new StorageException("Invalid data type in config $name: {$e->getMessage()}"); | |
| } | |
| $target = $this->getFilePath($name); | |
| $status = @file_put_contents($target, $data); | |
| if ($status === FALSE) { | |
| // Try to make sure the directory exists and try writing again. | |
| $this->ensureStorage(); | |
| $status = @file_put_contents($target, $data); | |
| } | |
| if ($status === FALSE) { | |
| throw new StorageException('Failed to write configuration file: ' . $this->getFilePath($name)); | |
| } | |
| else { | |
| drupal_chmod($target); | |
| } | |
| return TRUE; | |
| } | |
| /** | |
| * {@inheritdoc} | |
| */ | |
| public function delete($name) { | |
| if (!$this->exists($name)) { | |
| $dir = $this->getCollectionDirectory(); | |
| if (!file_exists($dir)) { | |
| throw new StorageException($dir . '/ not found.'); | |
| } | |
| return FALSE; | |
| } | |
| return drupal_unlink($this->getFilePath($name)); | |
| } | |
| /** | |
| * {@inheritdoc} | |
| */ | |
| public function rename($name, $new_name) { | |
| $status = @rename($this->getFilePath($name), $this->getFilePath($new_name)); | |
| if ($status === FALSE) { | |
| throw new StorageException('Failed to rename configuration file from: ' . $this->getFilePath($name) . ' to: ' . $this->getFilePath($new_name)); | |
| } | |
| return TRUE; | |
| } | |
| /** | |
| * {@inheritdoc} | |
| */ | |
| public function encode($data) { | |
| return Yaml::encode($data); | |
| } | |
| /** | |
| * {@inheritdoc} | |
| */ | |
| public function decode($raw) { | |
| $data = Yaml::decode($raw); | |
| // A simple string is valid YAML for any reason. | |
| if (!is_array($data)) { | |
| return FALSE; | |
| } | |
| return $data; | |
| } | |
| /** | |
| * {@inheritdoc} | |
| */ | |
| public function listAll($prefix = '') { | |
| $dir = $this->getCollectionDirectory(); | |
| if (!is_dir($dir)) { | |
| return array(); | |
| } | |
| $extension = '.' . static::getFileExtension(); | |
| // glob() directly calls into libc glob(), which is not aware of PHP stream | |
| // wrappers. Same for \GlobIterator (which additionally requires an absolute | |
| // realpath() on Windows). | |
| // @see https://github.com/mikey179/vfsStream/issues/2 | |
| $files = scandir($dir); | |
| $names = array(); | |
| $pattern = '/^' . preg_quote($prefix, '/') . '.*' . preg_quote($extension, '/') . '$/'; | |
| foreach ($files as $file) { | |
| if ($file[0] !== '.' && preg_match($pattern, $file)) { | |
| $names[] = basename($file, $extension); | |
| } | |
| } | |
| return $names; | |
| } | |
| /** | |
| * {@inheritdoc} | |
| */ | |
| public function deleteAll($prefix = '') { | |
| $success = TRUE; | |
| $files = $this->listAll($prefix); | |
| foreach ($files as $name) { | |
| if (!$this->delete($name) && $success) { | |
| $success = FALSE; | |
| } | |
| } | |
| if ($success && $this->collection != StorageInterface::DEFAULT_COLLECTION) { | |
| // Remove empty directories. | |
| if (!(new \FilesystemIterator($this->getCollectionDirectory()))->valid()) { | |
| drupal_rmdir($this->getCollectionDirectory()); | |
| } | |
| } | |
| return $success; | |
| } | |
| /** | |
| * {@inheritdoc} | |
| */ | |
| public function createCollection($collection) { | |
| return new static( | |
| $this->directory, | |
| $collection | |
| ); | |
| } | |
| /** | |
| * {@inheritdoc} | |
| */ | |
| public function getCollectionName() { | |
| return $this->collection; | |
| } | |
| /** | |
| * {@inheritdoc} | |
| */ | |
| public function getAllCollectionNames() { | |
| $collections = $this->getAllCollectionNamesHelper($this->directory); | |
| sort($collections); | |
| return $collections; | |
| } | |
| /** | |
| * Helper function for getAllCollectionNames(). | |
| * | |
| * If the file storage has the following subdirectory structure: | |
| * ./another_collection/one | |
| * ./another_collection/two | |
| * ./collection/sub/one | |
| * ./collection/sub/two | |
| * this function will return: | |
| * @code | |
| * array( | |
| * 'another_collection.one', | |
| * 'another_collection.two', | |
| * 'collection.sub.one', | |
| * 'collection.sub.two', | |
| * ); | |
| * @endcode | |
| * | |
| * @param string $directory | |
| * The directory to check for sub directories. This allows this | |
| * function to be used recursively to discover all the collections in the | |
| * storage. | |
| * | |
| * @return array | |
| * A list of collection names contained within the provided directory. | |
| */ | |
| protected function getAllCollectionNamesHelper($directory) { | |
| $collections = array(); | |
| $pattern = '/\.' . preg_quote($this->getFileExtension(), '/') . '$/'; | |
| foreach (new \DirectoryIterator($directory) as $fileinfo) { | |
| if ($fileinfo->isDir() && !$fileinfo->isDot()) { | |
| $collection = $fileinfo->getFilename(); | |
| // Recursively call getAllCollectionNamesHelper() to discover if there | |
| // are subdirectories. Subdirectories represent a dotted collection | |
| // name. | |
| $sub_collections = $this->getAllCollectionNamesHelper($directory . '/' . $collection); | |
| if (!empty($sub_collections)) { | |
| // Build up the collection name by concatenating the subdirectory | |
| // names with the current directory name. | |
| foreach ($sub_collections as $sub_collection) { | |
| $collections[] = $collection . '.' . $sub_collection; | |
| } | |
| } | |
| // Check that the collection is valid by searching it for configuration | |
| // objects. A directory without any configuration objects is not a valid | |
| // collection. | |
| // @see \Drupal\Core\Config\FileStorage::listAll() | |
| foreach (scandir($directory . '/' . $collection) as $file) { | |
| if ($file[0] !== '.' && preg_match($pattern, $file)) { | |
| $collections[] = $collection; | |
| break; | |
| } | |
| } | |
| } | |
| } | |
| return $collections; | |
| } | |
| /** | |
| * Gets the directory for the collection. | |
| * | |
| * @return string | |
| * The directory for the collection. | |
| */ | |
| protected function getCollectionDirectory() { | |
| if ($this->collection == StorageInterface::DEFAULT_COLLECTION) { | |
| $dir = $this->directory; | |
| } | |
| else { | |
| $dir = $this->directory . '/' . str_replace('.', '/', $this->collection); | |
| } | |
| return $dir; | |
| } | |
| } |