ae9d4cb13eec5e39f15600c11d2267fdd1c399c4
[yaffs-website] / web / core / modules / user / tests / src / Kernel / TempStoreDatabaseTest.php
1 <?php
2
3 namespace Drupal\Tests\user\Kernel;
4
5 use Drupal\Core\KeyValueStore\KeyValueExpirableFactory;
6 use Drupal\KernelTests\KernelTestBase;
7 use Drupal\user\SharedTempStoreFactory;
8 use Drupal\Core\Lock\DatabaseLockBackend;
9 use Drupal\Core\Database\Database;
10
11 /**
12  * Tests the temporary object storage system.
13  *
14  * @group user
15  * @group legacy
16  * @see \Drupal\user\SharedTempStore
17  */
18 class TempStoreDatabaseTest extends KernelTestBase {
19
20   /**
21    * Modules to enable.
22    *
23    * @var array
24    */
25   public static $modules = ['system', 'user'];
26
27   /**
28    * A key/value store factory.
29    *
30    * @var \Drupal\user\SharedTempStoreFactory
31    */
32   protected $storeFactory;
33
34   /**
35    * The name of the key/value collection to set and retrieve.
36    *
37    * @var string
38    */
39   protected $collection;
40
41   /**
42    * An array of (fake) user IDs.
43    *
44    * @var array
45    */
46   protected $users = [];
47
48   /**
49    * An array of random stdClass objects.
50    *
51    * @var array
52    */
53   protected $objects = [];
54
55   protected function setUp() {
56     parent::setUp();
57
58     // Install system tables to test the key/value storage without installing a
59     // full Drupal environment.
60     $this->installSchema('system', ['key_value_expire']);
61
62     // Create several objects for testing.
63     for ($i = 0; $i <= 3; $i++) {
64       $this->objects[$i] = $this->randomObject();
65     }
66
67   }
68
69   /**
70    * Tests the UserTempStore API.
71    *
72    * @expectedDeprecation \Drupal\user\SharedTempStoreFactory is scheduled for removal in Drupal 9.0.0. Use \Drupal\Core\TempStore\SharedTempStoreFactory instead. See https://www.drupal.org/node/2935639.
73    * @expectedDeprecation \Drupal\user\SharedTempStore is scheduled for removal in Drupal 9.0.0. Use \Drupal\Core\TempStore\SharedTempStore instead. See https://www.drupal.org/node/2935639.
74    */
75   public function testUserTempStore() {
76     // Create a key/value collection.
77     $factory = new SharedTempStoreFactory(new KeyValueExpirableFactory(\Drupal::getContainer()), new DatabaseLockBackend(Database::getConnection()), $this->container->get('request_stack'));
78     $collection = $this->randomMachineName();
79
80     // Create two mock users.
81     for ($i = 0; $i <= 1; $i++) {
82       $users[$i] = mt_rand(500, 5000000);
83
84       // Storing the SharedTempStore objects in a class member variable causes a
85       // fatal exception, because in that situation garbage collection is not
86       // triggered until the test class itself is destructed, after tearDown()
87       // has deleted the database tables. Store the objects locally instead.
88       $stores[$i] = $factory->get($collection, $users[$i]);
89     }
90
91     $key = $this->randomMachineName();
92     // Test that setIfNotExists() succeeds only the first time.
93     for ($i = 0; $i <= 1; $i++) {
94       // setIfNotExists() should be TRUE the first time (when $i is 0) and
95       // FALSE the second time (when $i is 1).
96       $this->assertEqual(!$i, $stores[0]->setIfNotExists($key, $this->objects[$i]));
97       $metadata = $stores[0]->getMetadata($key);
98       $this->assertEqual($users[0], $metadata->owner);
99       $this->assertIdenticalObject($this->objects[0], $stores[0]->get($key));
100       // Another user should get the same result.
101       $metadata = $stores[1]->getMetadata($key);
102       $this->assertEqual($users[0], $metadata->owner);
103       $this->assertIdenticalObject($this->objects[0], $stores[1]->get($key));
104     }
105
106     // Remove the item and try to set it again.
107     $stores[0]->delete($key);
108     $stores[0]->setIfNotExists($key, $this->objects[1]);
109     // This time it should succeed.
110     $this->assertIdenticalObject($this->objects[1], $stores[0]->get($key));
111
112     // This user can update the object.
113     $stores[0]->set($key, $this->objects[2]);
114     $this->assertIdenticalObject($this->objects[2], $stores[0]->get($key));
115     // The object is the same when another user loads it.
116     $this->assertIdenticalObject($this->objects[2], $stores[1]->get($key));
117
118     // This user should be allowed to get, update, delete.
119     $this->assertTrue($stores[0]->getIfOwner($key) instanceof \stdClass);
120     $this->assertTrue($stores[0]->setIfOwner($key, $this->objects[1]));
121     $this->assertTrue($stores[0]->deleteIfOwner($key));
122
123     // Another user can update the object and become the owner.
124     $stores[1]->set($key, $this->objects[3]);
125     $this->assertIdenticalObject($this->objects[3], $stores[0]->get($key));
126     $this->assertIdenticalObject($this->objects[3], $stores[1]->get($key));
127     $metadata = $stores[1]->getMetadata($key);
128     $this->assertEqual($users[1], $metadata->owner);
129
130     // The first user should be informed that the second now owns the data.
131     $metadata = $stores[0]->getMetadata($key);
132     $this->assertEqual($users[1], $metadata->owner);
133
134     // The first user should no longer be allowed to get, update, delete.
135     $this->assertNull($stores[0]->getIfOwner($key));
136     $this->assertFalse($stores[0]->setIfOwner($key, $this->objects[1]));
137     $this->assertFalse($stores[0]->deleteIfOwner($key));
138
139     // Now manually expire the item (this is not exposed by the API) and then
140     // assert it is no longer accessible.
141     db_update('key_value_expire')
142       ->fields(['expire' => REQUEST_TIME - 1])
143       ->condition('collection', "user.shared_tempstore.$collection")
144       ->condition('name', $key)
145       ->execute();
146     $this->assertFalse($stores[0]->get($key));
147     $this->assertFalse($stores[1]->get($key));
148   }
149
150 }