Problem/Motivation

In #2670730: Provide a delete action for each content entity type we want to add a generic entity delete action but this needs the User module's tempstore and we can't have core depend on User module code.

Proposed resolution

Move temp store code to core and deprecate the user code.

Remaining tasks

User interface changes

None

API changes

The services user.private_tempstore and user.shared_tempstore are deprecated in favour of tempstore.private and tempstore.shared.

The following classes are deprecated:
Drupal\user\PrivateTempStore in favour of Drupal\Core\TempStore\PrivateTempStore
Drupal\user\PrivateTempStoreFactory in favour of Drupal\Core\TempStore\PrivateTempStoreFactory
Drupal\user\SharedTempStore in favour of Drupal\Core\TempStore\SharedTempStore
Drupal\user\SharedTempStoreFactory in favour of Drupal\Core\TempStore\SharedTempStoreFactory

The Drupal\user\TempStoreException is aliased to Drupal\Core\TempStore\TempStoreException when the legacy services are used to provide BC if you are catching that exception.

The container parameter user.tempstore.expire is removed and if it has been customised it is copied to tempstore.expire and a deprecation notice triggered.

Data model changes

None

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

alexpott created an issue. See original summary.

alexpott’s picture

Status: Active » Needs review
FileSize
83.69 KB

One thing to decide is how to handle the removal of the parameter user.tempstore.expire. I think the best way might be a service modifier in the user module that checks to see if it is set - if so trigger a silenced deprecation error and set the core value to it.

There are also questions about whether we should alias \Drupal\user\TempStoreException to Drupal\Core\TempStore\TempStoreException this would mean that any code catching it wouldn't have to change.

alexpott’s picture

In discussion with @catch we thought the using class_alias() might work very nicely for the exception and preserve BC when using the BC services. Patch also adds deprecation of the user.tempstore.expire parameter.

alexpott’s picture

Title: Move user's temp stores to core » Move User module's temp stores to core
chr.fritsch’s picture

This looks really good.

Found a few minors:

Drupal\KernelTests\Core\TempStore\TempStoreDatabaseTest:

  1. It should be in @group TempStore
  2. $storeFactory var annotation need to be adjusted

Drupal\Tests\Core\TempStore\PrivateTempStoreTest:

  1. $tempStore var annotation need to be adjusted
chr.fritsch’s picture

Status: Needs review » Needs work

Forgot to change the status

alexpott’s picture

Status: Needs work » Needs review
FileSize
22.91 KB
85.26 KB

Fixed #6 and also noticed Drupal\KernelTests\Core\TempStore\TempStoreDatabaseTest was installing the user module - that's not necessary now :)

Also added the change record I created - https://www.drupal.org/node/2935639 - to the deprecation notices. The CR needs review too.

alexpott’s picture

Issue summary: View changes

Updated API changes.

catch’s picture

Good to see the class_alias() works, this will be our first non-test-framework usage afaik.

This means we can't trigger a deprecation message from the old exception, but we're going to have a subset of API changes from 8.x to 9.x that are documented but not automated, and this was the only idea I could come up with for forwards compatibility.

alexpott’s picture

@catch also in mitigation to not getting the deprecation message from the exception unless you have code that is throwing that exception outside of the core's usages you'll have a deprecation message from the factory and/or the temp store itself.

alexpott’s picture

Also for those reviewing the patch the class_alias is tested by the existing tests - see \Drupal\Tests\user\Unit\PrivateTempStoreTest::testDeleteWithNoLockAvailable() and \Drupal\Tests\user\Unit\SharedTempStoreTest::testSetWithNoLockAvailable() for example.

chr.fritsch’s picture

Status: Needs review » Needs work
Issue tags: -Needs change record
+++ b/core/modules/user/user.services.yml
@@ -50,12 +50,14 @@ services:
   user.private_tempstore:
     class: Drupal\user\PrivateTempStoreFactory
...
+    arguments: ['@keyvalue.expirable', '@lock', '@current_user', '@request_stack', '%core.tempstore.expire%']
+    deprecated: The "%service_id%" service is deprecated. You should use the 'core.private_tempstore' service instead. See https://www.drupal.org/node/2935639.
     tags:
       - { name: backend_overridable }
   user.shared_tempstore:
     class: Drupal\user\SharedTempStoreFactory
-    arguments: ['@keyvalue.expirable', '@lock', '@request_stack', '%user.tempstore.expire%']
+    arguments: ['@keyvalue.expirable', '@lock', '@request_stack', '%core.tempstore.expire%']
+    deprecated: The "%service_id%" service is deprecated. You should use the 'core.shared_tempstore' service instead. See https://www.drupal.org/node/2935639.
     tags:
       - { name: backend_overridable }

I guess we should add a deprecation comment here as well

CR looks good to me.

chr.fritsch’s picture

Status: Needs work » Needs review

Forget about #13. I missed that we have now the deprecated key.

alexpott’s picture

Couple of other minor nits I spotted.

chr.fritsch’s picture

Status: Needs review » Reviewed & tested by the community

I search in the Drupal codebase and couldn't find any other occurrence of the deprecated classes.

So for me, this is looking really good.

alexpott’s picture

This conflicts with #2935610: Remove or deprecate MediaDeleteMultipleConfirmForm and it's route definition is that one gets in first this will need a quick reroll.

Berdir’s picture

+++ b/core/modules/user/src/PrivateTempStore.php
@@ -2,212 +2,25 @@
-    if (($object = $this->storage->get($key)) && ($object->owner == $this->getOwner())) {

+++ b/core/modules/user/tests/src/Unit/SharedTempStoreTest.php
@@ -322,6 +336,7 @@ public function testDeleteWithNoLockAvailable() {
    * Tests the deleteIfOwner() method.
    *
    * @covers ::deleteIfOwner
+   * @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.
    */
   public function testDeleteIfOwner() {
     $this->lock->expects($this->once())

What's the plan with those tests. Wouldn't it make more sense to move them too and use the new class? Don't think we copied them?

alexpott’s picture

re #18

+++ b/core/modules/views_ui/views_ui.services.yml
similarity index 90%
copy from core/modules/user/tests/src/Kernel/TempStoreDatabaseTest.php

copy from core/modules/user/tests/src/Kernel/TempStoreDatabaseTest.php
copy to core/tests/Drupal/KernelTests/Core/TempStore/TempStoreDatabaseTest.php

copy to core/tests/Drupal/KernelTests/Core/TempStore/TempStoreDatabaseTest.php
index b3d7ff1e1a..a2f8a9456e 100644

index b3d7ff1e1a..a2f8a9456e 100644
--- a/core/modules/user/tests/src/Kernel/TempStoreDatabaseTest.php

--- a/core/modules/user/tests/src/Kernel/TempStoreDatabaseTest.php
+++ b/core/tests/Drupal/KernelTests/Core/TempStore/TempStoreDatabaseTest.php

+++ b/core/tests/Drupal/KernelTests/Core/TempStore/TempStoreDatabaseTest.php
similarity index 96%
copy from core/modules/user/tests/src/Unit/PrivateTempStoreTest.php

copy from core/modules/user/tests/src/Unit/PrivateTempStoreTest.php
copy to core/tests/Drupal/Tests/Core/TempStore/PrivateTempStoreTest.php

copy to core/tests/Drupal/Tests/Core/TempStore/PrivateTempStoreTest.php
index 8d188114cc..0144919b24 100644

index 8d188114cc..0144919b24 100644
--- a/core/modules/user/tests/src/Unit/PrivateTempStoreTest.php

--- a/core/modules/user/tests/src/Unit/PrivateTempStoreTest.php
+++ b/core/tests/Drupal/Tests/Core/TempStore/PrivateTempStoreTest.php

+++ b/core/tests/Drupal/Tests/Core/TempStore/PrivateTempStoreTest.php
similarity index 97%
copy from core/modules/user/tests/src/Unit/SharedTempStoreTest.php

copy from core/modules/user/tests/src/Unit/SharedTempStoreTest.php
copy to core/tests/Drupal/Tests/Core/TempStore/SharedTempStoreTest.php

copy to core/tests/Drupal/Tests/Core/TempStore/SharedTempStoreTest.php
index 33bde413e2..55a78b9a25 100644

index 33bde413e2..55a78b9a25 100644
--- a/core/modules/user/tests/src/Unit/SharedTempStoreTest.php

--- a/core/modules/user/tests/src/Unit/SharedTempStoreTest.php
+++ b/core/tests/Drupal/Tests/Core/TempStore/SharedTempStoreTest.php

All 3 tests that related to temp stores in the User module have been copied to Core tests and the User module tests are all legacy tests with all the necessary @expectedDeprecation annotations.

larowlan’s picture

Status: Reviewed & tested by the community » Needs review
+++ b/core/core.services.yml
@@ -1650,3 +1651,13 @@ services:
+  core.private_tempstore:
...
+  core.shared_tempstore:

this is the first instance of a core service being prefixed with `core.`. Are we sure want to introduce that here?

We could instead flip it and make it namespaced to the concept - e.g. `tempstore.private` and `tempstore.shared` instead?

We do similar for other services in core, eg cache, config, entity_type.

Thoughts?

Rest of the patch looks awesome, love the deprecation work.

alexpott’s picture

Assigned: Unassigned » alexpott
Status: Needs review » Needs work

There's no need to start setting a precedent here. Let's go with tempstore.private and tempstore.shared. We made a mistake when we adopted the service container by not prefixing everything with the provider but that is not a mistake we can undo here. I'll change the patch / issue summary / change record.

alexpott’s picture

Issue summary: View changes
Status: Needs work » Needs review
FileSize
19.55 KB
85.34 KB

Updated the patch and issue summary.

alexpott’s picture

Updated the change record as well.

chr.fritsch’s picture

Status: Needs review » Reviewed & tested by the community

I checked that all occurrences of core.private_tempstore and core.shared_tempstore were replaced by tempstore.private and tempstore.shared.

alexpott’s picture

FYI I also updated the container parameter from core.tempstore.expire to tempstore.expire for consistency. No core container parameters are prefixed with core. either.

catch’s picture

Status: Reviewed & tested by the community » Fixed

Committed 601593f and pushed to 8.5.x. Thanks!

  • catch committed 601593f on 8.5.x
    Issue #2935617 by alexpott, chr.fritsch: Move User module's temp stores...
tim.plunkett’s picture

This seems like a cop-out.
Without #2008884: Provide an interface for TempStore implementations this issue makes a bad situation... the same.
This was an opportunity to suggest people typehint by a real interface. Now the deprecation message is prompting them to do the same old thing.

-1

tim.plunkett’s picture

Glad to see #2008884: Provide an interface for TempStore implementations is moving again. If it doesn't make it into 8.5.x, I don't see why this should either (since the deprecation message will point people to do the wrong thing for typehints)

alexpott’s picture

@tim.plunkett I disagree. Adding the interface is hard API break for code, this isn't. I agree with adding the interface in 8.x.x but we can only enforce it in 9.0.0

Berdir’s picture

Gave 8.5.x a try on our internal distribution and ctools is very unhappy about this change:

The service "ctools.serializable.tempstore.factory" has a dependency
on a non-existent parameter "user.tempstore.expire". Did you mean
this: "tempstore.expire"? in

I think we need to better BC on the removal of this. my suggestion would be to keep it instead of removing it and copy the value over if it's not the default.

Follow-up?

Edit: Follow-up it is: #2936435: Better BC for deprecated container parameter user.tempstore.expire

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.

newme154’s picture

how is this fixed? I just downloaded 8.6.1 and still getting the issue. why do I have to perform a patch to the latest version if its fixed? does it not get rolled into the newest version?

Berdir’s picture

what isn't fixed? This was a task, it didn't fix any bugs. And there was an issue with BC but that was fixed a long time ago.

newme154’s picture

why am I getting the error on a fresh install? The status was set to closed (fixed).

Berdir’s picture

What error? If you have an error message you might want to create a new issue and mention everything you think might be relevant.

newme154’s picture

same error message that's in this thread.

[Sun Sep 23 23:29:00.196701 2018] [php7:notice] [pid 17992:tid 1944] [client ::1:59714] Symfony\\Component\\DependencyInjection\\Exception\\ParameterNotFoundException: The service "ctools.serializable.tempstore.factory" has a dependency on a non-existent parameter "user.tempstore.expire". Did you mean this: "tempstore.expire"? in C:\\xampp\\htdocs\\Drupal8\\vendor\\symfony\\dependency-injection\\ParameterBag\\ParameterBag.php on line 102 #0 C:\\xampp\\htdocs\\Drupal8\\vendor\\symfony\\dependency-injection\\ParameterBag\\ParameterBag.php(219): Symfony\\Component\\DependencyInjection\\ParameterBag\\ParameterBag->get('user.tempstore....')\n#1 C:\\xampp\\htdocs\\Drupal8\\vendor\\symfony\\dependency-injection\\ParameterBag\\ParameterBag.php(189): Symfony\\Component\\DependencyInjection\\ParameterBag\\ParameterBag->resolveString('%user.tempstore...', Array)\n#2 C:\\xampp\\htdocs\\Drupal8\\vendor\\symfony\\dependency-injection\\Compiler\\ResolveParameterPlaceHoldersPass.php(64): Symfony\\Component\\DependencyInjection\\ParameterBag\\ParameterBag->resolveValue('%user.tempstore...')\n#3 C:\\xampp\\htdocs\\Drupal8\\vendor\\symfony\\dependency-injection\\Compiler\\AbstractRecursivePass.php(60): Symfony\\Component\\DependencyInjection\\Compiler\\ResolveParameterPlaceHoldersPass->processValue('%user.tempstore...', false)\n#4 C:\\xampp\\htdocs\\Drupal8\\vendor\\symfony\\dependency-injection\\Compiler\\ResolveParameterPlaceHoldersPass.php(79): Symfony\\Component\\DependencyInjection\\Compiler\\AbstractRecursivePass->processValue(Array, false)\n#5 C:\\xampp\\htdocs\\Drupal8\\vendor\\symfony\\dependency-injection\\Compiler\\AbstractRecursivePass.php(67): Symfony\\Component\\DependencyInjection\\Compiler\\ResolveParameterPlaceHoldersPass->processValue(Array)\n#6 C:\\xampp\\htdocs\\Drupal8\\vendor\\symfony\\dependency-injection\\Compiler\\ResolveParameterPlaceHoldersPass.php(79): Symfony\\Component\\DependencyInjection\\Compiler\\AbstractRecursivePass->processValue(Object(Symfony\\Component\\DependencyInjection\\Definition), true)\n#7 C:\\xampp\\htdocs\\Drupal8\\vendor\\symfony\\dependency-injection\\Compiler\\AbstractRecursivePass.php(60): Symfony\\Component\\DependencyInjection\\Compiler\\ResolveParameterPlaceHoldersPass->processValue(Object(Symfony\\Component\\DependencyInjection\\Definition), true)\n#8 C:\\xampp\\htdocs\\Drupal8\\vendor\\symfony\\dependency-injection\\Compiler\\ResolveParameterPlaceHoldersPass.php(79): Symfony\\Component\\DependencyInjection\\Compiler\\AbstractRecursivePass->processValue(Array, true)\n#9 C:\\xampp\\htdocs\\Drupal8\\vendor\\symfony\\dependency-injection\\Compiler\\AbstractRecursivePass.php(39): Symfony\\Component\\DependencyInjection\\Compiler\\ResolveParameterPlaceHoldersPass->processValue(Array, true)\n#10 C:\\xampp\\htdocs\\Drupal8\\vendor\\symfony\\dependency-injection\\Compiler\\ResolveParameterPlaceHoldersPass.php(43): Symfony\\Component\\DependencyInjection\\Compiler\\AbstractRecursivePass->process(Object(Drupal\\Core\\DependencyInjection\\ContainerBuilder))\n#11 C:\\xampp\\htdocs\\Drupal8\\vendor\\symfony\\dependency-injection\\Compiler\\Compiler.php(141): Symfony\\Component\\DependencyInjection\\Compiler\\ResolveParameterPlaceHoldersPass->process(Object(Drupal\\Core\\DependencyInjection\\ContainerBuilder))\n#12 C:\\xampp\\htdocs\\Drupal8\\vendor\\symfony\\dependency-injection\\ContainerBuilder.php(788): Symfony\\Component\\DependencyInjection\\Compiler\\Compiler->compile(Object(Drupal\\Core\\DependencyInjection\\ContainerBuilder))\n#13 C:\\xampp\\htdocs\\Drupal8\\web\\core\\lib\\Drupal\\Core\\DrupalKernel.php(1318): Symfony\\Component\\DependencyInjection\\ContainerBuilder->compile()\n#14 C:\\xampp\\htdocs\\Drupal8\\web\\core\\lib\\Drupal\\Core\\DrupalKernel.php(892): Drupal\\Core\\DrupalKernel->compileContainer()\n#15 C:\\xampp\\htdocs\\Drupal8\\web\\core\\lib\\Drupal\\Core\\DrupalKernel.php(468): Drupal\\Core\\DrupalKernel->initializeContainer()\n#16 C:\\xampp\\htdocs\\Drupal8\\web\\core\\lib\\Drupal\\Core\\DrupalKernel.php(664): Drupal\\Core\\DrupalKernel->boot()\n#17 C:\\xampp\\htdocs\\Drupal8\\web\\index.php(19): Drupal\\Core\\DrupalKernel->handle(Object(Symfony\\Component\\HttpFoundation\\Request))\n#18 {main}

minhein’s picture

I am getting same error too.

Symfony\Component\DependencyInjection\Exception\ParameterNotFoundException: The service "ctools.serializable.tempstore.factory" has a dependency on a [error]
non-existent parameter "user.tempstore.expire". Did you mean this: "tempstore.expire"? in
/apps/drupal/htdocs/vendor/symfony/dependency-injection/ParameterBag/ParameterBag.php:102

larowlan’s picture

did you update ctools module?

ARRC-Drupal-Chick’s picture

#39, I am also experiencing issues related to user temp store and Chaos Tools. I was good until Chaos Tools updated twice this month.

Any attempts to install ctools 8.x-3.1 or 8.x-3.2 (both released this month) causes any Drupal based page to crash once the code has been changed:

This is the message:
TypeError: Argument 1 passed to Drupal\ctools\ParamConverter\TempstoreConverter::__construct() must be an instance of Drupal\user\SharedTempStoreFactory, instance of Drupal\Core\TempStore\SharedTempStoreFactory given in {full_path_removed}\modules\ctools\src\ParamConverter\TempstoreConverter.php on line 102

The fault here appears to be that Chaos Tools updated to use the deprecated user tempstore.

I have a configuration that does not allow the use of Drush (and, yes, it is unusual but has been working in production for 3 years):

  • Windows 10 (or Server 2012 R2)
  • Apache 2.4.33 64bit
  • PHP 7.2.5 64bit
  • Drupal 8.6.10
  • MS SQL Server 2012 and 2017
Berdir’s picture

Ctools was updated to use the non-deprecated service. If that's the error then IMHO something went very wrong with your update. Make sure you don't have multiple versions of the ctools module lying around in different folder or so and that you updated all files. You might want to remove the folder completely and replace it.

If it's still not working then post in the ctools issue queue, this isn't a problem in core.

Edit: I just saw you commented there too, but as I said, something with your code base is not correct. Note that you can still use drush (or composer) to manage your files on a local/development system, even if you can't use it on your production server.