from where cboden write:

Although Symfony Session Handlers provide the correct PHP functionality to still access the $_SESSION variable, the primary advantage of using the Symfony Session class is to provide clean unit testing. In unit tests you are able to replace the NativeSessionStorage with MockArraySessionStorage in the Session::__construct and run a full suite of tests using the same code/interface.

this extra testibility would be awesome to have.

This issue attempts to convert every use of $_SESSION to Symfony's handling of sessions.

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

Paul Simard’s picture

Issue tags: +8.x, +WSCCI, +symfony

Adding tags...

Paul Simard’s picture

This is my first pass for your review @cosmicdreams. It's the same patch from the previous thread, moved here for continuity.

Paul

aspilicious’s picture

drupal_get_session is an existing function? Can't find the function itself in the patch.

Paul Simard’s picture

@aspilicious I'm building this while following other work. I'm working from an isolated branch off HEAD. Once the patch implementing the function goes in, I can backport it.

I believe it or something similar is coming in from another source/Symfony conversion. I suspect it'll be found in namespace Drupal\Core\something\something. If not, I'll investigate the mechanism Drupal will be using to access the $_SESSION data and apply the means recommended.

Using $session->set(), $session->get(), $session->has(), $session->remove(), and the rest become the means to access and manipulate the $_SESSION contents.

http://api.symfony.com/2.0/Symfony/Component/HttpFoundation/Session.html

As I understand it, drupal_get_session() was removed some time ago, I'm not yet certain how we'll be accessing the Symfony session object in HttpFoundation. I'm still figuring out namespace and scoping issues. The $_SESSION is a static global (bad for direct use in the new scheme of things). AFAIK, this puts the code in compliance with Symfony's methods, and will improve testing with a series of tests that cover all the session handling code.

There exists in HttpFoundation MockArraySessionStorage to be used for testing purposes.

Please note the 'do-not-patch' portion of the patch name. What's contained within the file is WIP and not intended to ever be applied to core in its current state. We're all learning Symfony here. I'm also still learning Drupal.

cosmicdreams’s picture

Found some errors, sub-optimizations in the patch in #2. Going to clean it up. (Sorry my dreditor isn't working)

cosmicdreams’s picture

FileSize
15.54 KB

In general here are the issues I found:

  • When using $session->set('something', $value), this syntax is illegal : $session->set('something') = $value
  • use $session->has('something') in conditional statements whenever possible
  • Fixed namespace issues
  • statements like $thing = $session->has('something') ? $session->get('something') : array(); can be refactored to $thing = $session->get('something, array());
  • There were a few instances of the $session variable not being instantiated within the scope of the function where it is used
  • some commented out code could have been deleted
  • I removed some extra spacing

Still not sure how to handle multi-level arrays with this syntax. I think I might have figured it out a few days ago, but no longer remember.

Code Review notes along the way

  • in core/modules/update/update.manager.inc line 445 we use a $project_real_location that may be an uninitialized variable (theoretically) by the time it is used. What should it's base or initial value be?
  • in core/modules/user/user.pages.inc line 16 we have a db_select('users')->fields(....), but my IDE is claiming that the class SelectQuery doesn't have a fields method
cosmicdreams’s picture

From here there remain 237 instances of $_SESSION within the code. I'll try to remove any additional single-level array instances first and ask the greater community to help figure out how to handle multi-level array instances.

cosmicdreams’s picture

Somehow the implementation of the Drupal/Core/Session stuff didn't carry over. I'll try to fix that.

Edit: and it appears I was wrong about the namespace corrections, sorry.

cosmicdreams’s picture

FileSize
85.51 KB

Ok, here's a more complete patch (had to go back to parent issue and use the patch I previously posted there.

EDIT: 177 instances of $_SESSION remain

Paul Simard’s picture

@cosmicdreams: Thanks a lot. :) I'm still ferreting out the code from Symfony. Didn't like the syntactically wrong $session->set() I was using, and knew it wouldn't stand.

How is the $_SESSION data accessed the Symfony way?

I get:
adding the 'use Drupal/Core/Session;'
only one $_SESSION
I don't yet understand:
how we obtain the session object when we need to access it.
Which is why I threw in the drupal_get_session() stuff. When I understand how the session will be accessed, I can replace it with $session = new Session() or DrupalSession(), $session = some_global_utility_function(), or whatever the community determines is the best implementation method.

My thinking, at this point, leans toward creating a $session variable whenever we need to access the data on the fly. There may be a global function for 'bc' as long as it's decided to offer it, but that's actually a separate issue unless we need something in the interim.

A lot of the references remaining are in the tests. All the actual module code has been surveyed, and I believe all the single dimensional references have been ported (except the tests at this point).

Just saw #9, which do we use? Drupal\Core\Session? or Drupal\Core\Session\Session? or something more or else?

cosmicdreams’s picture

in the Symfony way, the session is merely an attribute of the request and pulled this so:

$request->getSession();

I suppose that once the HttpFoundation and HttpKernel patch lands we'll see if we can do that.

Currently, when we want to retrieve the session we use drupal_session_get(). Which does whatever it needs to do in order to pull the session for us. Currently that function is in session.inc and needs improvement as it only pulls from a file based session storage and isn't a proper factory. The file based session storage is there because we were trying to optimize that function for the installation process (where we don't always have access to a database, since early in the install process we don't have one setup yet.)

Just saw #9, which do we use? Drupal\Core\Session? or Drupal\Core\Session\Session? or something more or else?

I made a mistake before, the use of Drupal\Core\Session\Session is correct.

Paul Simard’s picture

FileSize
71.62 KB

Minor changes to comments... tenses, word choice, case, etc.

cosmicdreams’s picture

OK, in #symfony-dev I talked over handling multi-level arrays with lsmith and have an idea on how we could convert them to symfony's syntax:

for every

$_SESSION['something']['attribute']

we can convert it to

$session_all = $session->all();
$session_all['something']['attribute'];

Anyone have a better idea?

Paul Simard’s picture

FileSize
90.35 KB

More corrections, removed several missed uses of $_SESSION, added $session = drupal_session_get(); where $_SESSION (multi-dimensional) references obtain in modules (aggregator--user).

Paul Simard’s picture

Here's a question:

In the case of:


modules/dblog/dblog.admin.inc:  $_SESSION[] = array();

I'm not entirely sure what's happening. The $_SESSION is being cleared and reinitialized with an empty array(), that I get.

Reviewing class Sessions in Drupal\Core\Sessions, I find no equivalent method to clear and re-initialize the Session object. There is only the one reference, and it is the last one standing.

Any ideas?

Paul Simard’s picture

FileSize
102.12 KB

Here's a patch that removes (I believe) all but 1 reference to $_SESSION from everything (except tests) in the core subdir and children.

The suggested syntax for multidimensional $session arrays has been implemented as well.

I'm reluctant to submit for automatic testing, until the new tests (for Drupal's Symfony Session usage) have been written and tested.

cosmicdreams’s picture

It appears that the patches in #16, 15, 14, and 12 are all incomplete because it doesn't include the added files from /core/lib/Drupal/Session . I made the same mistake in the patch in #6, but have a fixed version in #9.

I'll try to start with #9 and merge the changes you've made in 16 and see if I can produce a patch with that.

cosmicdreams’s picture

FileSize
100.53 KB

A few key points with the changes in this patch from #16

  • included PSR-0 Session code
  • After talking with neclimdul on IRC, $something = $session->get('something') then using $something['attribute'] is prefered over $session_all = $session->all() then $session_all['something']['attribute']
  • added missing $session->set statements

I wasn't able to review every line but here's a partial cleanup of the patch: If I have time later in the day I'll fix the rest if you don't beat me to it.

Paul Simard’s picture

I'll start working on it. It's growing into one monster patch. 135K and rising. Managed to eliminate the usages in the test modules. Going back to change the $session_all = $session->all() usages to the recommended practice. Hope to finish by nightfall. Need the weekend for school projects so I won't be available for more than quick questions. 4 projects due Monday.

Paul Simard’s picture

FileSize
125.33 KB

@cosmicdreams: Here's the final edits (I think). I rolled it up again.

Accomplished:
-- All references to $_SESSION in code from core directory and below have been ported to Symfony usage as discussed.
-- All references to $_SESSION tests have been ported to Symfony usage as discussed.
Remaining references:
In lib/Drupal/Core/Cache/DatabaseBackend.php
In lib/Drupal/Core/Session/Storage/DrupalSessionStorage.php
In vendor/Symfony/Component/HttpFoundation/Session/Storage/NativeSessionStorage.php
Anything else is in a comment or text string left unchanged as I don't know how it's going to be documented.
cosmicdreams’s picture

Thanks Paul:

when I apply this patch I don't have any code in /core/lib/Drupal/Core/Session just empty folders (from when the previous patch created them)

I think you forgot to track those files when you created the patch. Can you add them into the patch and reroll?

Paul Simard’s picture

@cosmicdreams: Re: #21. Gonna need some help with that.

Was fairly clear on Git workflows until today. :) Now I'm confused.

Here's what I did:

git clone 8.x into local directory.
git branch local
git checkout local
git branch yourpatch - to isolate your changes from HEAD and mywork
git checkout yourpatch
git apply yourpatch
git commit -a
git branch mywork - created branch for my editing
git checkout mywork
did a bunch of editing.
git commit -a - in mywork branch.

At this point, I should have different versions. 8.x - base == local; yourpatch committed; then mywork also committed.
I figure at this point, I need to merge mywork with yourpatch, then diff to 8.x, is that right?

Anyway, it didn't work. lol I think I didn't do it right. Been reading Git Community book, Drupal's Tutorials, etc. and I come away clearer on some points and more confused on others. Can you help? My brain is beginning to hurt.

Added:
I tried again. I believe I successfully merged mywork and yourpatch branches. git status from local (8.x) shows it 2 commits ahead of 8.x. At this point, if I'm reading everything correctly, while on the local branch a ...

git diff -p 8.x > '1545680-SESSION-replaced-with-Symfony.patch

should yield the desired patch. Have I got that right?

Paul Simard’s picture

@cosmicdreams: Here's the re-roll as described in #22.

Hope this fixes everything. *whew*

cosmicdreams’s picture

Yes, the issue I've been seeing in a few of your patches has been resolved (as this patch includes the PSR-0 session code).

Great work!

I'll give the patch a full review.

cosmicdreams’s picture

Status: Active » Needs review
FileSize
123.03 KB

Notes:

  • In places where we are getting a multi-level array and changing it, we need to set it as soon as possible afterwards. That way the value is stored in the session and not in the variable ('call by value' in play here instead of 'call by reference')
  • removed the modifications in core/modules/entity/test/modules/entity_crud_hook_test/entity_crud_hook_test.module as I don't there there is an exact equivalence with what's going on it the code. We would have to add set messages, but those set messages would reset the variable each time, not append new children.
  • I double-checked every conversation of empty() to make sure that empty() ~ !$session->has(). I found a few that weren't converted properly (likely my fault)
  • I like you $s_ syntax for temporary variables for containing session information. Looked through the code for cases of inconsistency of that rule and fixed what I could find.
  • and I found a few places were we goofed and hadn't cleaned it up yet.
  • Let's see how the testbot treats it.

Status: Needs review » Needs work

The last submitted patch, 1545680_25_session.patch, failed testing.

cosmicdreams’s picture

FileSize
122.66 KB

Oops that one had a syntax error, here's the patch with that line reverted.

cosmicdreams’s picture

Status: Needs work » Needs review

Status: Needs review » Needs work

The last submitted patch, 1545680_27_session.patch, failed testing.

cosmicdreams’s picture

Status: Needs work » Needs review
FileSize
121.73 KB

revert changes to tests that fail.

Status: Needs review » Needs work

The last submitted patch, 1545680_29_session.patch, failed testing.

Paul Simard’s picture

Notes on the patching/editing I did.

As far as passed by value vs. passed by reference, I assumed since we were operating on the $_SESSION variable, i.e. a global structure, that it was passed by reference each time, and was consistently so for the duration of the request, which should be longer than the duration of a given function. At least that was my thinking. If that's mistaken, let me know.

As far as the setting as soon as possible, I used drupal_session_get() in the broadest scope needed by the code to process the same data, but in no case greater than function scope. Occasionally I was able to narrow the scoping tighter than that. When it was clearly safe to do so, I did.

In examining the patch, I found the following:

File: bootstrap.inc
Func: drupal_get_messages()
Line: 1683

if ($messages = drupal_set_message()) {

+++ b/core/includes/bootstrap.inc
@@ -1674,10 +1679,13 @@ function drupal_set_message($message = NULL, $type = 'status', $repeat = TRUE) {
 function drupal_get_messages($type = NULL, $clear_queue = TRUE) {
+  $session = drupal_session_get();
+  $s_messages = $session->get('messages');
   if ($messages = drupal_set_message()) {
     if ($type) {
       if ($clear_queue) {
-        unset($_SESSION['messages'][$type]);
+        unset($s_messages[$type]);
+        $session->set('messages', $s_messages);
       }

My IDE (NetBeans) indicates accidental assignment in the if statement. I suspect it isn't accidental, but I don't know enough about the internal structures being referenced to be certain.

Saw changes you made in form_test.module. Your style here is much clearer than mine.

Anyway, that's all so you can see where I'm coming from. Any other questions, feel free to let me know.

sun’s picture

Component: wscci » user system
Issue tags: -8.x +API clean-up

Fixing bogus tags.

pounard’s picture

FYI messages should use the flash messenger, maybe this part of the code could still live using the old fashion $_SESSION access (which should work) and be the target of another issue?

cosmicdreams’s picture

Status: Needs work » Needs review
FileSize
121.01 KB

removed the changes going on in the install.core.inc as that has proved to break things.

Status: Needs review » Needs work

The last submitted patch, 1545680_35_session.patch, failed testing.

cosmicdreams’s picture

Status: Needs work » Needs review
FileSize
121.08 KB

This one tries to put and get messages from the FlashBag.

Status: Needs review » Needs work

The last submitted patch, 1545680_36_session.patch, failed testing.

cosmicdreams’s picture

Status: Needs work » Needs review
FileSize
118.04 KB

rerolled to see where I am

pounard’s picture

Ho, I almost forgot this one! I should get back on working with sessions, still didn't get that much feedback.

Status: Needs review » Needs work

The last submitted patch, 1545680_39_session.patch, failed testing.

dawehner’s picture

Assigned: cosmicdreams » Unassigned

Working on a big big rerole / usage of the container etc.

dawehner’s picture

Assigned: Unassigned » dawehner

.

dawehner’s picture

Status: Needs work » Needs review
FileSize
92.26 KB

So ... this is just a rerole of the existing patch, with all the long leftover comments, todos, fixmes and all other kind of uglyness.

Additional this patch provides the session as part of the container.

Note: login doesn't work yet, see user.module::user_login_finalize().

dawehner’s picture

__***sigh***__

Seems to be a duplicate of #1858196: [meta] Leverage Symfony Session components

dawehner’s picture

FileSize
106.82 KB

Just in case that's important, this don't misses the session files.

Status: Needs review » Needs work

The last submitted patch, drupal-1545680-46.patch, failed testing.

ParisLiakos’s picture

Status: Needs work » Closed (duplicate)

there is some nice work done here, but it is definitely a dupe
#1858196: [meta] Leverage Symfony Session components

znerol’s picture

Issue summary: View changes

Restarted after the session is finally available from the $request: #2473875: Convert uses of $_SESSION to symfony session retrieved from the request