valan Posted October 31, 2015 Share Posted October 31, 2015 There is a need to prevent duplicate user emails, e.g. ensure that users have unique emails. This requires email uniqueness checks to be performed each time email field is going to be saved. Please could you help with right hook for that and get/set methods in function call? E.g. how to get "old" and "new" email values. How to skip saving OR save if email is unique? Simple piece of code is preferred over words.) Thanks! P.S. Also, it would be good it admin gets error notification when tries to save user page with duplicate email. Link to comment Share on other sites More sharing options...
kongondo Posted October 31, 2015 Share Posted October 31, 2015 (edited) Andrey, With adapted code stolen from Soma here: https://processwire.com/talk/topic/4476-validating-field-before-page-save/ (post #2), you can do something like below in an autoload module. Be sure to read Soma's explanations as well in that post/thread. <?php class ValidateEmail extends WireData implements Module { /** * Return information about this module (required). * * @access public * @return array module info * */ public static function getModuleInfo() { return array( 'title' => 'Validate Unique Email', 'summary' => 'Ensure Uniqueness of Emails across site', 'author' => 'Kongondo, Soma', 'version' => 001, 'singular' => true, 'autoload' => true, ); } public function init(){ $this->addHookAfter("InputfieldEmail::processInput", $this, "validEmail"); } public function validEmail($event){ $field = $event->object; if($field->name == 'mail'){ $page = $this->modules->ProcessPageEdit->getPage(); $oldEmail = $page->get($field->name); $newEmail = $field->value; #$this->message("old value: $oldEmail"); #$this->message("new value: $newEmail"); $existEmail = $this->wire('pages')->get("id!=$page->id, template=basic-page, mail=$newEmail, mail!=''"); if($existEmail && $existEmail->id > 0) { $field->value = $oldEmail; $field->error($this->_("That email $newEmail is already taken mate; go fishing! :-)")); } } } } This will save if unique, keep old value if not unique and show error. I am not sure what you mean by admin gets error notification; you mean send them an email or log the error? I'll let you Google that Edited November 1, 2015 by kongondo 3 Link to comment Share on other sites More sharing options...
valan Posted November 7, 2015 Author Share Posted November 7, 2015 @kongondo - thanks! Re notification - its already in your code: $field->error($this->_("That email $newEmail is already taken mate; go fishing! :-)")); Link to comment Share on other sites More sharing options...
KarlvonKarton Posted September 6, 2016 Share Posted September 6, 2016 @kongondo or anybody else: If I want to check only the email address of users on duplicates, would it then be safe to say that the template must be "user" Thus not: $existEmail = $this->wire('pages')->get("id!=$page->id, template=basic-page, mail=$newEmail, mail!=''"); But: $existEmail = $this->wire('pages')->get("id!=$page->id, template=user, mail=$newEmail, mail!=''"); NEVER MIND, I found it myself. EDIT: but with one more issue (see below) <?php namespace ProcessWire; class ValidateEmail extends WireData implements Module { /** * Return information about this module (required). * * @access public * @return array module info * */ public static function getModuleInfo() { return array( 'title' => 'Validate Email module', 'summary' => 'Ensure Uniqueness of Emails across site', 'author' => 'Kongondo, Soma', 'version' => 001, 'singular' => true, 'autoload' => true, ); } public function init(){ $this->addHookAfter("InputfieldEmail::processInput", $this, "validEmail"); } public function validEmail($event){ $field = $event->object; if($field->name == 'email'){ // edited to my field $page = $this->modules->ProcessPageEdit->getPage(); $oldEmail = $page->get($field->name); $newEmail = $field->value; #$this->message("old value: $oldEmail"); #$this->message("new value: $newEmail"); $existEmail = $this->wire('pages')->get("id!=$page->id, template=user, email=$newEmail, email!=''"); // edited to my field if($existEmail && $existEmail->id > 0) { $field->value = $oldEmail; $field->error($this->_("That email $newEmail is already taken mate; go fishing! :-)")); } } } } Link to comment Share on other sites More sharing options...
KarlvonKarton Posted September 6, 2016 Share Posted September 6, 2016 A question: When I'm admin my modified module works great, but when a user tries to edit his/her email address, then I get: You do not have permission to execute this module - ProcessPageEdit Any ideas? ps: the user is in a role that allows profile-edit. Link to comment Share on other sites More sharing options...
KarlvonKarton Posted September 6, 2016 Share Posted September 6, 2016 (edited) This is the code which gives the error: $page = $this->modules->ProcessPageEdit->getPage(); It gives an error because in my case the users in role 'clients' have only permission to 'profile-edit' and not to 'page-edit'. Superuser has all the permissions, so that's why the module works as admin, but not as user. So I tried with following code: $page = $this->modules->ProcessProfile->getPage(); With the latter the user can edit the email field, but then the superuser gave errors. (I don't understand why) So, for now I have this workaround (which I don't really like): if ($this->user->hasRole('clients')) { $page = $this->modules->ProcessProfile->getPage(); }else{ $page = $this->modules->ProcessPageEdit->getPage(); } Feel free to comment. I'm sure there must be a better way. Edited September 6, 2016 by KarlvonKarton typo Link to comment Share on other sites More sharing options...
adrian Posted September 6, 2016 Share Posted September 6, 2016 Have you tried: $event->object->getPage(); Link to comment Share on other sites More sharing options...
KarlvonKarton Posted September 6, 2016 Share Posted September 6, 2016 12 minutes ago, adrian said: Have you tried: $event->object->getPage(); I have now, but that was not a success. (my eyes are still hurting - very red screen ) Link to comment Share on other sites More sharing options...
adrian Posted September 6, 2016 Share Posted September 6, 2016 Sorry wasn't really checking through everything properly. Take a look at how I am doing it for InputfieldPassword::render https://github.com/adrianbj/EmailNewUser/blob/master/EmailNewUser.module#L50 $process = $this->wire('process'); if($process instanceof WirePageEditor) { $userpage = $process->getPage(); if($userpage->is(Page::statusUnpublished)) $event->object->notes = 'NB: Because you chose to automatically generate the password for new users, you can leave these blank. However, if you do enter a password here, it will override the generated one.'; } 2 Link to comment Share on other sites More sharing options...
KarlvonKarton Posted September 6, 2016 Share Posted September 6, 2016 Could you elaborate a little more if you want? (I don't understand how it relates...) Link to comment Share on other sites More sharing options...
adrian Posted September 6, 2016 Share Posted September 6, 2016 Sorry, I shouldn't give advice without really checking into it. This is what you need: $event->arguments[0]->id That will get you the id of the user/page. BTW, the way I figured this out was to bd($event) inside the validEmail() function. With TracyDebugger installed I see this: bd($event, '$event', array('maxDepth' => 5)); Then to confirm, I did this: bd($event->arguments[0]->id); and got this: With the ID you can get the full user object like this: $uid = $event->arguments[0]->id; bd(wire('users')->get($uid)); See all the user fields under "settings" 3 Link to comment Share on other sites More sharing options...
adrian Posted September 6, 2016 Share Posted September 6, 2016 Actually just thought to go back and check the: $process = $this->wire('process'); bd($process->getPage()); and it works fine also: and: $process->getPage()->id returns 41 4 Link to comment Share on other sites More sharing options...
KarlvonKarton Posted September 7, 2016 Share Posted September 7, 2016 @adrian I've tried this: $page = $event->arguments[0]->id But it gave an error on this: $page->get($field->name); Link to comment Share on other sites More sharing options...
adrian Posted September 7, 2016 Share Posted September 7, 2016 I am not sure what you're trying to do with that. $event->arguments[0]->id returns the ID of the user page. You don't want to override the $page object ever. Given that we are talking about a user, the convention is often to use $u. $u = wire('users')->get($event->arguments[0]->id); but that is basically what I showed you up above. Link to comment Share on other sites More sharing options...
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now