To quote http://drupal.org/node/141043:
Remember anonymous comment posters. When someone leaves a comment as an anonymous user, his name, e-mail address and URL are not remembered. If we'd store that information in the user's session, he or she wouldn't have to re-enter that information every single time. A subtle but important improvement.
This is essentially moving the comment info module (with improvements I am sure) into core.
Dries brought up that this may be possible to do entirely in sessions for both caching and non-caching situations. This is a problem that pushed the comment info module to use jQuery for caching situations.
When caching in enabled (tested with non-aggressive) a page is generated with one persons session information placed in the fields. This page is cached with that persons information filled in and other users then see that persons information rather than their own in the cached page. The issue is at http://drupal.org/node/91849. Our solution was to use jQuery and cookies for cached situations putting the remembering in to the browser.
The session only code can be seen at:
http://cvs.drupal.org/viewcvs/drupal/contributions/modules/comment_info/...
Here is the relevant code:
/**
* Insert our checkbox, and populate fields.
* set validation hook.
*/
function comment_info_form_alter($form_id, &$form) {
global $user;
if ($user->uid || ($form_id != 'comment_form')) {
return;
}
foreach (array('name','homepage','mail') as $field) {
if (is_array($form[$field]) && $_SESSION['comment_info']['optin']) {
$form[$field]['#value'] = $_SESSION['comment_info'][$field];
}
}
$form['#validate']['comment_info_validate'] = array();
$form['comment_info']['optin'] = array(
'#type' => 'checkbox',
'#title' => 'Save my Comment Information for next time.',
'#default_value' => $_SESSION['comment_info']['optin']
);
}
/**
* save our data.
*/
function comment_info_validate($form_id, $form_values) {
if ($form_values['optin']) {
foreach (array('name','homepage','mail','optin') as $field) {
$_SESSION['comment_info'][$field] = $form_values[$field];
}
} else {
foreach (array('name','homepage','mail','optin') as $field) {
unset($_SESSION['comment_info'][$field]);
}
}
}
Is there a way to make this work with caching and without javascript?
The jQuery version only uses jQuery when caching is enabled. That code is at:
http://cvs.drupal.org/viewcvs/drupal/contributions/modules/comment_info/...
When I get to my development machine I'll start whipping up a patch. But first, I would like to know if there is another way to deal with cached pages. Any thoughts?
Comment | File | Size | Author |
---|---|---|---|
#35 | comment-remember_info-141131-35.patch | 1.38 KB | ChrisKennedy |
#34 | comment-remember_info-141131-34.patch | 1.38 KB | webchick |
#32 | comment-remember_info-141131-32.patch | 1.38 KB | mfer |
#27 | comment_utf8_escape.patch.txt | 589 bytes | erdemkose |
#20 | comment-remember_info-141131-20.patch | 2.28 KB | mfer |
Comments
Comment #1
mfer CreditAttribution: mfer commentedHere is my first go at this patch.
The css is in system.css
When caching is disabled the session stores the anonymous users info.
When caching is enabled jQuery and cookies do the remembering. I split up the javascript. The cookie code is the jQuery cookie plugin and in is /misc/jquery.cookie.js. This can be used by other modules and is the .cookie code described at visualjquery.com.
The rest of the javascript is in /modules/comment/comment.js.
Comment #2
Dries CreditAttribution: Dries commentedI think we can simplify this a bit. Why would we want to have a setting for this? If you look at systems like WordPress, they just remember their users. No configuration, no choice. I think it makes for sane default behavior. Therefore, I'd prefer to start out with no configuration settings. :-)
Is there a good reason to use both sessions and javascript? If we have to use Javascript, we might as well always use Javascript? Just thinking up loud.
Thanks for taking a lead in this mfer.
Comment #3
Dries CreditAttribution: Dries commentedAnother solution might be to use jQuery to call a JSON-callback in Drupal. We could store the information in the session variable, and retrieve it with a simple HTTP request. Might be less jQuery code. Food for thought.
Comment #4
mfer CreditAttribution: mfer commentedSimplification = good
@todo: Remove checkbox to remember. Just do it.
@todo: Remove the on/off setting.
I thought about requesting the information with jQuery from drupal but figured it wasn't worth the performance hit.
Time to do some digging into how wordpress does this.
Comment #5
mfer CreditAttribution: mfer commentedHere is another shot that is much more simplified. The jquery.cookie.js in /misc is compressed with packer. All of the configuration settings are gone and it just works when the fields are there. The comment.js file has been greatly simplified.
Comment #6
mfer CreditAttribution: mfer commentedLets try that attachment again
Comment #7
mfer CreditAttribution: mfer commentedadded "// $Id: $" to the comment.js file
Comment #8
Dries CreditAttribution: Dries commentedWhat does that compressed function do?
Comment #9
mfer CreditAttribution: mfer commentedThe compressed function is jQuery.cookie. It's the jQuery cookie plugin from jquery.com. you can read about it's usage at http://www.visualjquery.com in the plugins section. The function reads:
I figured it is better to use the jQuery plugin than to roll my own. And, to separate it out in case anyone else wants to use it.
Comment #10
mfer CreditAttribution: mfer commentedI compared the jQuery.cookie code to some roll your own cookie reading and writing javascript in the contrib modules. Going with custom cookie javascript can save about 300 bytes of javascript.
Comment #11
Dries CreditAttribution: Dries commentedWouldn't it be easier to set the cookie from PHP?
Comment #12
mfer CreditAttribution: mfer commentedThis patch sets the cookie in the comment_form_submit and reads it with javascript. The jquery.cookie plugin is not used here and a custom function is used to read the cookie. It's less javascript.
The only question I have is how to word the watchdog event when a cookie isn't sent from php.
This or the solution in #7 both work. They just solve it different ways.
Comment #13
ChrisKennedy CreditAttribution: ChrisKennedy commentedYou have string concatenation & addition spacing errors on the setcookie line, the inline comment should go on its own line, string concatenation spacing error on the drupal_add_js & foreach lines, and returnvalue should be returnValue (although I'd just change it to be "result").
Also, it might be best to store the data in a single cookie rather than three cookies, considering that a domain has a limit of 20 cookies total per browser.
Comment #14
mfer CreditAttribution: mfer commentedfixed the concatenation and spacing issues. Changed setcookie to setrawcookie with rawurlencode so the escape characters would be the same between php and javascript. Updated javascript to returnValue.
Moved setting the cookie from _submit to _validate to work with preview. When it saves it in _submit, you have saved values, you change a value and hit preview, the value would revert.
Still looking in to how to do it with one cookie.
Comment #15
mfer CreditAttribution: mfer commentedThis patch moves everything into one cookie and is post FAPI3.
Comment #16
Dries CreditAttribution: Dries commented1. I'm trying to understand why you set one cookie, rather than 3 separate cookies?
2. The error message "Comment: failed to save cookie on node %node" is not helpful. What is the point of telling this to the administrator? What can he learn from this? What are the instructions to solve this problem? I'm not sure this is useful.
3.
Comment #17
ChrisKennedy CreditAttribution: ChrisKennedy commentedI suggested storing the data in a single cookie in #13 because only 20 cookies are allowed per domain.
Comment #18
mfer CreditAttribution: mfer commentedI'm not sure what I was thinking with that warning message. I removed it in this patch.
I moved everything to one cookie due to the suggestion by ChrisKennedy in #13. It seemed to make sense. There is a 20 cookie limit per domain per rfc2109 which is what most browsers including IE and Firefox go by.
If we go with 3 cookies that would put drupal core at 4 cookie (with the phpsession). This way there are just 2 for drupal core. One for the session and one for the anonymous comment information. This leaves 18 open cookies rather than 16 for other modules or apps to use.
Comment #19
Dries CreditAttribution: Dries commentedI don't think the cookie limit will be a problem. Most people will want to store data in the session anyway -- at least, that's what the past 6 years have shown us. Let's go with 3 cookies instead! :)
Comment #20
mfer CreditAttribution: mfer commented3 cookies it is :-D
Back to 3 cookies. This is similar to #14.
I, also, found that if the cookie doesn't exist we shouldn't be overwriting the value of the form field with '' which is what the cookie variable in the javascript is initialized with. So, if the cookie is empty no changes are made to that part of the form. This may come in handy if someone tries to theme the form to add default values.
Comment #21
Dries CreditAttribution: Dries commentedThe last patch looks good to me, and I'm inclined to commit it. I'd add an entry to the CHANGELOG.txt but I can do that for you.
The one thing I'm not 100% about is the setrawcookie() and the url-encoding. It looks like you are doing the right thing, but there might be a simpler way to achieve the say. Unfortunately, I'm not that well-versed with jQuery.
Either way, if someone can confirm that this patch works, it is RTBC. Feel free to mark it as such after some testing.
Comment #22
Dries CreditAttribution: Dries commentedOh, btw, thanks mfer! Good job. :)
Comment #23
mfer CreditAttribution: mfer commented@dries - The reason for the setrawcookie and rawurlencode has to do with the difference between php and javascript handling spaces, which drupal allows in the username. Some details in the php handbook at http://us2.php.net/manual/en/function.setcookie.php#62848.
Basically, setcookie uses urlencode to encode the cookie. This function is not RFC 1738 compliant and encodes spaces as a + which javascript does does not turn back into a space. According to the php manual on urlencode, this functionality is used for historical reasons. rawurlencode is RFC 1738 compliant and uses the same encoding as javascript.
Comment #24
Dries CreditAttribution: Dries commentedDidn't some more testing and research, and committed this patch. Thanks, mfer! :)
Comment #25
Senpai CreditAttribution: Senpai commentedJust an FYI, but sending three cookies to a security paranoid web surfer using IE6 is going to result in three buttons to click "Yes, accept this cookie" for. That's going to happen immediately after an anon comment event too. Doesn't look good for a site to be tossing three cookies at a user after they've submitted an anon form.
One single cookie which stores all the info for this simple, menial anonymous remembrance task would be better. It's also easier to keep track of when you're sorting through your browser's cookies looking for incriminating evidence that needs deleted.
Comment #26
mfer CreditAttribution: mfer commented@Senpai: I'm not sure that the 3 cookies will really be much of an issue compared to one. The trade off is about 10 more lines of javascript for that handful of users while wordpress and others are already using 3 cookies for this which has set a precedence.
Dries wanted the 3 and I'm really OK with that. If you want to submit an issue I'll subscribe to it and roll a patch if the powers at be deem it worthy.
Comment #27
erdemkose CreditAttribution: erdemkose commentedIf you enter some non-ASCII characters in name field, after preview they will be replaced by two ASCII characters (Erdem Köse > Erdem Köse). Because
escape()
javascript function doesn't work with UTF-8 values. It should be replaced withdecodeURIComponent()
function.Comment #28
mfer CreditAttribution: mfer commentedoops. Looks like unescape() is deprecated. decodeURIComponent() seems to be the utf8 compliant solution here.
I haven't tested it. I'll put that on my to do list for the weekend but everything I've read says this patch has it right.
Nice catch.
Comment #29
webchickThis change broke comment module on Dreamhost:
http://ca.php.net/setrawcookie is only available on PHP 5.
Comment #30
webchickComment #31
webchickTo reproduce, try and post a comment. ;)
Comment #32
mfer CreditAttribution: mfer commentederdemkose and webchick, nice catches. That'll teach me to read the manual and to not only develop in php5. :-)
This patch fixes the uft bug of eremkose and worked for me on php4.
Comment #33
Stefan Nagtegaal CreditAttribution: Stefan Nagtegaal commentedWorks as expected, RTBC.
Comment #34
webchickFixing a very minor code standards issue. Please don't credit me in the patch.
Confirmed this works again under PHP 4. Thanks. :)
This patch introduced some notices, but we can clean those up after code freeze.
Comment #35
ChrisKennedy CreditAttribution: ChrisKennedy commentedMight as well fix the other spacing error.
Comment #36
Dries CreditAttribution: Dries commentedCommitted to CVS HEAD. Thanks.
Comment #37
erdemkose CreditAttribution: erdemkose commentedDries, I think something went wrong. comment.js is not fixed by the patch you applied.
Comment #38
erdemkose CreditAttribution: erdemkose commentedcomment.js is fixed in commit #67988.
Comment #39
robertDouglass CreditAttribution: robertDouglass commentedThe cookie gets set for everybody, not just anonymous users. This is a bug. This patch removes some of the warnings and fixes the cookie bug: http://drupal.org/node/147417
Comment #40
(not verified) CreditAttribution: commented