FileStorage.php 5.11 KB
Newer Older
1 2
<?php

3 4 5 6 7
/**
 * @file
 * Definition of Drupal\Core\Config\FileStorage.
 */

8 9
namespace Drupal\Core\Config;

10 11
use Symfony\Component\Yaml\Dumper;
use Symfony\Component\Yaml\Parser;
12

13
/**
14
 * Defines the file storage controller.
15
 */
16
class FileStorage implements StorageInterface {
17 18

  /**
19
   * Configuration options for this storage controller.
20
   *
21
   * - directory: The filesystem path for configuration objects.
22
   *
23
   * @var array
24
   */
25
  protected $options;
26

27 28 29 30 31 32 33 34 35 36 37 38 39 40
  /**
   * A shared YAML dumper instance.
   *
   * @var Symfony\Component\Yaml\Dumper
   */
  protected $dumper;

  /**
   * A shared YAML parser instance.
   *
   * @var Symfony\Component\Yaml\Parser
   */
  protected $parser;

41
  /**
42
   * Implements Drupal\Core\Config\StorageInterface::__construct().
43
   */
44 45 46
  public function __construct(array $options = array()) {
    if (!isset($options['directory'])) {
      $options['directory'] = config_get_config_directory();
47
    }
48
    $this->options = $options;
49 50 51
  }

  /**
52
   * Returns the path to the configuration file.
53
   *
54 55
   * @return string
   *   The path to the configuration file.
56
   */
57 58
  public function getFilePath($name) {
    return $this->options['directory'] . '/' . $name . '.' . self::getFileExtension();
59 60 61 62 63 64 65 66 67 68
  }

  /**
   * Returns the file extension used by the file storage for all configuration files.
   *
   * @return string
   *   The file extension.
   */
  public static function getFileExtension() {
    return 'yml';
69 70 71
  }

  /**
72
   * Returns whether the configuration file exists.
73
   *
74 75 76
   * @return bool
   *   TRUE if the configuration file exists, FALSE otherwise.
   */
77 78
  public function exists($name) {
    return file_exists($this->getFilePath($name));
79 80 81
  }

  /**
82
   * Implements Drupal\Core\Config\StorageInterface::read().
83
   *
84
   * @throws Symfony\Component\Yaml\Exception\ParseException
85
   */
86 87
  public function read($name) {
    if (!$this->exists($name)) {
88
      return FALSE;
89 90 91 92 93 94
    }
    $data = file_get_contents($this->getFilePath($name));
    // @todo Yaml throws a ParseException on invalid data. Is it expected to be
    //   caught or not?
    $data = $this->decode($data);
    return $data;
95 96 97
  }

  /**
98
   * Implements Drupal\Core\Config\StorageInterface::write().
99
   *
100 101
   * @throws Symfony\Component\Yaml\Exception\DumpException
   * @throws Drupal\Core\Config\StorageException
102
   */
103 104 105 106 107
  public function write($name, array $data) {
    $data = $this->encode($data);
    $status = @file_put_contents($this->getFilePath($name), $data);
    if ($status === FALSE) {
      throw new StorageException('Failed to write configuration file: ' . $this->getFilePath($name));
108
    }
109
    return TRUE;
110 111 112
  }

  /**
113
   * Implements Drupal\Core\Config\StorageInterface::delete().
114
   */
115 116 117 118 119 120 121 122
  public function delete($name) {
    if (!$this->exists($name)) {
      if (!file_exists($this->options['directory'])) {
        throw new StorageException($this->options['directory'] . '/ not found.');
      }
      return FALSE;
    }
    return drupal_unlink($this->getFilePath($name));
123
  }
124

125
  /**
126
   * Implements Drupal\Core\Config\StorageInterface::rename().
127 128 129 130 131 132 133 134 135
   */
  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;
  }

136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159
  /**
   * Gets the YAML dumper instance.
   *
   * @return Symfony\Component\Yaml\Dumper
   */
  protected function getDumper() {
    if (!isset($this->dumper)) {
      $this->dumper = new Dumper();
    }
    return $this->dumper;
  }

  /**
   * Gets the YAML parser instance.
   *
   * @return Symfony\Component\Yaml\Parser
   */
  protected function getParser() {
    if (!isset($this->parser)) {
      $this->parser = new Parser();
    }
    return $this->parser;
  }

160
  /**
161 162 163
   * Implements Drupal\Core\Config\StorageInterface::encode().
   *
   * @throws Symfony\Component\Yaml\Exception\DumpException
164
   */
165
  public function encode($data) {
166 167
    // The level where you switch to inline YAML is set to PHP_INT_MAX to ensure
    // this does not occur.
168
    return $this->getDumper()->dump($data, PHP_INT_MAX);
169 170 171
  }

  /**
172 173 174
   * Implements Drupal\Core\Config\StorageInterface::decode().
   *
   * @throws Symfony\Component\Yaml\Exception\ParseException
175
   */
176 177
  public function decode($raw) {
    $data = $this->getParser()->parse($raw);
178 179 180
    // A simple string is valid YAML for any reason.
    if (!is_array($data)) {
      return FALSE;
181
    }
182
    return $data;
183 184 185
  }

  /**
186
   * Implements Drupal\Core\Config\StorageInterface::listAll().
187
   */
188 189 190 191 192 193 194 195 196 197
  public function listAll($prefix = '') {
    // glob() silently ignores the error of a non-existing search directory,
    // even with the GLOB_ERR flag.
    if (!file_exists($this->options['directory'])) {
      throw new StorageException($this->options['directory'] . '/ not found.');
    }
    $extension = '.' . self::getFileExtension();
    $files = glob($this->options['directory'] . '/' . $prefix . '*' . $extension);
    $clean_name = function ($value) use ($extension) {
      return basename($value, $extension);
198 199
    };
    return array_map($clean_name, $files);
200
  }
201
}