How to retrieve value from array and present in the field in admin orded data? - custom-fields

I have a question. I have plugin Furgonetka installed on woocommerce. Package numbers are collected from Furgonetka service in meta_key tracking_info like:
Array
(
[520000016902796077744528] => Array
(
[courierService] => inpostkurier
)
)
In data base it is presented like: a:1:{s:24:"520000016902796077744528";a:1:{s:14:"courierService";s:12:"inpostkurier";}}
I have added the function in functions.php to show field tracking_info in admin order data:
add_action( 'woocommerce_admin_order_data_after_order_details', 'add_admin_order_field' );
function add_admin_order_field( $order ){
woocommerce_wp_text_input(
array(
'id' => 'tracking_info',
'label' => __( 'Tracking number', 'your-text-domain' ),
'value' => get_post_meta( $order->get_id() , 'tracking_info', true ),
'wrapper_class' => 'form-field-wide',
)
);
}
But field presents only value "Array".
Do you know how to retrieve package number (which is for example 520000016902796077744528) and present in the field tracking_info?
I want to show package number in the field tracking_info.

Related

Symfony3 get the value of a non mapped field in event listener

Trying to make a form that a user chooses an option and depending on their choice loads additional fields. So far I have a UserSignupType:
class UserSignupType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('userType', ChoiceType::class, array(
'choices' => array(
"Subscriber" => "Subscriber",
"Friend" => "Friend"
),
'expanded' => true,
'mapped' => false
));
$builder->addEventListener(
FormEvents::PRE_SET_DATA,
function (FormEvent $event) {
$form = $event->getForm();
$usertype = $form->get('userType')->getData(); //updated per JBaffords answer
if($userType == "Subscriber")
{
$builder->add('agency', EntityType::class, array(
"class" => "\AppBundle\Entity\Agency",
"label" => "name"));
}
elseif($userType == "Friend")
{
$builder->add('phoneNumber', PhoneNumberType::class, array(
'default_region' => 'US',
'format' => PhoneNumberFormat::NATIONAL));
}
}
);
}
// ...
}
not sure if the getData method is the right method to use, and if it is, i need to somehow get the "userType" field out of it. I cant call getUserType because its not an actual mapped property and I don't want it to be. It simply decides the fields to show.
You can get the value for any form element (mapped or unmapped) by doing:
$form->get('fieldName')->getData();
get() returns a Form object, so if you have a nested form, you can continue to call ->get('nextFieldName') on each child until you get to the form element you need.
The value returned from getData for a form is going to depend on (amont other things) the mapping of its child elements. If the form has no children, then its value is its value; the mapping just determines whether that value is populated into its parent's data.
In your specific case, to get the data for the userType element, you would do:
$userType = $form->get('userType')->getData();

Zend framework 2 filters

When I use InputFilter required is not considered in int filters
$inputFilter->add($factory->createInput(array(
'name' => 'id',
'required' => true,
'filters' => array(
array('name' => 'Int'),
),
)));
You need to use allowEmpty attribute in order to force your InputFilter component to reject empty values.
$inputFilter->add($factory->createInput(array(
'name' => 'id',
'required' => true,
'allowEmpty' => false, // <--- Look ma
'filters' => array(
array('name' => 'Int'),
),
)));
Are you sure you want to use the Int InputFilter? Its function is to convert a scalar value to an Integer. Its code is just:
public function filter($value)
{
return (int) ((string) $value);
}
Which transforms the value to a string. If your value is an empty string, it'll convert it to 0, the reason why afterwards, in the validator's execution process, the required is not working (it checks a 0).
It seems to me, because of the name id of your input, that you just want to force users to enter something that must be a numeric. You can do it this way:
$inputFilter->add( $factory->createInput( array(
'name' => 'id',
'required' => true,
'validators' => array(
array( 'name' => 'Digits' ),
)
) );

ZF2 Validator Context when using a Fieldset or Collection

Is it possible to pass the full form as the context to a validator?
I would like to create a conditional validator for element X in fieldset A which checks the value of element Y in a different fieldset B.
The problem is that the isValid function only receives the context for the fieldset it is in. This element X knows nothing about element Y.
All answers greatly received!
You can do this with collections and ZendCollectionInputFilter yeah.
There's not like loads of documentation for this, know the zend guys are sorting this out though (think the only mention of it is in http://framework.zend.com/apidoc/2.2/classes/Zend.InputFilter.CollectionInputFilter.html) but for now a resource that really helped me was this:
http://www.aronkerr.com/2013/11/zf2-form-collection-validation-unique.html
Very clever stuff once you get your head round these. Can't really give you much more help as your question isn't massively specific and there is no code for your form, fieldsets and input filters that you currently have implmented but hope this helps. If you get stuck at any point more than happy to run through more specific code
Let's say our fieldsets A and B belong to the form Sample. We need to add the validators from this parent form in order to access the context of this form when validating any child fieldsets:
<?php
namespace App\Form;
use Zend\Form\Form;
use Zend\InputFilter\InputFilterProviderInterface;
class Sample extends Form InputFilterProviderInterface
{
public function init()
{
$this->add([
'type' => 'App:Fieldset:A',
'name' => 'fieldsetA',
]);
$this->add([
'type' => 'App:Fieldset:B',
'name' => 'fieldsetB',
]);
$this->add([
'type' => 'submit',
'name' => 'submit',
'attributes' => [
'value' => 'Submit',
],
]);
}
public function getInputFilterSpecification()
{
return [
'fieldsetA' => [
'type' => 'InputFilter',
'X' => [
'required' => true,
'allow_empty' => true,
'continue_if_empty' => true,
'validators' => [
[
'name' => 'Callback',
'options' => [
'callback' => function ($value)
{
if ($this->data['fieldsetB']['Y'])
{
// do something
}
// do something else
},
],
],
],
],
],
];
}
}
Notice how we add validators to X in A from within Sample using the InputFilter type. Next we access $this->data directly and traverse it to get Y in B.

How to add a class to all labels in a ZF2 form

I'm using a jQuery plugin that takes the text from labels associated with form elements and puts them as default text for the fields themselves. (You can find the plugin here.)
Here's the catch: it can only do this if the label has the class "inline". Now, I know I can use the following code to do this:
$this->add(array (
'name' -> 'name',
....
'options' => array (
'label' => 'Name',
'label_attributes' => array (
'class' => 'inline'
)
)
));
This will work fine, and if it has to be done item by item, then so be it. But I was wondering if there's some way I can add the class to ALL labels associated with text and text area form elements without using JavaScript. I'm thinking this would either done by a plugin, or by looping through all the elements in the form, but I don't know how to do either.
You could extend the FormRow view helper.
Here is a little example:
use Zend\Form\View\Helper\AbstractHelper;
use Zend\Form\View\Helper\FormRow;
class CustomFormRow extends FormRow
{
public function render(ElementInterface $element) {
...
$label = $element->getLabel();
if (isset($label) && '' !== $label) {
// Translate the label
if (null !== ($translator = $this->getTranslator())) {
$label = $translator->translate(
$label, $this->getTranslatorTextDomain()
);
}
$label->setAttribute('class', 'inline');
}
...
if ($this->partial) {
$vars = array(
'element' => $element,
'label' => $label,
'labelAttributes' => $this->labelAttributes,
'labelPosition' => $this->labelPosition,
'renderErrors' => $this->renderErrors,
);
return $this->view->render($this->partial, $vars);
}
...
}
You could probably leave the rest as it is and you should be good to go once you add some configuration in your Module.php for your view helper.
public function getViewHelperConfig() {
return array(
'factories' => array(
'CustomFormRow' => function($sm) {
return new \Application\View\Helper\CustomFormRow;
},
)
);
}
In your template files you now have to use your viewHelper instead.
<?php echo $this->CustomFormRow($form->get('yourelement')); ?>

How to include CJuiAutoComplete in a CGridView filter?

I have a grid view that lists contents of a table, table has column author_id.
Now I'm displaying usernames using relation name column syntax author.username.
Is it possible to allow user to type in a username in column filter, with support of CJuiAutoComplete, some examples hints?
My code sample:
<?php $this->widget('zii.widgets.grid.CGridView', array(
'dataProvider'=>$model->with('author')->search(),
'filter'=>$model,
'columns'=>array(
// ...
array(
'name'=>'author.username',
'filter'=> // ?
),
// ...
),
));
The widget has a 3rd parameter that can be set to true which means that will return a string and will not render the widget CJuiAutoComplete.
widget('zii.widgets.grid.CGridView', array(
'dataProvider'=>$model->with('author')->search(),
'filter'=>$model,
'columns'=>array(
// ...
array(
'name'=>'author.username',
'filter'=> $this->widget('zii.widgets.jui.CJuiAutoComplete', $array_params, true),
),
// ...
),
));
and $array_params can be replaced with similar as following ex :
array(
'name'=>'author_username',
//'model'=>$model,
'attribute'=>'city_eve',
'sourceUrl'=>"/controller/action/",
'options'=>array(
'minLength'=>'2',
),
'htmlOptions'=>array(
'size'=>'36'
),
)
and also you have to put in your model search method some checks :
if($request->getQuery("author_username")){
$criteria->addCondition(author.username=:author_username");
$criteria->params[':author_username'] = $request->getQuery("author_username");
}

Resources