Symfony Form - Value Object, DataMappers and EventSubscriber - forms

I am having trouble to dynamically modify field in my form using DataMapper and EventSubscriber.
Here is my form:
A select field
A field which will be modified by the select field above.
I am using an EventSubscriber to dynamically modify my form using AJAX.
And a DataMapper to map my Value Object to the form and vice-versa.
So when i do that:
$moneyForm = $this->createForm(MoneyType::class);
Everything is working. But when i pass my Value Object as data class:
$money = new Money(199, 'USD');
$moneyForm = $this->createForm(MoneyType::class, $money);
I got an error here:
public function mapDataToForms($viewData, $forms)
{
$forms = iterator_to_array($forms);
$forms['money']->setData($viewData ? $viewData->money() : 0);
$forms['currency']->setData($viewData ? $viewData->currency() : 'USD');
}
This error says that: Notice: Undefined index:.
It seems like the form has been replaced by a new one and i don't understand it.
I don't know why when i use a data mapper alone, or event subscriber alone everything is working.
But when i try to mix, both of them i got this error.
Does anyone have a clue of what's going on here?
Thank you

Related

Yii RBAC make Users update profile by himself

I'm trying to do this with mongodbauthmanager. I'm follow step by step in Usage section but finally i'm getting PHP warning: Illegal offset type. I had posted this question at Yii Extension before clone to SO:
Please tell me what is wrong?
1// Config
'authManager'=>array(
'class' =>'CMongoDbAuthManager',
'showErrors' => true,
),
2// Create auth items in db
$auth = new CMongoDbAuthManager();
$bizRule = 'return Yii::app()->user->id==$params["User"]->_id;';
$auth->createTask('updateSelf', 'update own information', $bizRule);
//I had tried with $auth->createOperation() but they has the same error
$role = $auth->createRole('user');
$role->addChild('updateSelf');
$auth->save();
and here is result in db
result in db http://i.minus.com/iIpXoBlDxaEfo.png
**3// Checking access in controller ** - UPDATE CODE AND ERROR
public function actionUpdate($id)
{
$model=$this->loadModel($id);
$params = array('User'=>$model);
if (!Yii::app()->user->checkAccess('updateSelf', Yii::app()->user->id,$params) )
{
throw new CHttpException(403, 'You are not authorized to perform this action');
}
//another statement ...
}
4// Getting error:
Fatal error : Cannot use object of type MongoId as array in F:\Data\03. Lab\www\yii\framework\web\auth\CAuthManager.php(150) : eval()'d code on line 1
RESOLVED PROBLEM
Base-on the answer of #Willem Renzema, I resolve my problem. Now, I update here and hope it useful for someone have this error.
0// First, config authManager with defaultRoles
'authManager'=>array(
'class'=>'CMongoDbAuthManager',
'showErrors' => true,
'defaultRoles'=> array('user'),//important, this line help we don't need assign role for every user manually
),
1// Fix save id in UserIdentity class
class UserIdentity extends CUserIdentity
{
private $_id;
//...
public function authenticate()
{
//...
$this->_id = (string)$user->_id;//force $this save _id by string, not MongoId object
//...
}
//...
}
2// Fix $bizrule in authe items
($bizrule will run by eval() in checkAccess)
//use _id as string, not MongoId object
$bizRule = 'return Yii::app()->user->id==(string)$params["User"]->_id;';
3// And user checkAccess to authorization
public function actionUpdate($id){
/**
* #var User $model
*/
$model=$this->loadModel($id);
$params = array('User'=>$model);
if (!Yii::app()->user->checkAccess('updateSelf', $params) )
{
throw new CHttpException(403, 'You are not authorized to perform this action');
}
//...
}
4// Done, now we can use checkAccess :D
First off, your original use of checkAccess was correct. Using Yii::app()->user->checkAccess() you are using the following definition:
http://www.yiiframework.com/doc/api/1.1/CWebUser#checkAccess-detail
Now, CWebUser's implementation of checkAccess calls CPHPAuthManager's implementation, which is where you encountered your problem with an illegal offset type.
http://www.yiiframework.com/doc/api/1.1/CPhpAuthManager#checkAccess-detail
An Illegal offset type means you are attempting to access an array element by specifying its key (also known as: offset) with a value that doesn't work as a key. This could be another array, an object, null, or possibly something else.
Your stack trace posted on the extensions page reveals that the following line gives the problem:
if(isset($this->_assignments[$userId][$itemName]))
So we have two possibilities for the illegal offset: $userId and $itemName.
Since $itemName is clearly a string, the problem must be with $userId.
(As a side note, the fact that your stack trace revealed surrounding code of this error also revealed that, at least for CPHPAuthManager, you are using a version of Yii that is prior to 1.1.11. Observe that lines 73 and 74 of https://github.com/yiisoft/yii/blob/1.1.11/framework/web/auth/CPhpAuthManager.php do not exist in your file's code.)
At this point I would have guessed that the problem is that the specified user is not logged in, and so Yii::app()->user->id is returning null. However, the new error you encountered when placing Yii::app()->user->id as the 2nd parameter of checkAccess reveals something else.
Since the 2nd parameter is in fact what should be the $params array that appears in your bizRule. Based on the error message, this means that Yii::app()->user->id is returning a mondoId type object.
I was unfamiliar with this type of object, so looked it up:
http://php.net/manual/en/class.mongoid.php
Long story short, you need to force Yii::app()->user->id to return the string value equivalent of this mondoId object. This likely set in your UserIdentity class in the components folder. To force it to be a string, simply place (string) to force a type conversion.
Example:
$this->_id = (string)$User->_id;
Your exact code will vary, based on what is in your UserIdentity class.
Then, restore your checkAccess to the signature you had before, and it should eliminate the Illegal offset error you encountered originally.
Note however that I have not used this extension, and while performing the following actions should fix this issue, it may cause new issues if the extension relies on the fact that Yii::app()->user->id is a mondoId object, and not a string.

Populate Tabular form field value with change of another field

There is a Tabular form with description, previous_value, unit_price fields in my Oracle Apex app.
I need to populate value of previous_value field with data on description field. I have a query to get value for previous_value field from database. i need to add onChange event to description field. with the changes in description field, value for previous_value field should be populate using my query.
how could i do this ?
You can bind the change event to the field in several ways. Target through the td headers,
or edit the column, and in the "Element attributes" field you could add a class (eg "fireAjax").
You can then bind to the event with either javascript code, or do this via a dynamic action.
You can do an ajax call in either of these 2 forms: through htmldb_Get or with jquery.post:
$('td[headers="ENAME"] input').change(function(){
var ajaxRequest = new htmldb_Get( null , $v('pFlowId') , 'APPLICATION_PROCESS=get_job' , $v('pFlowStepId'));
ajaxRequest.addParam('x01', $(this).val());
ajaxResult = ajaxRequest.get();
$(this).closest("tr").find("td[headers='JOB'] input").val(ajaxResult);
});
OR
$('td[headers="ENAME"] input').change(function(){
var that = this;
$.post('wwv_flow.show',
{"p_request" : "APPLICATION_PROCESS=get_job",
"p_flow_id" : $v('pFlowId'),
"p_flow_step_id" : $v('pFlowStepId'),
"p_instance" : $v('pInstance'),
"x01" : $(this).val()
},
function(data){
var eJob = $(that).closest("tr").find("td[headers='JOB'] input");
eJob.val(data);
},
"text"
);
});
With this application process, defined on the page with execution point "AJAX Callback":
Name: get_job
DECLARE
l_job emp.job%TYPE;
BEGIN
SELECT job
INTO l_job
FROM emp
WHERE ename = apex_application.g_x01;
htp.p(l_job);
EXCEPTION WHEN no_data_found THEN
htp.p('');
END;
Remember, handling errors and return in this process is up to you! Make sure you catch common errors such as no_data_found and/or too_many_rows. If they occur and are not trapped, chances are big you will encounter javascript errors because your javascript callback code can not handle the error (which in apex will be a full page html with the error message in it).
Also, as you can see i'm using the x01 variable, which is one of the 10 global temporary variables in apex. This way it is not required to use a page item and submit the value to session state for it.
If you want to put this code in a dynamic action you can. Pick "Change" as event and jQuery selector if you go for a dynamic action, and as true action pick execute javascript code. You can then put the function code in there. With the exception that $(this)will need to be $(this.triggeringElement)

Symfony2 - Multiple forms in one action

I implemented a page to create an instance of an entity and a user related to this. My problem is to bind the request after the submit.
Now i have this :
$formA = $this->createForm(new \MyApp\ABundle\Form\AddObjectForm());
$formB = $this->createForm(new \MyApp\UserBundle\Form\AddUserForm());
if ($request->getMethod() == 'POST')
{
$formA->bindRequest($request);
$formB->bindRequest($request);
if ($formA->isValid() && $formB->isValid())
{
}
// ...
}
With formA and formB extends AbstractType. But, naturally, $formA->isValid() returns false. How can I do to "cut" the request for example ?
If your forms are related and need to be processed and validated at once, consider using embedded forms. Otherwise, use a separate action for each form.
If you need to provide a select field to choose a user from existing ones, consider using an entity type field.
I know that has been a long time since the answer, but maybe if someone is looking for it this could be helpfull.
I've got two forms: user_form and company_form, and the submit has take place in the same function of the controller. I can know wich form has been submit with the follow code:
if ($request->getMethod() == 'POST') {
$data = $request->request->all();
if (isset($data['user_form'])) //This if means that the user_form has been submit.
{
The company_form will pass through the else.

Zend Form MutliCheckbox Validate Number of Checked Items

I have a Zend Form with a MutliCheckbox element.
I would like to validate the number of checked items, i.e. verify that exactly 3 items are checked.
Can I do it with any current validates or do I have to write my own?
Thanks.
You will have to write your own, but that's quite simple. There is a second optional argument on the isValid() method that gives you access to all the form values, and enables this way to validate against multiple inputs.
class MyValidator extends Zend_Validate_Abstract {
public function isValid($value, $formData = null){
//you can access to all the form values in the $formData, and check/count
//the values of your multicheckbox
//this is the super-quick way, but you could also add error messages
return $isValid;
}
}
and then add it to your element
$myElement->addValidator( new MyValidator());

Populate values to checkbox while editing in zend framework

I am trying to populate the values into check box. I want check box to be checked when there is value stored in database.
This is my code in form:
$form ['test_1'] = new Zend_Form_Element_Checkbox('test_1');
$form['test_1']->setLabel('test1')->setCheckedValue('1');
$form ['test_2'] = new Zend_Form_Element_Checkbox('test_2');
$form['test_2']->setLabel('test2')->setCheckedValue('2');
If there is value 1 in database i want first check box to be checked and if its 2 then 2nd checkbox needs to be checked.
What do i need to do in the controller.
Could anyone please help me on this issue.
The easiest way would be to fetch the values from the database as an array that maps to the form input elements, e.g. return a row like
array('test_1' => 'value of checkbox', 'test_2' => 'value of checkbox');
You could then simply call $form->populate($values) and let do Zend_Form do the setting, e.g. in your controller do
public function showFormAction()
{
$form = $this->getHelper('forms')->get('MyForm');
$data = $this->getHelper('dbGateway')->get('SomeTable');
$form->populate($data->getFormData());
$this->view->form = $form;
}
Note: the helpers above do not exist. They are just to illustrate how you could approach this. Keep in mind that you want thin controllers and fat models, so you should not create the form inside the controller, nor put any queries in there.