Commit 79c10d63 authored by gdd's avatar gdd

Converting config system to PSR-0

parent 1de1df57
This diff is collapsed.
<?php
namespace Drupal\Core\Config;
/**
* @todo
*/
class ConfigException extends Exception {}
\ No newline at end of file
<?php
namespace Drupal\Core\Config;
use Drupal\Core\Config\ConfigException;
/**
* @todo
*/
class ConfigFileStorageException extends ConfigException {}
\ No newline at end of file
<?php
namespace Drupal\Core\Config;
use Drupal\Core\Config\ConfigFileStorageException;
/**
* @todo
*/
class ConfigFileStorageReadException extends ConfigFileStorageException {}
\ No newline at end of file
<?php
namespace Drupal\Core\Config;
use Drupal\Core\Config\ConfigFileStorageException;
/**
* @todo
*/
class ConfigFileStorageSignatureException extends ConfigFileStorageException {}
\ No newline at end of file
<?php
namespace Drupal\Core\Config;
use Drupal\Core\Config\DrupalConfigVerifiedStorageInterface;
/**
* Represents the default configuration storage object.
*/
class DrupalConfig {
/**
* The storage engine to save this config object to.
*
* @var DrupalConfigVerifiedStorageInterface
*/
protected $_verifiedStorage;
protected $data = array();
/**
* Constructs a DrupalConfig object.
*
* @param DrupalConfigVerifiedStorageInterface $verified_storage
* The storage engine where this config object should be saved.
*/
public function __construct(DrupalConfigVerifiedStorageInterface $verified_storage) {
$this->_verifiedStorage = $verified_storage;
$this->read();
}
/**
* Reads config data from the active store into our object.
*/
public function read() {
$active = (array) config_decode($this->_verifiedStorage->read());
foreach ($active as $key => $value) {
$this->set($key, $value);
}
}
/**
* Checks whether a particular value is overridden.
*
* @param $key
* @todo
*
* @return
* @todo
*/
public function isOverridden($key) {
return isset($this->_overrides[$key]);
}
/**
* Returns all values in the config object as a stdClass.
*
* @return object
* All values of $this->data.
*/
public function getData() {
return (object) $this->data;
}
/**
* Gets data from this config object.
*
* @param $key
* A string that maps to a key within the configuration data.
* For instance in the following XML:
*
* <foo>
* <bar>baz</bar>
* </foo>
*
* A key of 'foo.bar' would return the string 'baz'. However
* a key of 'foo' would return array('bar' => 'baz').
*
* If no key is specified, then the entire data array is returned.
*
* @return
* The data that was requested.
*/
public function get($key = '') {
if (empty($key)) {
return $this->data;
}
else {
$parts = explode('.', $key);
if (count($parts) == 1) {
return isset($this->data[$key]) ? $this->data[$key] : NULL;
}
else {
return drupal_array_get_nested_value($this->data, $parts);
}
}
}
/**
* Sets value in this config object.
*
* @param $key
* @todo
* @param $value
* @todo
*/
public function set($key, $value) {
$parts = explode('.', $key);
if (count($parts) == 1) {
$this->data[$key] = $value;
}
else {
drupal_array_set_nested_value($this->data, $parts, $value);
}
}
/**
* Unsets value in this config object.
*
* @param $key
* @todo
*/
public function clear($key) {
$parts = explode('.', $key);
if (count($parts) == 1) {
unset($this->data[$key]);
}
else {
drupal_array_unset_nested_value($this->data, $parts);
}
}
/**
* Saves the configuration object to disk as XML.
*/
public function save() {
$this->_verifiedStorage->write(config_encode($this->data));
}
/**
* Deletes the configuration object on disk.
*/
public function delete() {
$this->_verifiedStorage->delete();
}
}
<?php
namespace Drupal\Core\Config;
use Drupal\Core\Config\DrupalConfigVerifiedStorageInterface;
use Drupal\Core\Config\SignedFileStorage;
/**
* @todo
*/
abstract class DrupalConfigVerifiedStorage implements DrupalConfigVerifiedStorageInterface {
/**
* Implements DrupalConfigVerifiedStorageInterface::__construct().
*/
function __construct($name) {
$this->name = $name;
}
/**
* @todo
*
* @return
* @todo
*/
protected function signedFileStorage() {
return new SignedFileStorage($this->name);
}
/**
* Implements DrupalConfigVerifiedStorageInterface::copyToFile().
*/
public function copyToFile() {
return $this->signedFileStorage()->write($this->read());
}
/**
* Implements DrupalConfigVerifiedStorageInterface::deleteFile().
*/
public function deleteFile() {
return $this->signedFileStorage()->delete();
}
/**
* Implements DrupalConfigVerifiedStorageInterface::copyFromFile().
*/
public function copyFromFile() {
return $this->writeToActive($this->readFromFile());
}
/**
* @todo
*
* @return
* @todo
*/
public function readFromFile() {
return $this->signedFileStorage()->read($this->name);
}
/**
* Implements DrupalConfigVerifiedStorageInterface::isOutOfSync().
*/
public function isOutOfSync() {
return $this->read() !== $this->readFromFile();
}
/**
* Implements DrupalConfigVerifiedStorageInterface::write().
*/
public function write($data) {
$this->writeToActive($data);
$this->copyToFile();
}
/**
* Implements DrupalConfigVerifiedStorageInterface::delete().
*/
public function delete() {
$this->deleteFromActive();
$this->deleteFile();
}
}
<?php
namespace Drupal\Core\Config;
/**
* Defines an interface for verified storage manipulation.
*
* This class allows reading and writing configuration data from/to the
* verified storage and copying to/from the signed file storing the same data.
*/
interface DrupalConfigVerifiedStorageInterface {
/**
* Constructs a verified storage manipulation class.
*
* @param $name
* Lowercase string, the name for the configuration data.
*/
function __construct($name);
/**
* Reads the configuration data from the verified storage.
*/
function read();
/**
* Copies the configuration data from the verified storage into a file.
*/
function copyToFile();
/**
* Copies the configuration data from the file into the verified storage.
*/
function copyFromFile();
/**
* Deletes the configuration data file.
*/
function deleteFile();
/**
* Checks whether the file and the verified storage is in sync.
*
* @return
* TRUE if the file and the verified storage contains the same data, FALSE
* if not.
*/
function isOutOfSync();
/**
* Writes the configuration data into the active storage but not the file.
*
* Use this function if you need to make temporary changes to your
* configuration.
*
* @param $data
* The configuration data to write into active storage.
*/
function writeToActive($data);
/**
* Writes the configuration data into the active storage and the file.
*
* @param $data
* The configuration data to write.
*/
function write($data);
/**
* Gets names starting with this prefix.
*
* @param $prefix
* @todo
*/
static function getNamesWithPrefix($prefix);
}
<?php
namespace Drupal\Core\Config;
use Drupal\Core\Config\DrupalConfigVerifiedStorage;
/**
* Represents an SQL-based configuration storage object.
*/
class DrupalVerifiedStorageSQL extends DrupalConfigVerifiedStorage {
/**
* Overrides DrupalConfigVerifiedStorage::read().
*/
public function read() {
// There are situations, like in the installer, where we may attempt a
// read without actually having the database available. This is a
// workaround and there is probably a better solution to be had at
// some point.
if (!empty($GLOBALS['databases']) && db_table_exists('config')) {
return db_query('SELECT data FROM {config} WHERE name = :name', array(':name' => $this->name))->fetchField();
}
}
/**
* Implements DrupalConfigVerifiedStorageInterface::writeToActive().
*/
public function writeToActive($data) {
return db_merge('config')
->key(array('name' => $this->name))
->fields(array('data' => $data))
->execute();
}
/**
* @todo
*/
public function deleteFromActive() {
db_delete('config')
->condition('name', $this->name)
->execute();
}
/**
* Implements DrupalConfigVerifiedStorageInterface::getNamesWithPrefix().
*/
static public function getNamesWithPrefix($prefix = '') {
return db_query('SELECT name FROM {config} WHERE name LIKE :name', array(':name' => db_like($prefix) . '%'))->fetchCol();
}
}
<?php
namespace Drupal\Core\Config;
/**
* Represents the signed file storage interface.
*
* Classes implementing this interface allow reading and writing configuration
* data to and from disk, while automatically managing and verifying
* cryptographic signatures.
*/
class SignedFileStorage {
/**
* Constructs a SignedFileStorage object.
*
* @param string $name
* The name for the configuration data. Should be lowercase.
*/
public function __construct($name) {
$this->name = $name;
}
/**
* Reads and returns a signed file and its signature.
*
* @return
* An array with "signature" and "data" keys.
*
* @throws
* Exception
*/
protected function readWithSignature() {
// @todo Optimize with explicit offsets?
$content = file_get_contents($this->getFilePath());
if ($content === FALSE) {
throw new Exception('Read file is invalid.');
}
$signature = file_get_contents($this->getFilePath() . '.sig');
if ($signature === FALSE) {
throw new Exception('Signature file is invalid.');
}
return array('data' => $content, 'signature' => $signature);
}
/**
* Checks whether the XML configuration file already exists on disk.
*
* @return
* @todo
*/
protected function exists() {
return file_exists($this->getFilePath());
}
/**
* Returns the path to the XML configuration file.
*
* @return
* @todo
*/
public function getFilePath() {
return config_get_config_directory() . '/' . $this->name . '.xml';
}
/**
* Recreates the signature for the file.
*/
public function resign() {
if ($this->exists()) {
$parts = $this->readWithSignature();
$this->write($parts['data']);
}
}
/**
* Cryptographically verifies the integrity of the configuration file.
*
* @param $contentOnSuccess
* Whether or not to return the contents of the verified configuration file.
*
* @return mixed
* If $contentOnSuccess was TRUE, returns the contents of the verified
* configuration file; otherwise returns TRUE on success. Always returns
* FALSE if the configuration file was not successfully verified.
*/
public function verify($contentOnSuccess = FALSE) {
if ($this->exists()) {
$split = $this->readWithSignature();
$expected_signature = config_sign_data($split['data']);
if ($expected_signature === $split['signature']) {
if ($contentOnSuccess) {
return $split['data'];
}
return TRUE;
}
}
return FALSE;
}
/**
* Writes the contents of the configuration file to disk.
*
* @param $data
* The data to be written to the file.
*
* @throws
* Exception
*
* @todo What format is $data in?
*/
public function write($data) {
$signature = config_sign_data($data);
if (!file_put_contents($this->getFilePath(), $data)) {
throw new Exception('Failed to write configuration file.');
}
if (!file_put_contents($this->getFilePath() . '.sig', $signature)) {
throw new Exception('Failed to write signature file.');
}
}
/**
* Returns the contents of the configuration file.
*
* @return
* @todo
*/
public function read() {
if ($this->exists()) {
$verification = $this->verify(TRUE);
if ($verification === FALSE) {
throw new Exception('Invalid signature in file header.');
}
return $verification;
}
}
/**
* Deletes a configuration file.
*/
public function delete() {
// Needs error handling and etc.
@drupal_unlink($this->getFilePath());
@drupal_unlink($this->getFilePath() . '.sig');
}
}
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment