diff --git a/core/core.services.yml b/core/core.services.yml index 025368ec3c8b237ae7d6e0f467ec8671d719e590..3f7c394aec5e7bb3e64f73ae5a06f6b52a2c5de6 100644 --- a/core/core.services.yml +++ b/core/core.services.yml @@ -127,15 +127,23 @@ services: arguments: ['@service_container', '@settings'] keyvalue.database: class: Drupal\Core\KeyValueStore\KeyValueDatabaseFactory - arguments: ['@database'] + arguments: ['@serialization.phpserialize', '@database'] keyvalue.expirable: class: Drupal\Core\KeyValueStore\KeyValueExpirableFactory arguments: ['@service_container', '@settings'] keyvalue.expirable.database: class: Drupal\Core\KeyValueStore\KeyValueDatabaseExpirableFactory + arguments: ['@serialization.phpserialize', '@database'] tags: - { name: needs_destruction } - arguments: ['@database'] + + serialization.json: + class: Drupal\Component\Serialization\Json + serialization.phpserialize: + class: Drupal\Component\Serialization\PhpSerialize + serialization.yaml: + class: Drupal\Component\Serialization\Yaml + settings: class: Drupal\Component\Utility\Settings factory_class: Drupal\Component\Utility\Settings @@ -288,7 +296,7 @@ services: arguments: ['@database'] user.tempstore: class: Drupal\user\TempStoreFactory - arguments: ['@database', '@lock'] + arguments: ['@serialization.phpserialize', '@database', '@lock'] router.request_context: class: Symfony\Component\Routing\RequestContext tags: diff --git a/core/lib/Drupal/Component/Serialization/Json.php b/core/lib/Drupal/Component/Serialization/Json.php index 91081d7e46dcba53800f086af614e9933f6a387d..3349a3ae173cfb47212f4e57bba6a1b5af9d48c1 100644 --- a/core/lib/Drupal/Component/Serialization/Json.php +++ b/core/lib/Drupal/Component/Serialization/Json.php @@ -8,44 +8,32 @@ namespace Drupal\Component\Serialization; /** - * Provides helpers for dealing with json. - * - * @ingroup utility + * Default serialization for JSON. */ -class Json { +class Json implements SerializationInterface { /** - * Converts a PHP variable into its JavaScript equivalent. + * {@inheritdoc} * - * We use HTML-safe strings, with several characters escaped. - * - * @param mixed $variable - * The variable to encode. - * - * @return string - * Returns the encoded variable. - * - * @see drupal_json_decode() - * @ingroup php_wrappers + * Uses HTML-safe strings, with several characters escaped. */ public static function encode($variable) { - // Encode <, >, ', &, and " using the json_encode() options parameter. + // Encode <, >, ', &, and ". return json_encode($variable, JSON_HEX_TAG | JSON_HEX_APOS | JSON_HEX_AMP | JSON_HEX_QUOT); } /** - * Converts an HTML-safe JSON string into its PHP equivalent. - * - * @param string $string - * The string to decode. - * - * @return mixed - * Returns the decoded string. - * - * @ingroup php_wrappers + * {@inheritdoc} */ public static function decode($string) { return json_decode($string, TRUE); } + /** + * {@inheritdoc} + */ + public static function getFileExtension() { + return 'json'; + } + } diff --git a/core/lib/Drupal/Component/Serialization/PhpSerialize.php b/core/lib/Drupal/Component/Serialization/PhpSerialize.php new file mode 100644 index 0000000000000000000000000000000000000000..a6f11fcfb570be854bf990a55aa84d16147e4474 --- /dev/null +++ b/core/lib/Drupal/Component/Serialization/PhpSerialize.php @@ -0,0 +1,36 @@ +<?php + +/** + * @file + * Contains \Drupal\Component\Serialization\PhpSerialize. + */ + +namespace Drupal\Component\Serialization; + +/** + * Default serialization for serialized PHP. + */ +class PhpSerialize implements SerializationInterface { + + /** + * {@inheritdoc} + */ + public static function encode($data) { + return serialize($data); + } + + /** + * {@inheritdoc} + */ + public static function decode($raw) { + return unserialize($raw); + } + + /** + * {@inheritdoc} + */ + public static function getFileExtension() { + return 'serialized'; + } + +} diff --git a/core/lib/Drupal/Core/KeyValueStore/DatabaseStorage.php b/core/lib/Drupal/Core/KeyValueStore/DatabaseStorage.php index 1464186339a74a6ca03dad926f1da79cc711cf02..d9893644f968a49929c9543643f03c59a3c513a0 100644 --- a/core/lib/Drupal/Core/KeyValueStore/DatabaseStorage.php +++ b/core/lib/Drupal/Core/KeyValueStore/DatabaseStorage.php @@ -7,6 +7,7 @@ namespace Drupal\Core\KeyValueStore; +use Drupal\Component\Serialization\SerializationInterface; use Drupal\Core\Database\Query\Merge; use Drupal\Core\Database\Connection; @@ -18,6 +19,13 @@ */ class DatabaseStorage extends StorageBase { + /** + * The serialization class to use. + * + * @var \Drupal\Component\Serialization\SerializationInterface + */ + protected $serializer; + /** * The database connection. * @@ -37,11 +45,16 @@ class DatabaseStorage extends StorageBase { * * @param string $collection * The name of the collection holding key and value pairs. + * @param \Drupal\Component\Serialization\SerializationInterface $serializer + * The serialization class to use. + * @param \Drupal\Core\Database\Connection $connection + * The database connection to use. * @param string $table * The name of the SQL table to use, defaults to key_value. */ - public function __construct($collection, Connection $connection, $table = 'key_value') { + public function __construct($collection, SerializationInterface $serializer, Connection $connection, $table = 'key_value') { parent::__construct($collection); + $this->serializer = $serializer; $this->connection = $connection; $this->table = $table; } @@ -65,7 +78,7 @@ public function getMultiple(array $keys) { $result = $this->connection->query('SELECT name, value FROM {' . $this->connection->escapeTable($this->table) . '} WHERE name IN (:keys) AND collection = :collection', array(':keys' => $keys, ':collection' => $this->collection))->fetchAllAssoc('name'); foreach ($keys as $key) { if (isset($result[$key])) { - $values[$key] = unserialize($result[$key]->value); + $values[$key] = $this->serializer->decode($result[$key]->value); } } } @@ -86,7 +99,7 @@ public function getAll() { foreach ($result as $item) { if ($item) { - $values[$item->name] = unserialize($item->value); + $values[$item->name] = $this->serializer->decode($item->value); } } return $values; @@ -101,7 +114,7 @@ public function set($key, $value) { 'name' => $key, 'collection' => $this->collection, )) - ->fields(array('value' => serialize($value))) + ->fields(array('value' => $this->serializer->encode($value))) ->execute(); } @@ -113,7 +126,7 @@ public function setIfNotExists($key, $value) { ->insertFields(array( 'collection' => $this->collection, 'name' => $key, - 'value' => serialize($value), + 'value' => $this->serializer->encode($value), )) ->condition('collection', $this->collection) ->condition('name', $key) diff --git a/core/lib/Drupal/Core/KeyValueStore/DatabaseStorageExpirable.php b/core/lib/Drupal/Core/KeyValueStore/DatabaseStorageExpirable.php index fb0b8b0a7ca4eb1a9cf8041501396ecb1d92b9d0..3263a47e0673edd33517e2a3356950cff3a2ec3d 100644 --- a/core/lib/Drupal/Core/KeyValueStore/DatabaseStorageExpirable.php +++ b/core/lib/Drupal/Core/KeyValueStore/DatabaseStorageExpirable.php @@ -7,6 +7,7 @@ namespace Drupal\Core\KeyValueStore; +use Drupal\Component\Serialization\SerializationInterface; use Drupal\Core\DestructableInterface; use Drupal\Core\Database\Connection; use Drupal\Core\Database\Query\Merge; @@ -19,13 +20,6 @@ */ class DatabaseStorageExpirable extends DatabaseStorage implements KeyValueStoreExpirableInterface, DestructableInterface { - /** - * The connection object for this storage. - * - * @var \Drupal\Core\Database\Connection - */ - protected $connection; - /** * Flag indicating whether garbage collection should be performed. * @@ -44,16 +38,15 @@ class DatabaseStorageExpirable extends DatabaseStorage implements KeyValueStoreE * * @param string $collection * The name of the collection holding key and value pairs. - * @param array $options - * An associative array of options for the key/value storage collection. - * Keys used: - * - connection: (optional) The database connection to use for storing the - * data. Defaults to the current connection. - * - table: (optional) The name of the SQL table to use. Defaults to - * key_value_expire. + * @param \Drupal\Component\Serialization\SerializationInterface $serializer + * The serialization class to use. + * @param \Drupal\Core\Database\Connection $connection + * The database connection to use. + * @param string $table + * The name of the SQL table to use, defaults to key_value_expire. */ - public function __construct($collection, Connection $connection, $table = 'key_value_expire') { - parent::__construct($collection, $connection, $table); + public function __construct($collection, SerializationInterface $serializer, Connection $connection, $table = 'key_value_expire') { + parent::__construct($collection, $serializer, $connection, $table); } /** @@ -78,7 +71,7 @@ public function getMultiple(array $keys) { ':keys' => $keys, ':collection' => $this->collection, ))->fetchAllKeyed(); - return array_map('unserialize', $values); + return array_map(array($this->serializer, 'decode'), $values); } /** @@ -91,7 +84,7 @@ public function getAll() { ':collection' => $this->collection, ':now' => REQUEST_TIME ))->fetchAllKeyed(); - return array_map('unserialize', $values); + return array_map(array($this->serializer, 'decode'), $values); } /** @@ -107,7 +100,7 @@ function setWithExpire($key, $value, $expire) { 'collection' => $this->collection, )) ->fields(array( - 'value' => serialize($value), + 'value' => $this->serializer->encode($value), 'expire' => REQUEST_TIME + $expire, )) ->execute(); @@ -124,7 +117,7 @@ function setWithExpireIfNotExists($key, $value, $expire) { ->insertFields(array( 'collection' => $this->collection, 'name' => $key, - 'value' => serialize($value), + 'value' => $this->serializer->encode($value), 'expire' => REQUEST_TIME + $expire, )) ->condition('collection', $this->collection) diff --git a/core/lib/Drupal/Core/KeyValueStore/KeyValueDatabaseExpirableFactory.php b/core/lib/Drupal/Core/KeyValueStore/KeyValueDatabaseExpirableFactory.php index 9000e20c15e1125937a75f7d546364e3e8e27417..5ff8ae6f503f9536094610067b6aae5f48b15b93 100644 --- a/core/lib/Drupal/Core/KeyValueStore/KeyValueDatabaseExpirableFactory.php +++ b/core/lib/Drupal/Core/KeyValueStore/KeyValueDatabaseExpirableFactory.php @@ -7,6 +7,7 @@ namespace Drupal\Core\KeyValueStore; +use Drupal\Component\Serialization\SerializationInterface; use Drupal\Core\DestructableInterface; use Drupal\Core\Database\Connection; @@ -22,6 +23,13 @@ class KeyValueDatabaseExpirableFactory implements KeyValueExpirableFactoryInterf */ protected $storages = array(); + /** + * The serialization class to use. + * + * @var \Drupal\Component\Serialization\SerializationInterface + */ + protected $serializer; + /** * The database connection. * @@ -32,11 +40,13 @@ class KeyValueDatabaseExpirableFactory implements KeyValueExpirableFactoryInterf /** * Constructs this factory object. * - * + * @param \Drupal\Component\Serialization\SerializationInterface $serializer + * The serialization class to use. * @param \Drupal\Core\Database\Connection $connection * The Connection object containing the key-value tables. */ - function __construct(Connection $connection) { + function __construct(SerializationInterface $serializer, Connection $connection) { + $this->serializer = $serializer; $this->connection = $connection; } @@ -45,7 +55,7 @@ function __construct(Connection $connection) { */ public function get($collection) { if (!isset($this->storages[$collection])) { - $this->storages[$collection] = new DatabaseStorageExpirable($collection, $this->connection); + $this->storages[$collection] = new DatabaseStorageExpirable($collection, $this->serializer, $this->connection); } return $this->storages[$collection]; } diff --git a/core/lib/Drupal/Core/KeyValueStore/KeyValueDatabaseFactory.php b/core/lib/Drupal/Core/KeyValueStore/KeyValueDatabaseFactory.php index 1a840b39c4000aafa40c1441ed85cdd595c150f4..391b08edd4a1631c9d1b57948cd636c6054ae609 100644 --- a/core/lib/Drupal/Core/KeyValueStore/KeyValueDatabaseFactory.php +++ b/core/lib/Drupal/Core/KeyValueStore/KeyValueDatabaseFactory.php @@ -6,6 +6,8 @@ */ namespace Drupal\Core\KeyValueStore; + +use Drupal\Component\Serialization\SerializationInterface; use Drupal\Core\Database\Connection; use Drupal\Core\Database\Database; @@ -15,13 +17,29 @@ class KeyValueDatabaseFactory implements KeyValueFactoryInterface { /** - * Constructs this factory object. + * The serialization class to use. + * + * @var \Drupal\Component\Serialization\SerializationInterface + */ + protected $serializer; + + /** + * The database connection to use. * + * @var \Drupal\Core\Database\Connection + */ + protected $connection; + + /** + * Constructs this factory object. * + * @param \Drupal\Component\Serialization\SerializationInterface $serializer + * The serialization class to use. * @param \Drupal\Core\Database\Connection $connection * The Connection object containing the key-value tables. */ - function __construct(Connection $connection) { + function __construct(SerializationInterface $serializer, Connection $connection) { + $this->serializer = $serializer; $this->connection = $connection; } @@ -29,6 +47,6 @@ function __construct(Connection $connection) { * {@inheritdoc} */ public function get($collection) { - return new DatabaseStorage($collection, $this->connection); + return new DatabaseStorage($collection, $this->serializer, $this->connection); } } diff --git a/core/modules/system/lib/Drupal/system/Tests/KeyValueStore/DatabaseStorageExpirableTest.php b/core/modules/system/lib/Drupal/system/Tests/KeyValueStore/DatabaseStorageExpirableTest.php index 5f7365d8168f2040cf5432d96e07da6baeef6518..ed4236bc048329f80f942b2ce8d88fef3b723c9e 100644 --- a/core/modules/system/lib/Drupal/system/Tests/KeyValueStore/DatabaseStorageExpirableTest.php +++ b/core/modules/system/lib/Drupal/system/Tests/KeyValueStore/DatabaseStorageExpirableTest.php @@ -35,7 +35,10 @@ protected function setUp() { ->addArgument('default'); $this->container ->register('keyvalue.expirable.database', 'Drupal\Core\KeyValueStore\KeyValueDatabaseExpirableFactory') + ->addArgument(new Reference('serialization.phpserialize')) ->addArgument(new Reference('database')); + $this->container + ->register('serialization.phpserialize', 'Drupal\Component\Serialization\PhpSerialize'); $this->settingsSet('keyvalue_expirable_default', 'keyvalue.expirable.database'); } diff --git a/core/modules/system/lib/Drupal/system/Tests/KeyValueStore/DatabaseStorageTest.php b/core/modules/system/lib/Drupal/system/Tests/KeyValueStore/DatabaseStorageTest.php index ad286d62c2800312d9b03b1c0ef0f46cc054f039..2254501df572d37e27e36fa6bfe93bd2bf7a3a2f 100644 --- a/core/modules/system/lib/Drupal/system/Tests/KeyValueStore/DatabaseStorageTest.php +++ b/core/modules/system/lib/Drupal/system/Tests/KeyValueStore/DatabaseStorageTest.php @@ -34,7 +34,10 @@ protected function setUp() { ->addArgument('default'); $this->container ->register('keyvalue.database', 'Drupal\Core\KeyValueStore\KeyValueDatabaseFactory') + ->addArgument(new Reference('serialization.phpserialize')) ->addArgument(new Reference('database')); + $this->container + ->register('serialization.phpserialize', 'Drupal\Component\Serialization\PhpSerialize'); $this->settingsSet('keyvalue_default', 'keyvalue.database'); } diff --git a/core/modules/system/lib/Drupal/system/Tests/KeyValueStore/GarbageCollectionTest.php b/core/modules/system/lib/Drupal/system/Tests/KeyValueStore/GarbageCollectionTest.php index 2835a470c38a159068133bd05d31246bf12b784f..e583e75cb1ee45a4bcabafe87eebd9113260bfbc 100644 --- a/core/modules/system/lib/Drupal/system/Tests/KeyValueStore/GarbageCollectionTest.php +++ b/core/modules/system/lib/Drupal/system/Tests/KeyValueStore/GarbageCollectionTest.php @@ -7,6 +7,7 @@ namespace Drupal\system\Tests\KeyValueStore; +use Drupal\Component\Serialization\PhpSerialize; use Drupal\Core\Database\Database; use Drupal\Core\KeyValueStore\DatabaseStorageExpirable; use Drupal\simpletest\UnitTestBase; @@ -41,7 +42,7 @@ protected function tearDown() { */ public function testGarbageCollection() { $collection = $this->randomName(); - $store = new DatabaseStorageExpirable($collection, Database::getConnection()); + $store = new DatabaseStorageExpirable($collection, new PhpSerialize(), Database::getConnection()); // Insert some items and confirm that they're set. for ($i = 0; $i <= 3; $i++) { diff --git a/core/modules/user/lib/Drupal/user/TempStoreFactory.php b/core/modules/user/lib/Drupal/user/TempStoreFactory.php index 28d4147b638df71a1d11b0a139d09b56fc9dcc2f..c93cb58ecded193a147b4320fcbecd8519fc4b09 100644 --- a/core/modules/user/lib/Drupal/user/TempStoreFactory.php +++ b/core/modules/user/lib/Drupal/user/TempStoreFactory.php @@ -7,6 +7,7 @@ namespace Drupal\user; +use Drupal\Component\Serialization\SerializationInterface; use Drupal\Core\Database\Connection; use Drupal\Core\KeyValueStore\DatabaseStorageExpirable; use Drupal\Core\Lock\LockBackendInterface; @@ -16,6 +17,13 @@ */ class TempStoreFactory { + /** + * The serialization class to use. + * + * @var \Drupal\Component\Serialization\SerializationInterface + */ + protected $serializer; + /** * The connection object used for this data. * @@ -33,12 +41,15 @@ class TempStoreFactory { /** * Constructs a Drupal\user\TempStoreFactory object. * + * @param \Drupal\Component\Serialization\SerializationInterface $serializer + * The serialization class to use. * @param \Drupal\Core\Database\Connection $connection * The connection object used for this data. * @param \Drupal\Core\Lock\LockBackendInterface $lockBackend * The lock object used for this data. */ - function __construct(Connection $connection, LockBackendInterface $lockBackend) { + function __construct(SerializationInterface $serializer, Connection $connection, LockBackendInterface $lockBackend) { + $this->serializer = $serializer; $this->connection = $connection; $this->lockBackend = $lockBackend; } @@ -65,7 +76,7 @@ function get($collection, $owner = NULL) { } // Store the data for this collection in the database. - $storage = new DatabaseStorageExpirable($collection, $this->connection); + $storage = new DatabaseStorageExpirable($collection, $this->serializer, $this->connection); return new TempStore($storage, $this->lockBackend, $owner); } diff --git a/core/modules/user/lib/Drupal/user/Tests/TempStoreDatabaseTest.php b/core/modules/user/lib/Drupal/user/Tests/TempStoreDatabaseTest.php index 04378376a2a27f238a05fb91617bf09012e04e2e..1c83eb865be23e062cc3d845c69b900d48dbe20e 100644 --- a/core/modules/user/lib/Drupal/user/Tests/TempStoreDatabaseTest.php +++ b/core/modules/user/lib/Drupal/user/Tests/TempStoreDatabaseTest.php @@ -7,6 +7,7 @@ namespace Drupal\user\Tests; +use Drupal\Component\Serialization\PhpSerialize; use Drupal\simpletest\UnitTestBase; use Drupal\user\TempStoreFactory; use Drupal\Core\Lock\DatabaseLockBackend; @@ -83,7 +84,7 @@ protected function tearDown() { */ public function testUserTempStore() { // Create a key/value collection. - $factory = new TempStoreFactory(Database::getConnection(), new DatabaseLockBackend(Database::getConnection())); + $factory = new TempStoreFactory(new PhpSerialize(), Database::getConnection(), new DatabaseLockBackend(Database::getConnection())); $collection = $this->randomName(); // Create two mock users.