Jump to content

Front-end form to let Member edit specific fields


modifiedcontent
 Share

Recommended Posts

How can I let a Member - or whatever Role - edit a specific field from the front-end?

If I do a search on "front-end editing" etc. a lot of stuff comes up that doesn't really fit my case. I'll use the front-end editing module for some cases, but in this case I am looking how to put a structure account management interface together. I also know there is now a login/register module, but I already have my own login/register system and don't want to start over. I also know about Form Builder, but that looks like overkill. I am trying to understand basic principles that I can use across my site, don't want a module "to do it all for me out of the box".

I had a front-end edit form for members that used to work fine, something like this with role checks etc.:

Spoiler

if($input->post->updateprofile) {

	$pass = $input->post->pass;
	
	if($pass) {
		if(strlen($pass) < 6) {
		$winorfail = 'Your new password must have at least six characters.';
	} else if($pass !== $input->post->pass_confirm) {
		$winorfail = 'Your passwords do not match.';
	} else {
		$user->of(false);
		$user->pass = $pass; 
		$user->save();
		$user->of(true);
		$winorfail = 'Your password has been changed.';
		}
	}

 $user->of(false); // turn off output formatting
 $user->fullname = $sanitizer->text($input->post->fullname);
 $user->body = $sanitizer->text($input->post->bio);
 $user->save();
}

 

But it no longer works. I know there is a better way to do that password update form - what is it...? - and it is probably a bad idea to mash up several things in one form. I also use Ckeditor on the bio/body field which may cause issues. I also had a messy profile picture upload in the form, years old, probably better ways to do that now.

So going back to basics, if I want to give logged-in Member a simple front-end form to edit a specific field, what would I put in the template? Which directions should I follow?

Link to comment
Share on other sites

2 hours ago, modifiedcontent said:

But it no longer works.

What does this mean exactly? No save? No post? ?

 

2 hours ago, modifiedcontent said:

if I want to give logged-in Member a simple front-end form to edit a specific field

Depends on the type of field. Plain text? Not repeaters by the looks of it. 

Maybe a little bit more info will help get better responses :-).

  • Like 1
Link to comment
Share on other sites

@kongondo, thank you again for your response. Yes, just a plain text field to start with, like a body field. Or/and the password field. Basic fields that a member role would need to edit.

I did not provide details on why it no longer works, because there could be many factors specific to my site/template, like the use of Ckeditor.

I just want to strip it down to the most basic working example. I was not able to find 2020 instructions, only threads from 2012-14 and information about Form Builder and the front-end editing and login/register modules.

Can you point me in the right general direction? Did anything change in upgrades since about 2016 that breaks the code/approach posted above or is it still basically the same?

Link to comment
Share on other sites

14 hours ago, modifiedcontent said:

most basic working example

Well, I just tested out this on PW 3.0.167, and it works as expected:

$user_roles       = user()->roles;
$user_roles_count = count($user_roles);

// make sure the current user has more than just default "guest" role
if (($user_roles_count > 1) && !input()->post->ts) {

    $u_name = user()->name;
    $u_id   = user()->id;
    $here   = page()->url;
    $ts     = time();

    $form = <<<EOF

<h1>Hello $u_name . Would you like to change your password?</h1>
<form method="post" action="$here">
    <label for="new_pass">New password:    
        <input type="password" id="new_pass" name="new_pass" autocomplete="false">
    </label>
    <label for="new_pass2">Confirm new password:
        <input type="password" id="new_pass2" name="new_pass2" autocomplete="false">
    </label>
    <input type="hidden" id="uid" name="uid" autocomplete="false" value="$u_id">
    <input type="hidden" id="uname" name="uname" autocomplete="false" value="$u_name">
    <input type="hidden" id="ts" name="ts" autocomplete="false" value="$ts">
    <button type="submit">Change your password</button>    
</form>

EOF;

    echo $form;

}

if (input()->post->ts && input()->post->new_pass && input()->post->new_pass2 && input()->post->uid) {
    $out        = '';
    $errCount   = 0;
    $form_uid   = input()->post->uid;
    $form_uname = input()->post->uname;
    $curr_uid   = user()->id;
    $curr_uname = user()->name;
    $form_new_pass  = input()->post->new_pass;
    $form_new_pass2 = input()->post->new_pass2;
    $form_ts        = (int)input()->post->ts;
    $max_time       = 30 * 60; // 30 minutes

    // If the POST arrives a half hour later, something is probably fishy
    if ($form_ts < (time() - $max_time)) {
        $errCount++;
        $out = "It seems that it took you longer than 30 minutes to change your password - your request has been blocked due to security concerns. Please try again.";
    }

    // user has maybe manipulated the hidden form input fields
    if (($curr_uid != $form_uid) || ($curr_uname != $form_uname)) {
        $errCount++;
        $out = "Your request has been blocked due to security concerns. Please try again.";
    }

    // for added security, I would highly suggest to take this note seriously @ https://cheatsheet.processwire.com/user/user-properties/user-pass/
    // "you will need to add your own complexity checks for passwords to ensure they meet a minimum length and character requirement."
    // I'm not sure if there is an API sanitizer method available for this purpose
    // below is just a basic check to ensure both pw-field values are identical
    if (($form_new_pass !== $form_new_pass2)) {
        $errCount++;
        $out = "Your new passwords do not match. Please try again.";
    }

    // If we've got that far, we're ready to update the user's PW
    if ($errCount < 1) {
        $user_page = users()->get($curr_uid);
        $user_page->of(false);
        $user_page->pass = $form_new_pass;
        $user_page->save();
        $out = "Success! Your account has been updated with the new password you've chosen.";
    }

    echo $out;

}

If syntax like user()->roles doesn't work in your installation, you can either enable it in site/config.php ($config->useFunctionsAPI = true;) or re-write it with $user / $page / $input notation.

  • Like 2
Link to comment
Share on other sites

Thanks @dragan. I actually have a super basic password update somewhere that works. I'll update that with some of your suggestions.

I stripped down my Member Account management script to bare essentials and it still doesn't work:

<?php 
if($input->post->updateprofile) {
 $user->of(false); // turn off output formatting
 $user->fullname = $sanitizer->text($input->post->fullname);
 $user->body = $sanitizer->text($input->post->bio);
 $user->save();
}
?>

<form method=post id=updateprofile>
    <div class=field>
    <label for=fullname>Full Name</label>
    <input placeholder='Firstname Lastname' type=text name=fullname value='<?php echo $user->fullname; ?>' />
    </div>

    <div class=field>
    <p>Please introduce yourself</p>
    <label for=bio></label>
    <textarea placeholder='biography or description' id=bio name=bio><?php echo $user->body; ?></textarea>
    </div>

    <div class=buttonrow>
    <button type=submit name=updateprofile>Update Profile</button>
    </div>
</form>

What am I missing?

Link to comment
Share on other sites

33 minutes ago, modifiedcontent said:

and it still doesn't work

Well, insert debug code (Tracy's d($var) or plain print_r() etc.) to see if any of your variables/functions doesn't do what you think it should.

body and fullname are certainly fields you have added to the user profile yourself, they're not part of the default user template. Perhaps you need to check those fields in the user template where it says "What fields can a user edit in their own profile?"

Link to comment
Share on other sites

body and fullname are both set to user-editable in their own profile; the code I have used to work, just no longer doesn't for some reason.

I set Access control for the User template to No*, but that didn't fix the edit forms.  * bad idea?

Should my general approach work or does anyone see obvious problems? This just doesn't seem to do anything:

if($input->post->updateprofile) {
 $user->of(false); // turn off output formatting
 $user->fullname = $sanitizer->text($input->post->fullname);
 $user->body = 'Just enter something when I click the updateprofile button';
 $user->save();
}

I have ProcessWire 3.0.161 dev, with as few modules as possible. This page should be all plain code. No hooks used. Code already simplified to bare essentials.

 

Link to comment
Share on other sites

24 minutes ago, dragan said:

Well, insert debug code (Tracy's d($var) or plain print_r() etc.) to see if any of your variables/functions doesn't do what you think it should.

Did you do any of that? Do you have Tracy Debugger installed? Do you have debug mode enabled? Did you check if you have any hooks activated that could block your code? Saying "it doesn't work" without trying to debug each line of code makes it difficult to find the culprit, and for those people trying to help you. We don't even know your PW version, or what modules you have installed.

For starters, what happens if you simplify the code and enter a few lines directly in the Tracy console (e.g. just edit the bio field). Does it work or not?

Link to comment
Share on other sites

How would I even use Tracy Debugger console for this? I want to test what happens in a Member account, where I don't have access to Tracy Debugger. I don't want to risk messing up my SuperUser admin account by running random code in that Debugger console.

What is Process Tracy Adminer that is suddenly also installed in my site? Tracy Debugger installs way more stuff than I am comfortable with and I have no clue how to use it to troubleshoot my particular problem.

The variables are fine. This used to work fine in my site. 

I was just looking for basics of how to edit a field via a simple form on the front-end. Is there an example anywhere? Has anything changed about that in the last few years?

This "works":

if($input->post->bio) {
 $user->of(false);
 $user->body = $sanitizer->text($input->post->bio);
 $user->save();
}

This doesn't:

if($input->post->updateprofile) {
 $user->of(false);
 $user->body = $sanitizer->text($input->post->bio);
 $user->save();
}

Both with a form like this:

<form method=post id=updateprofile>
    <textarea placeholder='biography or description' id=bio name=bio><?php echo $user->body; ?></textarea>
    <button type=submit name=updateprofile>Update Profile</button>
</form>

So I guess using <button> instead of <input> broke it? Apparently yes, changing it back to <input type=submit ... fixed it.

Link to comment
Share on other sites

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 account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...