Reuse Zend 2 form with captcha for editing - forms

I have a form for some element creation with captcha.
It works fine.
But I want use this form in Admin page too, and there should be no captcha.
When I try to submit form I have an error
["captcha"] => array(1) {
["isEmpty"] => string(36) "Value is required and can't be empty"
}
How can I reuse this form without captcha? Is there another method without extending another new form?

Solved.
Just create Filter
use Zend\InputFilter\Input;
use Zend\InputFilter\InputFilter;
class FreeLessonFilter extends InputFilter
{
public function __construct()
{
$this->addElements();
}
protected function addElements()
{
$captcha = new Input('captcha');
$captcha->setRequired(TRUE);
$this->add($captcha);
}
}
And than use it in Admin page controller, but not in Index page
$this->defaultForm = new FreeLessonForm();
$filter = new FreeLessonFilter();
$filter->get('captcha')->setRequired(false);
$this->defaultForm->setInputFilter($filter);
By default it required, but in admin - not.

Related

zend framework 1 Form - Note element lost its value if there is validation error

I have a Note element in my zend framework 1 form used for registration. It is defined in the format:
$captcha_reload = new Zend_Form_Element_Note('captcha_reload',
array('value'=>"<div id='captcha_reload_div'>
<a href='javascript:return false;'
id='change-image'>Change text.</a></div>"));
$this->addElement($captcha_reload);
This element displays a hyperlink and displays perfectly during registration page call.
The problem is during form submission. This note element doesn't displays anything (ie missing the hyperlink) if there is form validation error.
I have checked and tried the code below:
$this->setDefaults(array('captcha_reload'=>"<div id='captcha_reload_div'>
<a href='javascript:return false;'
id='change-image'>Change text.</a></div>"));
But still there is no value if there is form validation error.
For Note element, I have included the following in the Zend Registration Form page:
class Zend_Form_Element_Note extends Zend_Form_Element_Xhtml
{
public $helper = 'formNote';
}
When the form is submitted it is over-riding the value property of your element. As there is nothing being submitted, when the form is echoed again to show form errors, the value of the element is nothing as well.
Perhaps adding an isValid function to the element?
// pseudo-code
public function isValid($value, $context = null) {
$this->_setValue("<div id='captcha_reload_div'><a href='javascript:return false;' id='change-image'>Change text.</a></div>");
return true;
}
This will reset the value to your custom text, and return true without doing any checks (as you know the value is what you want it to be). Subsequently, when the form echos again it will show the value as set in isValid
class Zend_Form_Element_Note extends Zend_Form_Element_Xhtml
{
public $helper = 'formNote';
public function isValid($value, $context = null)
{
return true;
}
}
I have added that isValid() into Note class and it works fine. It doesn't need to use _setValue() inside Note class.

ZEND: Displaying form error messages on failed validation

I have a form say:
class Application_Form_UserDetails extends Zend_Form
{
public function init()
{
$pswd = new Zend_Form_Element_Password('password');
$pswd->setLabel('New password:');
$pswd->setAttrib('size', 25);
$pswd->setRequired(false);
$pswd->addValidator('StringLength', false, array(4,15));
$pswd->addErrorMessage('Wron password');
}
}
In my user details controller class I have:
class UserDetailsController extends Zend_Controller_Action {
public function editAction()
{
$userId = $this->userInfo->id;
$DbTableUsers = new Application_Model_DbTable_User;
$obj = $DbTableUsers->getUserDetails($userId);
$this->view->formUser = new $this->_UserDetails_form_class;
$this->view->formCompany = new $this->_CompanyDetails_form_class;
if ($obj) {
$this->view->formUser->populate($obj);
}
$url = $this->view->url(array('action' => 'update-user-details'));
$this->view->formUser->setAction($url);
}
public function updateUserDetailsAction()
{
$formUser = new $this->_UserDetails_form_class;
if ($formUser->isValid($this->getRequest()->getPost())) {
}
else {
//validation failed
$formUser->markAsError();
$this->view->formUser = $formUser;
$this->_helper->redirector('edit', 'user-details');
}
}
}
The first time Edit action is called the form built and displayed.
User fills the form and sends it (updateUserDetailsAction is called).
In updateUserDetailsAction, on validation failure I mark the form as having errors and want to display the form with error messages that I previously set in updateUserDetailsAction class.
Then I redirect:
$this->_helper->redirector('edit', 'user-details');
in order to display the same form but with errors for the user to re-enter correct values.
The problem is I don't know how to let know the edit action that the form must display validation errors?
On $this->_helper->redirector('edit', 'user-details'); the form is redisplayed
as a new form with cleared erros but I need them displayed.
Do I do this the correct way?
regards
Tom
Problem comes from the fact that you are redirecting and in each method you are creating a new instance of the form, that means the form class is loosing its state - data you injected from the request and any other values passed to this object.
Combine editAction and updateUserDetailsAction into one method:
...
$formUser = new Form();
// populate the form from the model
if ($this->getRequest()->isPost()) {
if ($formUser->isValid($this->getRequest()->getPost())) {
// update the model
}
}
...
and have the form being submitted to the edit action. This will simplify your code and remove code duplication.
If you just wan to fix your code you can instantiate the form object in the init() method of your controller as set it as a property of your controller. This will way you will reuse same instance after redirection. I still think that solution above is much more compact and easier to understand for someone else.

Symfony: prevent form field from being saved

I have a form to change email, EmailChangeForm which extends the guard user form, sfGuardUserForm and uses two columns: email_address and password.
I want the form to check if the password is correct and if so, change the email to the new one.
My problem is that the form also saves the password field to the user object.
I know that since the password is checked, it cannot be changed in theory, but I still don't like it being re-saved with the new value from the form, so is there a way to make the form only save the email_address field?
I would suggest a sceleton like this :
class emailForm extends sfFrom {
public function configure(){
$this->widgetSchema['email'] = new sfWidgetFormInputText();
$this->widgetSchema['password'] = new sfWidgetFormInputPassword();
$this->validatorSchema['password'] = new myValidatorPassword();
}
}
class myValidatorPassword extends sfValidatorBase{
protected function doClean($value)
{
$clean = (string) $value;
// current user
$sf_guard_user = sfContext::getInstance()->getUser()->getGuardUser();
if($sf_guard_user)
{
// password is ok?
if ($sf_guard_user->checkPassword($value))
{
return $clean;
}
}
// Throw error
throw new sfValidatorError($this, 'invalid', array('value' => $value));
}
}
So in your action you can easily save the new password :
/***** snip *****/
if($this->form->isValid()){
// set and save new password to current user
$user = $this->getUser()->getGuardUser();
$user->setPassword($formValues["password"]);
$user->save();
/***** snip *****/
Of course this is a basic approach, improvements are always welcome :-)
First make sure you're using the useFields function in your EmailChangeForm class. With that you can define which fields you want to edit with your form (this is better than unset because if you add more fields you dont have to worry with useFields). Example:
$this->useFields(array(
'email'
));
DO NOT INCLUDE THE PASSWORD!
Second: In your template put an extra input field for your password with the same name schema (updatemail[password]).
Third: In your action before the $form->isValid method you add the following:
$params = $request->getParameter($form->getName();
unset($params['password'];
$form->bind($params), $request->getFiles($form->getName()));
if($form->isValid()) {...}
create the new form (editUserForm for example) that extend the base form and then unset the password by this code
class editUserForm extend baseForm{
public function configure(){
unset($this['password']);
}
}
all the name above is an example you must change it to your name.
I'm assuming there is only one field in EmailChangeForm, and that EmailChangeForm extends SfUserForm...
To eliminate all the fields except the email field add this to the configure method:
$this->useFields(array('email'));

Symfony: How to hide form fields from display and then set values for them in the action class

I am fairly new to symfony and I have 2 fields relating to my table "Pages"; created_by and updated_by. These are related to the users table (sfGuardUser) as foreign keys. I want these to be hidden from the edit/new forms so I have set up the generator.yml file to not display these fields:
form:
display:
General: [name, template_id]
Meta: [meta_title, meta_description, meta_keywords]
Now I need to set the fields on the save. I have been searching for how to do this all day and tried a hundred methods. The method I have got working is this, in the actions class:
protected function processForm(sfWebRequest $request, sfForm $form)
{
$form_params = $request->getParameter($form->getName());
$form_params['updated_by'] = $this->getUser()->getGuardUser()->getId();
if ($form->getObject()->isNew()) $form_params['created_by'] = $this->getUser()->getGuardUser()->getId();
$form->bind($form_params, $request->getFiles($form->getName()));
So this works. But I get the feeling that ideally I shouldnt be modifying the web request, but instead modifying the form/object directly. However I havent had any success with things like:
$form->getObject()->setUpdatedBy($this->getUser()->getGuardUser());
If anyone could offer any advice on the best ways about solving this type of problem I would be very grateful.
Thanks,
Tom
After processing and saving the form you could set those fields on the object and re-save:
protected function processForm(sfWebRequest $request, sfForm $form)
{
$form->bind($request->getParameter($form->getName()));
if ($form->isValid())
{
$page = $form->save();
$user = $this->getUser()->getGuardUser();
$page->setUpdatedBy($user);
if (empty($page->created_by))
{
$page->setCreatedBy($user);
}
$page->save();
$this->getUser()->setFlash('notice', 'Successfully saved page.');
$this->redirect('#homepage');
}
}
There's also a Doctrine extension called Blameable that automatically sets edited_by and created_by fields on specified models. The Doctrine website is undergoing some reorganization but here is the cached page for the extension.
To process your form create a new object, set the fields then save.
$article = new Article();
$article->setName($request->getParameter($form->getName());
$article->setDescription($request->getParameter($form->getDescription());
$article->setMetaKeywords($request->getParameter($form->getMetaKeywords());
$article->save();
What you want to do is customize your form and unset the 'created_at' and 'updated_at' pieces of the form in configure
class SampleForm extends BaseSampleForm
{
public function configure()
{
unset(
$this['created_at'],
$this['updated_at']
);
}
}
Then they won't show up in the form and will get the values setup by the "Timestampable" behavior before being saved
http://stereointeractive.com/blog/2010/04/07/symfony-forms-hide-created_at-updated_at-columns/

Zend_Form using subforms getValues() problem

I am building a form in Zend Framework 1.9 using subforms as well as Zend_JQuery being enabled on those forms. The form itself is fine and all the error checking etc is working as normal. But the issue I am having is that when I'm trying to retrieve the values in my controller, I'm receiving just the form entry for the last subform e.g.
My master form class (abbreviated for speed):
Master_Form extends Zend_Form
{
public function init()
{
ZendX_JQuery::enableForm($this);
$this->setAction('actioninhere')
...
->setAttrib('id', 'mainForm')
$sub_one = new Form_One();
$sub_one->setDecorators(... in here I add the jQuery as per the docs);
$this->addSubForm($sub_one, 'form-one');
$sub_two = new Form_Two();
$sub_two->setDecorators(... in here I add the jQuery as per the docs);
$this->addSubForm($sub_two, 'form-two');
}
}
So that all works as it should in the display and when I submit without filling in the required values, the correct errors are returned. However, in my controller I have this:
class My_Controller extends Zend_Controller_Action
{
public function createAction()
{
$request = $this->getRequest();
$form = new Master_Form();
if ($request->isPost()) {
if ($form->isValid($request->getPost()) {
// This is where I am having the problems
print_r($form->getValues());
}
}
}
}
When I submit this and it gets past isValid(), the $form->getValues() is only returning the elements from the second subform, not the entire form.
I recently ran into this problem. It seems to me that getValues is using array_merge, instead of array_merge_recursive, which does render to correct results. I submitted a bug report, but have not gotten any feedback on it yet.
I submitted a bug report (http://framework.zend.com/issues/browse/ZF-8078). Perhaps you want to vote on it?
I think that perhaps I must have been misunderstanding the way that the subforms work in Zend, and the code below helps me achieve what I wanted. None of my elements share names across subforms, but I guess this is why Zend_Form works this way.
In my controller I now have:
if($request->isPost()) {
if ($form->isValid($request->getPost()) {
$all_form_details = array();
foreach ($form->getSubForms() as $subform) {
$all_form_details = array_merge($all_form_details, $subform->getValues());
}
// Now I have one nice and tidy array to pass to my model. I know this
// could also be seen as model logic for a skinnier controller, but
// this is just to demonstrate it working.
print_r($all_form_details);
}
}
I have a same problem to get value from subforms I solve it with this but not my desire one
code:
in controller i get value with this code that 'rolesSubform' is my subform name
$this->_request->getParam ( 'rolesSubform' );
Encountered the same problem. Used post instead of getValues.
$post = $this->getRequest()->getPost();
There are times when getValues does not return the same values returned by $post.
Must be a getValues() bug.