Unique profile field as the name suggests, provides an option to make the profile fields created by the profile (core) module, unique.
After installing and enabling, this module will provide an option to make any profile field unique on its edit page. This is generally at admin/user/profile/edit/%fid .
If this option is checked, the module will let users only enter unique values for that field. The check for uniqueness is performed on the registration page (if any profile fields are used on the registration form); and when a user tries to add or update general profile information.
This project is similar to unique field. However, unique field does not provide an option for making profile fields unique. Which is where the inspiration for this project comes from.
Possible use-case: A company that lets user's register against a Unique identifier provided by a third party: like a social security number or a PAN number. This field then has to be unique.
There are two possible alternatives to using this module:
1: Use the username as a unique field for registration and other purposes. However, this limits you to using only one field as unique.
2: Use content profile in conjunction with unique field.
Project page at http://drupal.org/sandbox/vrun/1173080
I've uploaded the module files through git to the project above. However, I am attaching the module files as a zip file to this post for convenience.
| Comment | File | Size | Author |
|---|---|---|---|
| #40 | drupalcs-result.txt | 4.36 KB | klausi |
| #24 | mysql.png | 11.2 KB | v-a-1 |
| #13 | unique_profile_field.zip | 2.8 KB | v-a-1 |
| #4 | unique_profile_field.zip | 2.38 KB | v-a-1 |
| #2 | unique_profile_field.zip | 2.64 KB | v-a-1 |
Comments
Comment #1
v-a-1 commentedFound and removed a dsm() call.
Filled out the missing description for schema.
Please ignore above attachement.
Use this one instead for review.
Comment #2
v-a-1 commentedI didn't realise there were very specific coding standards that I need to adhere to.
Ran through coder and fixed all problems.
Please ignore above.
Use the following attachment for review.
Git updated too.
Comment #3
joachim commentedI'm not sure the folder 1173080 should be in your git repo...
// $Id$
This line is now obsolete.
> hook_form_alter
Consider using hook_form_FORM_ID_alter for the first if() block here; it makes the code easier to read.
> // get profile fields configured as unique in {unique_profile_fields}
Comments should be a sentence: capital, full stop.
Other than that, looks fairly complex and messy, but I've worked with Profile module myself and I know that's just necessary ... :/
Comment #4
v-a-1 commentedThanks for the review.
I've removed the outdated CVS $Id$ from all files. I've also removed the unwanted directory from the git repo.
Regarding hook_form_alter: I'd rather I keep it the way it is. Its a small function which checks three forms. If I were to use hook_form_FORM_ID_alter, I would have to end up defining at least two functions and still do if() checks inside the second one.
Have changed the comments to properly constructed sentences.
Have also changed the formatting so that its a little more readable and make it seem a little less complex :).
Updated to git.
Attached the same here.
Thanks again.
BTW Did you get a chance to test the functionality though?
Comment #5
v-a-1 commentedComment #6
alliax commentedThat's what I'm looking for, thanks, do you plan on creating a real module page for this, or to integrate it in unique field module?
Comment #7
v-a-1 commentedThis is a working module alliax. I've submitted it here for review so that I can put it up as a real project page once its approved.
You can download the latest zip file above, and use it. I would really appreciate it if you could provide feedback about it here once you have.
Thanks.
Comment #8
alliax commentedHi, I have downloaded it, and installed it. I have gone to /admin/user/profile and I edited one of the user profile fields and set it as unique.
It did nothing, so I don't know if it does something (any checking) to previous (over 1,000) users.
So from now on, I guess this field's uniqueness is protected in future users registrations.
Comment #9
joachim commented> I edited one of the user profile fields and set it as unique.
Incidentally... how do you handle an existing profile field with existing data which is possibly non-unique being set to unique?
Comment #10
v-a-1 commentedCurrently, all existing profile fields remain untouched.
Uniqueness check is only performed on new field creation and existing field update.
For instance: say out of 1000 users, there are 4 with the same x value in a particular field that is designated as unique.
When any of the 4 users tries to update their profile information, they will not be able to do so with the value x.
If all 4 users update their profiles, the last one to do so won't be forced to enter a new value for the field containing x.
And of course no user will be allowed to create a new field with the same x value.
--
Perhaps an option can be provided after install where you can choose what you want to do with old data. Something like:
[]Auto-increment non-unique data for this field.
[]Leave data untouched.
[]...
This could be a per field or a global setting.
I don't think this should be too difficult to implement.
I did originally design the module thinking that one would generally want to install something like this pre-production. Because making a decision to make an existing field unique on a production site, means there is some major change in business logic itself. And I don't know whether the module should address that.
Having said that, if you think this would be a useful feature, do let me know and I could try to implement it.
Comment #11
joachim commented> I did originally design the module thinking that one would generally want to install something like this pre-production. Because making a decision to make an existing field unique on a production site, means there is some major change in business logic itself.
Yup.
Simplest of all would be to lock the setting on fields with data, but that's a bit draconian.
Otherwise, you could run queries when a field is changed to unique and just warn the user that there is duplicate data, and show a list of the duplicates.
Comment #12
v-a-1 commented> Simplest of all would be to lock the setting on fields with data, but that's a bit draconian.
I agree. Locking settings seems a bit over the top.
> Otherwise, you could run queries when a field is changed to unique and just warn the user that there is duplicate data, and show a list of the duplicates.
I think this is a very sensible suggestion. I am going to try and implement this.
Thanks.
Comment #13
v-a-1 commentedI've implemented the feature that notifies the user if any existing values in a field are duplicate.
This notification is shown when a profile field's settings are updated and the user has turned on the option to make the field unique.
Have updated git.
http://drupalcode.org/sandbox/vrun/1173080.git/tree/ab724fa
Also find attached.
I am wondering though, how does this project actually get approved? I mean the module works, the code meets the coding standards, and the feature the module provides is currently not available. Do I need to do something more? I am a little unclear as to the next steps. Should I change the status to "reviewed and tested by the community"? Or someone else does that?
Comment #14
jordojuice commentedApplicants cannot approve their own module. The process is this: one of us will set the status to "Reviewed and tested by the community" once we feel the review has sufficiently addressed all screening, coding, and security issues, and once that is done a git administrator will come along and grant you the git vetted user role. Since joachim has been conversing with you here, it is up to him as to where the review moves at this point. But, beware, the majority of project applications are taking around a month or more to review right now, so if your review slows down don't get discouraged - we have not forgotten about you and there are still things that need to be done. The queue is backed up, but we are working hard to reduce the backlog. We appreciate your patience and understanding in this process.
By the way, I won't set this to "Needs work" for this, but you need to add a README.txt file outlining the steps to install and configure the module.
Comment #15
jordojuice commentedBy the way. Considering the lengthy backlog and your understanding the the Drupal API and standards, we endorse and encourage you reviewing project applications yourself. If youd like to help shorten the queue, this is one way you can accomplish this. You don't have to conduct a full code/security review. You can even check other applications in the queue to ensure they have README files, are not duplicate modules, have no LICENSE files, and have been run through the coder module. You're welcome to come join the code review group at http://groups.drupal.org/code-review as well.
Comment #16
joachim commented> you need to add a README.txt file outlining the steps to install and configure the module.
Unless your install procedure is weird or has special steps, you can just assume the reader knows the normal procedure for installing Drupal modules.
Comment #17
v-a-1 commentedjordojuice, thanks for the prompt and helpful response. I will definitely try and review other modules as and when I find some time. Frankly, I had no clue that I could review modules.
Regarding the README.txt file, I understand from joachim's response that this isn't necessary, since this module is fairly straightforward to use. And, I assume anybody trying to use this module will at least read the description of the same, which delineates how the module functions. However, if this is a necessity let me know, and I will add a README.txt.
Also, I'm curious: what does the pdx-code-review tag that you attached signify?
joachim, thanks again for keeping this module on your radar. I look forward to further feedback. Already, I think the module is better for implementing your suggestion of notifying the user of duplicates.
Speaking of which, did you get a chance to test this new feature?
Awaiting your thoughts.
Comment #18
v-a-1 commentedbump
Comment #19
joachim commentedThis seems to be coming along nicely.
I do see a few places where your SQL could do more work.
Eg:
Couldn't you do all this with just:
Also, could unique_profile_field_check_existing_data() do its work with a COUNT ... GROUP BY ... query? Or would that not account for case differences (eg 'foo' / 'FOO')?
> unique_profile_field_get_value
That would be better named unique_profile_field_field_is_unique() perhaps?
Comment #20
v-a-1 commentedThanks joachim.
I don't know why it din't occur to me to use JOIN instead of two separate queries. I have fixed this:
http://drupalcode.org/sandbox/vrun/1173080.git/tree/577d5b6
___
Also, could unique_profile_field_check_existing_data() do its work with a COUNT ... GROUP BY ... query? Or would that not account for case differences (eg 'foo' / 'FOO')?
I remember doing something like:
SELECT value FROM profile_values WHERE fid = %d GROUP BY value HAVING ( COUNT(value) > 1 )while designing it originally, and yes you are right -- the query above would consider "test", "TEST" and "TeSt" as the same value and return a count greater than 1. I remember reading somewhere, something about doing a GROUP BY hex(value), which would return a case sensitive match. But it seemed convoluted and would have been indecipherable when read by someone else.
___
unique_profile_field_get_value -- That would be better named unique_profile_field_field_is_unique() perhaps?
I use the get and set value naming combination as a convention that I find convenient in my head to deal with. I do realize that since the function returns a 0 or a 1 it could be used as a boolean check, and thus named. But I think I prefer the naming the way it is.
Comment #21
joachim commented> SELECT value FROM profile_values WHERE fid = %d GROUP BY value HAVING ( COUNT(value) > 1 )
How about:
SELECT COUNT(value) AS field_value_occurrence_count FROM profile_values WHERE fid = %d GROUP BY value HAVING ( field_value_occurrence_count > 1 )
Small change but makes it much clearer what you're counting and why you care about it :)
Comment #22
v-a-1 commentedSELECT COUNT(value) AS field_value_occurrence_count FROM profile_values WHERE fid = %d GROUP BY value HAVING ( field_value_occurrence_count > 1 )
This will still return a case-insensitive match. I need it to consider "test" and "TEst" as different values. GROUP BY considers both as the same value and so returns a count greater than 1. Which is incorrect in this context. To make it case-sensitive I would need to do something like:
SELECT COUNT(value) AS field_value_occurrence_count FROM profile_values WHERE fid = %d GROUP BY hex(value) HAVING ( field_value_occurrence_count > 1 )
This will work correctly, since the hex value for "test" and "TEst" will be different, but will be the same for "test" and "test".
What I don't know is whether the above statement should be used considering its an unorthodox SQL statement, specifically the hex part.
Comment #23
joachim commentedThis works for me in a test table:
SELECT COUNT(bar) AS occurrences, bar FROM foo GROUP BY LOWER(bar) HAVING occurrences > 1
Bear in mind you should select the value too so you can print out useful information.
Comment #24
v-a-1 commentedI think you are mistaken, joachim.
For instance:
lower("TEST") will translate to "test", as will lower("TeSt"), lower("test") or lower("Test").
This would again end up leading to the same thing: Case insensitive match, and thus fields that are in fact unique will be considered as non-unique.
however hex("TEST") is different than hex("test"), which would lead to correct results.
Please see the attached image. The test table has the values "Test" and "test" in it, along with five occurrences or "100000", and some other random values. The first result in the image is incorrect. The second one is correct.
I could simply use HEX and put a comment explaining why.
Comment #25
joachim commented> Case insensitive match, and thus fields that are in fact unique will be considered as non-unique.
Oh. We've maybe been talking cross-purposes.
I would consider 'test' and 'TEST' to be the same, and therefore non-unique.
Comment #26
v-a-1 commented> I would consider 'test' and 'TEST' to be the same, and therefore non-unique.
This would be acceptable in say a field that contains a name or something where the case doesn't matter.
But, what about say if the field contains unique registration codes which are entered by the user during registration and which are stored as a profile field. And say these codes are originally generated randomly by a script and mailed to the user. In this case, case-sensitive match is a must because otherwise two unique codes like uxfTT56 and UXFtt56 will end up being considered as the same, effectively disallowing registration of the later user. (This is in fact is a real use-case on one of my sites)
However during the course of this conversation, I did modify the function code slightly to try out with HEX (Find below). Functionally of course its no different. It doesn't even translate to lesser code. But perhaps is a bit clearer in terms of what its trying to do. What do you think? If it does make things clearer then I will update the existing function code.
Comment #27
v-a-1 commentedComment #28
v-a-1 commentedComment #29
joachim commentedYou might want to consider a setting for whether uniqueness is case-sensitive or not.
Also, a thought: are you checking for whitespace? Would 'John' and 'John ' count as different? Should they?
Comment #30
v-a-1 commented>You might want to consider a setting for whether uniqueness is case-sensitive or not.
Good idea. Have implemented it. Updated git:
http://drupalcode.org/sandbox/vrun/1173080.git/tree/3de6792
>Also, a thought: are you checking for whitespace? Would 'John' and 'John ' count as different? Should they?
I haven't thought about this. Good point. I think I should simply trim the values.
So 'John ' == 'John' == ' John', but
'John' != 'J ohn' != 'Jo hn '
What do you think?
If agreed, will implement.
Currently am not even using trim().
Thanks.
Comment #31
v-a-1 commentedHad inadvertently removed descriptions from schema in the install file in the last update.
Have fixed it.
http://drupalcode.org/sandbox/vrun/1173080.git/tree
Comment #32
v-a-1 commentedbump
Comment #33
v-a-1 commentedI am just hoping that someone will look into this. It's been 1.5 months since my last substantive post, and haven't yet received any feedback/review.
Comment #34
klausiSome minor things:
* Git release branch missing, see http://drupal.org/node/1015226
* install file: add an extra newline between one function and the next doc block
* README.txt is missing
Comment #35
v-a-1 commentedDone.
http://drupalcode.org/sandbox/vrun/1173080.git/tree/8a695744f69d47c3e16c...
Comment #36
klausiComment #37
v-a-1 commentedHave implemented all the changes as recommended
http://drupalcode.org/sandbox/vrun/1173080.git/tree/7d17820
One question though:
I did remove the t() calls for db field descriptions as suggested, but why is it that a lot of other modules I went through do this?
Comment #38
v-a-1 commentedComment #39
asrobv-a-1, "do not run database field descriptions through t(), this will just create overhead for translators" as klausi said, that's why you should remove it.
Anyway I've been using it for a while and it's working well. Therefore I think it's rtbc.
Comment #40
klausiThere are still files other than README.txt in the master branch, make sure to remove them. See also step 5 in http://drupal.org/node/1127732
Review of the 6.x-1.x branch:
This automated report was generated with PAReview.sh, your friendly project application review script. You can also use the online version to check your project. Get a review bonus and we will come back to your application sooner.
manual review:
Comment #41
v-a-1 commented@asrob: Thanks! I am glad it works for you.
@klausi: Thanks for the detailed and helpful review. Especially for the manual review.
Have updated as per your recommendations.
http://drupalcode.org/sandbox/vrun/1173080.git/tree/f2afd1e
Thanks again.
Comment #42
jthorson commentedVerified that major issues in #40 have been addressed.
This has been in the hopper *way* too long ... let's let contrib address any further issues. *wink*
Comment #43
klausiThanks for your contribution, v-a-1! Welcome to the community of project contributors on drupal.org.
I've granted you the git vetted user role which will let you promote this to a full project and also create new projects as either sandbox or "full" projects depending on which you feel is best.
Thanks, also, for your patience with the review process. Anyone is welcome to participate in the review process. Please consider reviewing other projects that are pending review. I encourage you to learn more about that process and join the group of reviewers.
As you continue to work on your module, keep in mind: Commit messages - providing history and credit and Release naming conventions.
Thanks to the dedicated reviewer(s) as well.
Comment #44
v-a-1 commented@klausi: Thanks, this is great!
A big thanks to all the reviewers too.
Comment #46
emi_bcn commentedHi all,
Just posting the link to the finally released module:
http://drupal.org/project/unique_profile_field
Thanks everybody for doing it possible!!
emi
Comment #47
crevillo commentedHi all.
Even last message in this thread is March 30, 2012, project page shows only a 6.x release.
Where can i find the 7.x if si there any? maybe from git?
Thank you.
Comment #48
alliax commentedIt says on the module's page "This module is not required for drupal 7."
I don't know why since I've never installed a Drupal 7 yet, but I guess that's because the functionality must be included in Drupal 7 somehow. You have to investigate.
Comment #49
crevillo commentedi see... but i can't find where that functionality may be. i'll keep trying.
thanks anyway.
Comment #50
alliax commentedI don't know as I said I didn't install D7, but I can see at least one such module who could do it:
http://drupal.org/project/field_validation
Look on the project page: Unique
Perhaps it is not even needed in D7, no idea.
Comment #51
crevillo commenteddon't worry. i finally added a custom validation for those fields. thanks a lot for your time.