Zend -> ZfcUser create new user after email verification/activation - email

I am working on a website, which already has a working registration form, using the ZfcUser module.
However,
I need to also be able to create a user via the admin page i've created.
Step by step it goes something like this:
Admin adds user by filling in first name, last name and email.
email gets sent to user.
user clicks validation link and gets redirected to website.
now the user only has to enter his desired password and he is done.
How would i be able to do this, if at all possible?

first of all, im not sure what would be the best aproach, but a few come to my mind.
I think the easier would be to load the register form in your admin, remember you can load it from any controller with the service manager, something like
$form = $sm->get('zfcuser_register_form');
and then you can work with it as you would do with any form, sending it to the view, and so.
You would have the full register form, with all the fields you have set as required in your zfcuser.global.php, including the password. I think it is good to set a temp password, and have the user change it later. also you could have its status as unconfirmed until the first password change.
If you dont want an specific field, you can take it out as you would with any form, by means of
$form->remove('element_name');
You would want to check the element names at ZfcUser\Form\Register
Also, remember that if you remove any field, you would have to modify the input filter, otherwise the validation will fail. For this, in your module's bootstrap, you should attach an event listener, something like this:
$em = $e->getApplication ()->getEventManager ();
$em->attach ( 'ZfcUser\Form\RegisterFilter', 'init', function ($e) {
$filter = $e->getTarget ();
//now modify the inputfilter as you need
});
Then, you will have to send the mail to the user. For that i will also use the event manager, at your bootstrap you register a listener for when the user is created, this is by means of
$sm = $e->getApplication ()->getServiceManager ();
$zfcServiceEvents = $sm->get ( 'zfcuser_user_service' )->getEventManager ();
$zfcServiceEvents->attach ( 'register.post', function ($e) {
$form = $e->getParam ( 'form' );
$user = $e->getParam ( 'user' );
//now you have all the info from the form and the already created user, so you can send the mail and whatever you need.
The last step, is to let the user change his password. To do this, i will send him to a module where you show the change password form, that you can retrieve with:
$sm->get('zfcuser_change_password_form');
or directly, sending him to the /user/change-password url that is one of the predefined with zfc-user.
I think this will be the cleanest way.
Another approach
If you dont like it that way, you can use another approach where you create your own form, fill it, save the data to a temp table, send the mail and then...when the user comes to set his password, you build a register form, with the fields pre-filled (and hidden, changing the input type to hidden, or by css) and let him send the form, so while he thinks he is sending just the password, actually he is sending all the registration form, and from here everything is like in normal registration.
For this solution you will also have to use the events, but probably you'd have to take a look at the register event,that is triggered when the form is sent, before the user is saved in the database, so you can modify any data you could need.
$zfcServiceEvents->attach ( 'register', function ($e) {
$form = $e->getParam ( 'form' );
And also you should take a look to the already mentioned init event, where you can retrieve the form before you show it to the user, and prefill any data from the temp table.
$events->attach ( 'ZfcUser\Form\Register', 'init', function ($e) {
$form = $e->getTarget ();
//now you set form element values from the temp table
Probably this is so confusing, but i hope you at least get a clue of where start from!

Related

CakePHP 3 how to edit user without changing password (hashed)

I have my UsersController with my edit.ctp view. When I browse /users/edit/1, I see password field filled with ***** (filled with hash in entity User.php, using DefaultPasswordHasher). My UsersTable.php has password has required.
So, I can try:
unset($user->password); // in edit() from UsersController.php
and setting [require => false] in edit.ctp
When I save, I get
The user could not be saved. Please, try again.
Because in my UsersTable.php I have:
$validator
->requirePresence('password', 'create')
->notEmpty('password');
If I try to leave blank from controller I get error, if I try to fill with actual password, it hashes again.
How could I edit any user without change his password? Can I set this from model or I need to make password as not required?
I don't need show the real password to admins
I validate from controller for password_confirm (already works)
In add.ctp there is no problem because default value is always blank
I want to change password only if password field is filled
I suppose password needs to be required in Model because all users need their passwords, that's why I'm trying to keep it far from validation in controller
Validation says "on create" but even in update is needed, bug possible?
My cake version is 3.4.4
Thanks in advance
Couple of things:
Firstly, if you haven't already, you may want to mark the password field as hidden to prevent it from exposing the hash in toArray calls or JSON views.
Secondly, any data field provided to patchEntity will be validated and saved (as you've discovered), even if the value for the field is blank.
If you look at the entity with debug($user) you'll notice it tracks which fields are "dirty", and since patchEntity saw you submitted a password field (even if it was blank), it set the User entity's password to blank and marked it as "dirty". Even if you later call unset($user->password) it's still got a record of it being dirty, and so it'll attempt to validate a value for it.
You could potentially mark the field clean with $export->setDirty('password', false); but then when a new password was submitted in the form it wouldn't be saved.
A better option would be to check if the password field was blank before calling patchEntity, and unset it then:
if ($this->request->is(['patch', 'post', 'put'])) {
$data = $this->request->getData();
if(empty($data['password'])){
unset($data['password']);
}
$user = $this->Users->patchEntity($user, $data);

How to display just students in users page(Moodle:/admin/user.php)

I want to display just students in moodle users page without manually adding a filter using the web interface. Could anybody help me on how to do?
You can create a link that shows only students but you'll need to post the data. Here's how I did it.
If you install WebDeveloper - http://chrispederick.com/work/web-developer/
Then go to /admin/user.php and click WebDeveloper, choose the "Forms" tab and "convert POSTS to GETS".
Choose the filter and click add filter. This will display a url with all the form fields. Moodle is expecting a POST rather than a GET though.
So copy and paste the url into a variable and use the single_button function with the post method eg:
$url = '/admin/user.php?sesskey=xxxxxxx&_qf__user_add_filter_form=1&mform_showmore_id_newfilter=1&mform_isexpanded_id_newfilter=1&realname_op=0&realname=&lastname_op=0&lastname=&firstname_op=0&firstname=&email_op=0&email=&city_op=0&city=&country_op=0&confirmed=&suspended=&profile_fld=0&profile_op=0&profile=&courserole_rl=5&courserole_ct=0&courserole=&systemrole=0&cohort_op=2&cohort=&username_op=0&username=&auth=&deleted=&addfilter=Add+filter';
echo $OUTPUT->single_button($url, get_string('student'), 'post');
Copy and paste your own url rather than the above.
You can probably remove a lot of the parameters. You should also get the roleid for the student and use the moodle_url function, eg:
$studentroleid = $DB->get_field('role', 'id', array('shortname' => 'student'));
$params = array('courserole_rl' => $studentroleid, 'courserole_ct' => 0, ... );
$url = new moodle_url('/admin/user.php', $params);
echo $OUTPUT->single_button($url, get_string('students'), 'post');
This is not possible, as, in Moodle, it is rare for someone to be assigned the role of 'student' at the system level (and if you did, they would have access to every course on the site).
The concept of 'student' in Moodle only makes sense at the course level.

Yii - creating a record for a related model and populating the parent form

this is my first stack overflow question, so I'm keeping my fingers crossed!
Scenario:
I have a relationship between contracts and customers, expressed in the model as:
'customer' => array(self::BELONGS_TO, 'Customer', 'customer_id'),
Now, this is fine - I can access my related model in the view without a problem.
What I want, however, is:
to add the ability to add a 'New Customer' button from within the Create Contract page (which is fine)
have it fire up the /views/customer/create form (which is also fine)
but then, once it's created, have it capture the new ID, close the window and return to the Create Contract page with the newly-created Customer ID pre-populated. I cannot for the life of me work out how to do this :(
Any help appreciated.
Gary
One way is this that when your actionSave() saves the customer you can redirect the page to something like
www.website.com/contract/create/CUSTOMER_ID
Now this way you can pass the user ID to the form and have it pre-populated.
With your contract create action being like : -
public function actionCreate($user_id = NULL){
...
$model = new Contract();
if($user_id)
//You can also check here if the user ID is valid or not
$model->user_id = $user_id;
$this->render('create', array(
'model' => $model
));
}
Another way is that you can put the user ID in session and redirect the user to Contract Create page and fetch the user ID there and again pass it to the model as above.
Hope it helps with the issue.

Altering a Drupal form after validation

I have a Drupal 7 form where after submitting it, some validation happens. It is taking the email address and doing a database look-up to see if that user already exists. If the user exists, I need to alter the form that re-renders on the page that normally displays the errors, removing some fields. Basically on the error page, regardless of any other validation errors they would have normally received (First name required, last name required etc.) they would only get one error message that says "that email address is already in the system" and then I no longer want to display ANY of the other fields at this point except the email address field and a file upload field. So I'm having trouble trying to figure out how to alter the form after the first submission based on some validation.
Thanks
What you want to do is add some data to the $form_state variable in your validation function that can inform your form function as to what fields it should provide.
Untested Example:
function my_form($form, &$form_state){
$form['my_field1'] = array('#markup' => 'my default field');
// look for custom form_state variable
if ($form_state['change_fields']) {
$form['my_field2'] = array('#markup' => 'my new field');
}
}
function my_form_validate($form, &$form_state){
// if not valid for some reason {
form_set_error('my_field1','this did not validate');
$form_state['change_fields'] = true;
// }
}

move from one action (signup) to confirm action (show the data submited) and success page Zend Framework

I am a newbie to Zend and creating a simple signup form but which has many fields. So I want to create a confirm page after the user signup action.
this is how my flow goes:
signup -> confirm ->success/error
My main reason for having a separate confirm form page is the data fields are so many so the user must go through to make sure they are all correctly filled.
using forms signup and confirm (with field disabled), I want to know if there is a way to pass the data from the signup form to confirm form?
Please any helpful ideas and suggestions welcomed
;)
public function signupAction()
{
$users = new Application_Model_Users();
$form = new Application_Form_RegistrationForm();
$this->view->form=$form;
if($this->getRequest()->isPost()){
if($form->isValid($_POST)){
$data = $form->getValues();
//some checks before sending data to confirm page
//not sure how the data can be passed to the confirm page from here
$this->_redirect('auth/confirmsignup');
}
}
}
public function confirmsignupAction()
{
$users = new Application_Model_Users();
$form = new Application_Form_ConfirmRegistrationForm();
$this->view->form=$form;
if($this->getRequest()->isPost()){
if($form->isValid($_POST)){
$data = $form->getValues();
//some checks before
unset($data['confirmPassword']);
$users->insert($data);
$this->_redirect('auth/login');
}
}
}
When redirecting, you will lose the POST data, unless:
You store it in session in signup and then read in confirmsignup
You don't redirect at all. Instead, after first submit check for existence of special data in your form, it may be a random token like hash of session id etc., but not easily guessable like "confirm=1". If the token does not exist, add a hidden field with this token to your form and show it to the user again in the same action, with data filled in - this will be the confirmation phase. If you have a POST in signup again, you will receive the token and by checking it exists, you will know this is the second submit with confirmation and you may proceed with the signup. I hope I didn't overcomplicate this.