How create a zend form object? - zend-framework

In my Users controller I have an editAction. The below declaration is from editAction.
$form = $this->_getEditForm();//here I need to pass $user->email to the form class.
I have another class _gerEditForm() in same controller.
private function _getEditForm()
{
$form = new Form_Admin_Users_Add(array(
'method' => 'post',
'action' => $this->_helper->url('edit', 'users'),
));
return $form;
}
enter code here
//form class
class Form_Admin_Users_Add extends Form_Abstract
{
public function __construct($mail=null)
{
parent::__construct();
$this->setName('user');
//$userId = new Zend_Form_Element_Text('userId');
//$userId->addFilter('Int');
//$this->addElement($userId);
$this->setAttrib('id', 'addUserForm');
$this->setAttrib('class', 'formInline');
$firstName = new Zend_Form_Element_Text('firstName');
$firstName->setRequired(true)
->addFilter('StringTrim')
->addValidator('NotEmpty', false, array('messages'=>'First name cannot be empty'))
->addValidator('StringLength', false, array(1, 256))
->setLabel('First Name:');
$this->addElement($firstName);
$lastName = new Zend_Form_Element_Text('lastName');
$lastName->setRequired(true)
->addFilter('StringTrim')
->addValidator('NotEmpty', false, array('messages'=>'Last name cannot be empty'))
->addValidator('StringLength', false, array(1, 256))
->setLabel('Last Name:');
$this->addElement($lastName);
$email = new Zend_Form_Element_Text('email');
$email->setLabel('Email :')
->addValidator('NotEmpty', false, array('messages'=>'email cannot be empty'))
->addFilter('StripTags')
->addFilter('StringTrim')
->addValidator('EmailAddress')
->addValidator(new BusinessForum_Validate_UniqueEmail($mail));
Now I need to pass the email the form class. But I don't know how to do this.
Please help me in this regard.
Thanks

I'm a bit confused. The __construct function takes one argument, $mail. You're passing that to your BusinessForum_Validate_UniqueEmail class.
But in your _getEditForm function, you're passing in an array to that $mail argument that looks like it has settings for the form, not email information.
If that's just how you named stuff, and that's how it works, fine. Then you should just need to add a second parameter to your __construct function:
public function __construct($mail=null, $emailAddress="")
Pass it in from your _getEditForm function:
private function _getEditForm($emailAddress="")
{
$form = new Form_Admin_Users_Add(array(
'method' => 'post',
'action' => $this->_helper->url('edit', 'users')
), $emailAddress);
return $form;
}
And pass the email address to your _getEditForm function:
$form = $this->_getEditForm($user->email);

Related

Injecting variables into Forms __construct function Zend 2

I am trying to prepopulate a form's drop down options via data stored statically in the module.config.php in Zend 2 and am running into a problem which entails:
I try to get the Servicemanager in the __construct() function but it is unavailable.
I move the element declarations to another function within the form class so I can pass variables into it but the view controller cannot find the elements.
I currently call the form via a Servicemanager Invokable. How can I pass these arrays into the form's __construct() function?
Here is the code:
class ILLForm extends Form
{
public function __construct($fieldsetName, $campuses, $ILLTypes, $getFromOptions)
{
parent::__construct('create_ill');
$this
->setAttribute('method', 'post')
->setHydrator(new ClassMethodsHydrator(false))
->setInputFilter(new InputFilter())
;
$ill = new ILLFieldset('ill', $campuses, $ILLTypes, $getFromOptions);
$ill->setName('ill')
->setOptions(array(
'use_as_base_fieldset' => true,
));
$captcha = new Element\Captcha('captcha');
$captchaAdapter = new Captcha\Dumb();
$captchaAdapter->setWordlen(5);
$captcha->setCaptcha($captchaAdapter)
->setLabelAttributes(array('class' => 'sq-form-question-title'))
->setAttribute('class', 'sq-form-field required')
->setLabel("* Captcha")
->setAttribute('title', 'Help to prevent SPAM');
$submit = new Element\Submit('submit');
$submit->setAttribute('value', 'Submit ILL')
->setAttribute('class', 'sq-form-submit')
->setAttribute('title', 'Submit ILL');
$this->add($ill)
->add($captcha)
->add($submit);
}
}
The Indexcontroller Factory that calls the Form:
class IndexControllerFactory implements FactoryInterface
{
public function createService(ServiceLocatorInterface $controllers)
{
$allServices = $controllers->getServiceLocator();
$sm = $allServices->get('ServiceManager');
$smConfig = $allServices->get('config');
$campuses = $smConfig['campuses'];
$illCategories = $smConfig['ILLCategories'];
$getFromOptions = $smConfig['getFromOptions'];
$controller = new IndexController();
$controller->setCampuses($campuses);
$controller->setILLCategories($illCategories);
$controller->setGetFromOptions($getFromOptions);
$controller->setILLForm($sm->get('ILL-form'));
$controller->setILLFormFilter($sm->get('ILL-form-filter'));
//$controller->setParams($sm->get('params'));
return $controller;
}
}
and the relevant module.config.php excerpt:
'service_manager' => array(
'abstract_factories' => array(
'Zend\Cache\Service\StorageCacheAbstractServiceFactory',
'Zend\Log\LoggerAbstractServiceFactory',
),
'invokables' => array(
'ILL-form-filter' => 'ILL\Form\ILLFormFilter',
'ILL-form' => 'ILL\Form\ILLForm',
),
I ended up taking the form out of the service manager invokables in module.config.php (removed line for 'ILL-form') and call it from the indexControllerFactory.php instead
$create_ill = new Form\ILLForm('create_ill', $campuses, $illCategories, $getFromOptions);
$controller->setILLForm($create_ill);
instead of
$controller->setILLForm($sm->get('ILL-form'));

PHP-Unit Tests: how to implement a TYPO3 Extbase object interface

I have some problems with the PHP UnitTests for my Controller:
this is the function in my controller code that has to be tested
public function newAction(\ReRe\Rere\Domain\Model\Fach $newFach = NULL) {
// Holt die übergebene Modulnummer
if ($this->request->hasArgument('modul')) {
// Holt das Modul-Objekt aus dem Repository
$modul = $this->modulRepository->findByUid($this->request->getArgument('modul'));
}
// Ausgabe in der View
$this->view->assignMultiple(array(
'newFach' => $newFach, self::MODULUID => $modul->getUid(), 'modulname' => $modul->getModulname(), 'modulnummer' => $modul->getModulnr(), 'gueltigkeitszeitraum' => $modul->getGueltigkeitszeitraum()
));
}
this is the PHPUnit-Test code for the function
public function newActionAssignsTheGivenFachToView() {
$fach = new \ReRe\Rere\Domain\Model\Fach();
$modul = array('');
$MockGetArgument = $this->getMock('ReRe\Rere\Domain\Repository\ModulRepository', array('getArgument'), array(), '', FALSE);
$MockGetArgument->expects($this->any())->method('getArgument')->with('modul');
$mockRequest = $this->getMock('TYPO3\\CMS\\Extbase\\Mvc\\Request');
$mockRequest->expects($this->any())->method('hasArgument')->with('modul');
$this->inject($this->subject, 'request', $mockRequest);
$objectManager = $this->getMock('TYPO3\\CMS\\Extbase\\Persistence\\ObjectManager', array(), array(), '', FALSE);
$this->inject($this->subject, 'objectManager', $objectManager);
$modulRepository = $this->getMock('ReRe\\Rere\\Domain\\Repository\\ModulRepository');
$modulRepository->expects($this->any())->method('findByUid')->will($this->returnValue($modul));
$this->inject($this->subject, 'modulRepository', $modulRepository);
$view = $this->getMock(self::VIEWINTERFACE);
$view->expects($this->any())->method(self::ASSIGN)->with('newFach', $fach);
$this->inject($this->subject, 'view', $view);
$this->subject->newAction($fach);
}
I keep getting this error as I run the test
Error in test case newActionAssignsTheGivenFachToView
File: /Applications/MAMP/typo3_src/typo3/sysext/extbase/Classes/Mvc/Controller/AbstractController.php
Line: 162
Argument 1 passed to TYPO3\CMS\Extbase\Mvc\Controller\AbstractController::injectObjectManager() must implement interface TYPO3\CMS\Extbase\Object\ObjectManagerInterface, instance of Mock_ObjectManager_fa2fde18 given, called in /Applications/MAMP/typo3_src/typo3/sysext/core/Tests/BaseTestCase.php on line 260 and defined
And this is the line from AbstractController.php that was called
public function injectObjectManager(\TYPO3\CMS\Extbase\Object\ObjectManagerInterface $ObjectManager) {
$this->ObjectManager = $ObjectManager;
$this->arguments = $this->ObjectManager->get('TYPO3\\CMS\\Extbase\\Mvc\\Controller\\Arguments');
}
How can I implement this interface TYPO3\CMS\Extbase\Object\ObjectManagerInterface ?
I really appreciate every answers ! I have been trying and looking for answers for weeks :(
UPDATE 18.02.2015: PROBLEM SOLVED
CONFIGURED CODE:
$fach = new \ReRe\Rere\Domain\Model\Fach();
$modul = new \ReRe\Rere\Domain\Model\Modul();
$request = $this->getMock(self::REQUEST, array(), array(), '', FALSE);
$request->expects($this->once())->method('hasArgument')->will($this->returnValue($this->subject));
$modulRepository = $this->getMock(self::MODULREPOSITORY, array('findByUid'), array(), '', FALSE);
$modulRepository->expects($this->once())->method('findByUid')->will($this->returnValue($modul));
$this->inject($this->subject, 'modulRepository', $modulRepository);
$request->expects($this->once())->method('getArgument')->will($this->returnValue($this->subject));
$this->inject($this->subject, 'request', $request);
$view = $this->getMock(self::VIEWINTERFACE);
$view->expects($this->once())->method('assignMultiple')->with(array(
'newFach' => $fach,
'moduluid' => $modul->getUid(),
'modulname' => $modul->getModulname(),
'modulnummer' => $modul->getModulnr(),
'gueltigkeitszeitraum' => $modul->getGueltigkeitszeitraum()
));
$this->inject($this->subject, 'view', $view);
$this->subject->newAction($fach);
You are mocking the wrong (inexistent) ObjectManager. The correct namespace is TYPO3\\CMS\\Extbase\\Object\\ObjectManager.
So the correct line should be $objectManager = $this->getMock('TYPO3\\CMS\\Extbase\\Object\\ObjectManager', ...);
Otherwise I wonder why you mock the ObjectManager at all. You don't use it in your method.
One side note: Your code will fail if there is no 'modul' inside the request. Then $modul is not set and you will call getUid(), getModulname(), ... on an non-object.

symfony 2 Add values in a collection form in

I'm trying to add values into each element of a collection from a multiple form, but I got this :
Call to a member function getQuestions() on a non-object
What is the correct syntax?
This is my code:
$repository = $this->getDoctrine()->getManager()
->getRepository('***Bundle:Projet');
$projet = $repository->find($projetid);
$formBuilder = $this->createFormBuilder($projet);
$formBuilder->add('questions','collection',array(
'type' => new QuestionType(),
'allow_add' => true,
'allow_delete' => true
));
$form = $formBuilder->getForm();
if ($request->getMethod() == 'POST') {
$form->bind($request);
if ($form->isValid()) {
$em = $this->getDoctrine()->getManager();
$membreid = $this->getUser()->getId();
$questions = $projet->getQuestions();
//I'm gonna do a loop here
$questions[0]->setMembreId($membreid);
$projet->addQuestion($questions[0]);
$em->persist($projet);
$em->flush();
return $this->redirect($this->generateUrl('***_nouveau_projet',array('etape' => 3, 'id' => $projet->getId() )));
}
}
return $this->render('***:nouveau_projet.html.twig',array(
'form' => $form->createView(),
'etape' => $etape,
'projet' => $projetid,
));
The error message you got provides relevant clues about what's going wrong.
getQuestions() is called on a non object.
Make sure $project is an instance of ***Bundle:Projet and that
$repository->find($projetid); is returning a valid object.
Probably that the given $projetid doesn't match any record in your date source.

Validate a set of fields / group of fields in Zend Form

Is there any good solution for the following requirements:
A form with one field for zip code and default validators like number, length, etc.
After submission, the form is checked against a database.
If the zip code is not unique we have to ask for an city.
Examples:
Case 1: Submited zip code is unique in database. Everything is okay. Process form
Case 2: Submited zip code is not unique. Add a second field for city to the form. Go back to form.
We want to handle this in an generic way (not inside an controller). We need this logic for
a lot of forms. First thought was to add it to isValid() to every form or write a
validator with logic to add fields to the form. Subforms are not possible for us, because we need this for different fields (e.g. name and street).
Currently I'm using isValid method inside my forms for an User Form to verify the password and confirm password field. Also, when the form is displayed in a New Action, there are no modifications, but when displayed in an Edit Action, a new field is added to the form.
I think that is a good option work on the isValid method and add the field when the validation return false, and if you want something more maintainable, you should write your own validatator for that purpose.
Take a look at my code:
class Admin_Form_User extends Zf_Form
{
public function __construct($options = NULL)
{
parent::__construct($options);
$this->setName('user');
$id = new Zend_Form_Element_Hidden('id');
$user = new Zend_Form_Element_Text('user');
$user->setLabel('User:')
->addFilter('stripTags')
->addFilter('StringTrim')
->setAllowEmpty(false)
->setRequired(true);
$passwordChange = new Zend_Form_Element_Radio('changePassword');
$passwordChange->setLabel('Would you like to change the password?')
->addMultiOptions(array(1 => 'Sim', 2 => 'Não'))
->setValue(2)
->setSeparator('');
$password = new Zend_Form_Element_Password('password');
$password->setLabel('Password:')
->addFilter('stripTags')
->addFilter('StringTrim')
->setRequired(true);
$confirm_password = new Zend_Form_Element_Password('confirm_password');
$confirm_password->setLabel('Confirm the password:')
->addFilter('stripTags')
->addFilter('StringTrim')
->addValidator('Identical')
->setRequired(true);
$submit = new Zend_Form_Element_Submit('submit');
$submit->setLabel('Save');
$this->addElements(array($id,$name,$lastname,$group,$user,$passwordChange,$password,$confirm_password,$submit));
$this->addDisplayGroup(array('password','confirm_password'),'passwordGroup');
$this->submit->setOrder(8);
$this->setDisplayGroupDecorators(array(
'FormElements',
array('HtmlTag', array('tag' => 'div','id' => 'div-password'))
)
);
$passwordChange->clearDecorators();
}
public function addPasswordOption()
{
$this->changePassword->loadDefaultDecorators();
$this->getDisplayGroup('passwordGroup')
->addDecorators(array(
array('HtmlTag', array('tag' => 'div','id' => 'div-password'))
)
);
$this->password->setRequired(false);
$this->confirm_password->setRequired(false);
}
public function setPasswordRequired($flag = true)
{
$this->password->setRequired($flag);
$this->confirm_password->setRequired($flag);
}
public function isValid($data)
{
$confirm = $this->getElement('confirm_password');
$confirm->getValidator('Identical')->setToken($data['password']);
return parent::isValid($data);
}
}
So, in my controller:
public function newAction()
{
$this->view->title = "New user";
$this->view->headTitle($this->view->title, 'PREPEND');
$form = $this->getForm();
if($this->getRequest()->isPost())
{
$formData = $this->_request->getPost();
if($form->isValid($formData))
{
$Model = $this->getModel();
$id = $Model->insert($formData);
$this->_helper->flashMessenger('The user data has beed updated.');
$this->_helper->redirector('list');
}
}
$this->view->form = $form;
}
public function editAction()
{
$this->view->title = "Edit user";
$this->view->headTitle($this->view->title, 'PREPEND');
$id = $this->getRequest()->getParam('id');
$form = $this->getForm();
// Add yes or no password change option
$form->addPasswordOption();
$Model = $this->getModel();
if($this->getRequest()->isPost())
{
$formData = $this->getRequest()->getPost();
// Change password?
if($formData['changePassword'] == 2) $form->setPasswordRequired(false);
if($form->isValid($formData))
{
$Model->update($formData);
$this->_helper->flashMessenger('The user data has beed updated.');
$this->_helper->redirector('list');
}
}
$data = $Model->getById($id)->toArray();
$form->populate($data);
$this->view->form = $form;
}
You will probably need a Javascript form validator for that. In the submit function perform an AJAX call to check if the zipcode is unique. If not, show an extra city field.
But you still have to perform the validation server side: never trust user input, even if it's validated on the client side.

Zend Form Text value stays null

I've created a simple upload-form and got a little problem when submitting the data.
The file is uploaded correctly, but my little description field stays null.
Here's my form:
class Upload_Form_Uploadvideo extends Zend_Form{
public function init()
{
$this->setName('video')
->setAction('interface/videoupload')
->setMethod('post');
#id
$id = new Zend_Form_Element_Hidden('id');
$id->addFilter('Int');
#Textfield "Videofile"
$video = new Zend_Form_Element_File('videofile', array(
'label' => 'Videofile')
);
$video->setDestination(APPLICATION_PATH.'/upload/video/toConvert/');
#Textfield "Videofile"
$desc = new Zend_Form_Element_Text('videodescription', array(
'label' => 'Description')
);
$desc->setAttrib('value','The description is not optional!');
$desc->setAttrib('size','25');
#Submit
$submit = new Zend_Form_Element_Submit('submit', array('label' => 'Upload Video'));
$submit->setAttrib('id', 'submitbutton');
#bringing everything together
$this->addElements(array($id,$video,$desc,$submit));
}
}
the controller, giving it to the view:
public function videouploadAction()
{
#in production this code goes to the index()
if(!$this->getRequest()->isPost()){
return $this->_forward('index');
}
$form = $this->getForm();
$this->view->via_getpost = var_dump($this->_request->getPost());
$this->view->via_getvalues= var_dump($form->getValues());
}
Now, I var_dump $this->_request->getPost() and $form->getValues().
The output is the following:
array[$this->_request->getPost()]
'id' => string '0' (length=1)
'MAX_FILE_SIZE' => string '134217728' (length=9)
'videodescription' => string 'This is a test-video' (length=20)
'submit' => string 'Upload Video' (length=12)
array [$form->getValues()]
'id' => int 0
'videofile' => string 'swipeall.avi' (length=12)
'videodescription' => null
In addition, I set the "value"-attrib, without any effect. I intended to write something in the box, when the user loads the site.
I'm new to Zend, so I guess I'm just overseeing something stupid, though I can't find it.
Update:
I really had to get the $_POST-Data via
$formdata = $this->getRequest()->getPost();
use
$desc->setValue('The description is not optional!');
instead of
$desc->setAttrib('value','The description is not optional!');