Foreach form in array validation - php

Thanks for reading :D
I'm creating a online order system. You will see 3 inputs. Partnumber, Quantity and Price. You will only fill in Partnumber and Quantity. Price will be checked trough my database for the right price. I tried to create that function, still not working. But anyway. I included a jQuery function so you can add extra lines into the form when you want to order more products.
A little snippet so you know what i am meaning.
$('#addpart').click(function(){
var loop = $('#loop').val();
var html;
html = '<p>';
html += '<input type="text" name="part[]" style="margin-left:20px;" class="text medium" id="part" placeholder="SP partnumber" />';
html += '<input type="text" name="qty[]" style="margin-left:20px;" class="text small" placeholder="Qty" />';
html += '<input type="text" style="margin-left:20px;" class="text small" id="price" placeholder="Price" tabindex="-1" readonly />';
html += '</p>';
for (i = 0; i < loop; i++) {
$("#form").append(html);
}
});
So when your post this form we dont know how many fields it will be. Sometimes it will be 5 order lines, sometimes 10.
So i start using [] in my input field.
The input name attribute will be like this: "part[]".
The form will be validated with the class Validation.
To show my class this page will be very long ghehe.
Here is a little snippet how to use this class/function so you know the structure.
if(toxInput::exists()){
if(toxtoken::check(toxInput::get('token'))){
$toxValidate = new toxValidate();
$toxValidation = $toxValidate->check($_POST, array(
'name' => array(
'required' => true,
'min' => 2,
'max' => 50
)
));
if($toxValidation->passed()){
etcetcetc..
So with the order form it should be something like this:
$toxValidate = new toxValidate();
$toxValidation = $toxValidate->check('$_POST', array(
'part1' => array('required' => TRUE, 'maxlength' => 14),
'part2' => array('required' => TRUE, 'maxlength' => 14),
'part3' => array('required' => TRUE, 'maxlength' => 14),
'part4' => array('required' => TRUE, 'maxlength' => 14),
'part5' => array('required' => TRUE, 'maxlength' => 14)
));
How can i print this line 'part1' => array('required' => TRUE, 'maxlength' => 14) for every filled in line. I tried serveral ways with foreach and [].
All didnt work.. :(

I suppose that you need to extend your Validation class to be able to validate arrays in the most comfortable way.
You can try to handle array variables like this (just an example):
$toxValidate->check($_POST, [
'name' => [
'required' => TRUE,
'min' => 2,
'max' => 50,
],
'qty' => [
'required' => TRUE,
'array' => TRUE,
'min' => 2,
'max' => 14,
],
]);
Under the hood of your Validation class, just loop through the values of the passed qty array if is_array($toxValue) and apply your rules to every member of that array (min, max, etc.).
Also, I suggest to refactor your Validation class: use callbacks or class member functions to call separate validation rules (not the best OOP-way, but feasible for easy cases). Like this:
class Validation
{
...
public function ruleMax($value)
{
... // Validate value max
}
public function ruleMin($value)
{
... // Validate value min
}
}
With this approach you won't need to fully rewrite your check function if you need to add more validation rules to your class (or subclass).
By the way, I suggest to see how it's made in popular frameworks like Laravel:
https://laravel.com/docs/5.4/validation#validating-arrays
And the class itself as an easy example (not the best of course) of rules decoupling: https://github.com/laravel/framework/blob/5.1/src/Illuminate/Validation/Validator.php

Related

Prestashop 1.6 add tinymce field to admin preferences

I'm trying to add a new field to Admin Preferences - a textarea field with tinymce. I've added code to AdminPreferencesController.php:
$this->fields_options['contact'] = array(
'title' => $this->l('Contact'),
'icon' => 'icon-cogs',
'submit' => array('title' => $this->l('Save')),
);
$this->fields_options['contact']['fields']['PS_CONTACT_ADDITIONAL_INFO'] = array(
'type' => 'textarea',
'label' => $this->l('Short description'),
'name' => 'short_description',
'lang' => true,
'cols' => 60,
'rows' => 10,
'autoload_rte' => 'rte',
'col' => 6,
);
But tinymce doesnt' appear and when I'm using HTML tags after saving they disappear. Presta strips all HTML tags.
How to allow HTML tags on this field and enable tinymce?
It seems that you can't just add it in a regular way. But you can implement it in a next way.
First of all, use field type textareaLang instead of textarea and add a parameter 'validation' => 'isCleanHtml' to this field
$this->fields_options['contact']['fields']['PS_CONTACT_ADDITIONAL_INFO'] = array(
'type' => 'textareaLang',
'label' => $this->l('Short description'),
'name' => 'short_description',
'lang' => true,
'cols' => 60,
'rows' => 10,
'col' => 6,
'validation' => 'isCleanHtml'
);
Create your own script to initialize your editor. I created a script tinymce.init.js and put it to js/admin/ folder
$(document).ready(function(){
ad = ''; // this is defenition of the external plugin path. I didn't fint how it can impact on script if it's empty but by default it it the path to your admin folder
iso = iso_user;
var config = {
selector: '.textarea-autosize'
};
tinySetup(config);
});
Then include tinymce script and your own to this controller AdminPreferencesController.php
public function setMedia()
{
$this->context->controller->addJquery();
$this->context->controller->addJS(
array(
_PS_JS_DIR_.'admin/tinymce.init.js',
_PS_JS_DIR_.'tiny_mce/tiny_mce.js',
_PS_JS_DIR_.'admin/tinymce.inc.js'
)
);
parent::setMedia();
}
It should implement your requirements. But don't forget that now you should call your configuration field in multilingual scope. So, add a language id to Configuration::get() like
Configuration::get('PS_CONTACT_ADDITIONAL_INFO, $id_lang)
whenever you use it.
P.S. Bear in mind that the best solution for your goal is to create a simple module which will handle this. And far more, it is recommended way.

TYPO3 Custom Element colorpicker

I'm new to TYPO3 (first project) and I have some understanding issues of the creation of a custom element with a colorpicker. In this project I already have created a few elements but I only use predetermined fields for the backend input. For the element I need next I need the user to choose a color. I haven't found a fitting existing element. My setup that doesn't work is in the TCA/Overrides/tt_content.php file and looks like this.
$GLOBALS['TCA']['tt_content']['item_0']=array();
$GLOBALS['TCA']['tt_content']['item_0']['label']='Color';
$GLOBALS['TCA']['tt_content']['item_0']['config']=array();
$GLOBALS['TCA']['tt_content']['item_0']['config']['type']='input';
$GLOBALS['TCA']['tt_content']['item_0']['config']['renderType']='colorpicker';
$GLOBALS['TCA']['tt_content']['item_0']['config']['size']=10;
$GLOBALS['TCA']['tt_content']['types']['wo_mitem'] = array(
'showitem' => '--palette--;LLL:EXT:cms/locallang_ttc.xlf:palette.general;general,
header;Title,
subheader;Background,
header_link;Target,
item_0;Color,
bodytext;Text;;richtext:rte_transform[flag=rte_enabled|mode=ts_css]
');
The item_0 was a try to create a colorpicker but it doesn't seem to work. Do I need something different in a different file? The first few lines I added to define my field. Is there a better way to do this?
All other files in my custom extension work (since all other custom elements work fine). The only difference is, as said, the need of a way to choose a color in the new one.
Just for a clearer look here the other files
setup.txt:
lib.contentElement {
templateRootPaths {
100 = EXT:wostyle/Resources/Private/Template
}
}
tt_content {
wo_mitem < lib.contentElement
wo_mitem {
templateName = MItem
}
}
tt_content.php
\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addPlugin(
array(
'WO_Item (ItemBox, Text only)',
'wo_mitem',
'content-image'
),
'CType',
'wostyle'
);
$GLOBALS['TCA']['tt_content']['item_0']=array();
$GLOBALS['TCA']['tt_content']['item_0']['label']='Farbe';
$GLOBALS['TCA']['tt_content']['item_0']['config']=array();
$GLOBALS['TCA']['tt_content']['item_0']['config']['type']='input';
$GLOBALS['TCA']['tt_content']['item_0']['config']['renderType']='colorpicker';
$GLOBALS['TCA']['tt_content']['item_0']['config']['size']=10;
$GLOBALS['TCA']['tt_content']['types']['wo_mitem'] = array(
'showitem' => '--palette--;LLL:EXT:cms/locallang_ttc.xlf:palette.general;general,
header;Bezeichnung,
subheader;Chemische Bezeichnung,
header_link;Zielseite,
item_0;Farbe,
bodytext;Text;;richtext:rte_transform[flag=rte_enabled|mode=ts_css]
');
typo.ts
mod.wizards.newContentElement.wizardItems.wo_extra {
header = WO Elemente
after = common
elements {
wo_mitem {
iconIdentifier = content-image
title = WO_Item (ItemBox, Text only)
description = Ein Produktfeld mit Text
tt_content_defValues {
CType = wo_mitem
}
}
}
show := addToList(wo_mitem)
}
MItem.html
<div class="item-text">
<f:link.typolink parameter="{data.header_link}">
<div class="item-front">
<f:if condition="{data.subheader}!=''">
<f:then>
<div class="item-bg">
<f:format.html>{data.subheader}</f:format.html>
</div>
</f:then>
</f:if>
<div class="item-title">
<f:format.html>{data.header}</f:format.html>
</div>
</div>
<div class="item-back">
<f:format.html>{data.bodytext}</f:format.html>
</div>
</f:link.typolink>
</div>
<f:debug>{data}</f:debug>
EDIT: I use typo3 8.7.8
I did not check your whole code but I have a working color-picker on a field ...
you're close but an error that pops up right away is that your item should be placed under ['columns'] ...
$GLOBALS['TCA']['tt_content']['columns']['item_0']=array();
next you are missing the refference to the wizard !! (you should adopt the annotation with square brackets which shows much more the structure)
this should be stored in Configuration/TCA/Overrides/tt_content.php: (when you override existing fields, otherwise you have a dedicated code for the element)
<?php
/***************
* Modify the tt_content TCA
*/
$tca = [
'columns' => [
'item_0' => [
'label' => 'Color',
'config' => [
'type' => 'input',
'size' => 10,
'eval' => 'trim',
'default' => '#ffffff',
'wizards' => [
'colorChoice' => [
'type' => 'colorbox',
'title' => 'LLL:EXT:lang/locallang_wizards:colorpicker_title',
'module' => [
'name' => 'wizard_colorpicker'
],
'dim' => '20x20',
'JSopenParams' => 'height=600,width=380,status=0,menubar=0,scrollbars=1',
],
],
],
],
],
];
$GLOBALS['TCA']['tt_content'] = array_replace_recursive($GLOBALS['TCA']['tt_content'], $tca);
With the help of webMan and some internet searches I could adopt my code a little.
I added the file "ext_tables.sql" with the content
CREATE TABLE tt_content (
item_0 varchar(10) DEFAULT '' NOT NULL,
);
And changed the tt_content.php in TCA/Overrides to:
$temporaryColumns = Array(
"item_0" => Array(
'label' => 'Color',
'config' => Array(
'type' => 'input',
'renderType' => 'colorpicker',
'size' => 10
)
)
);
\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addTCAcolumns('tt_content',$temporaryColumns);
$GLOBALS['TCA']['tt_content']['types']['wo_mitem'] = array(
'showitem' => '--palette--;LLL:EXT:cms/locallang_ttc.xlf:palette.general;general,
header;Bezeichnung,
subheader;Chemische Bezeichnung,
header_link;Zielseite,
item_0;Farbe,
bodytext;Text;;richtext:rte_transform[flag=rte_enabled|mode=ts_css]
');
There are still a view things missing in compare to webMans code but at least this is the first working version I have so i figured i show it since my question is answered:).

How can I edit a field of a form in my controller?

I'm having trouble formulating a solution for 'editing' a field of my form in my controller.
Here's what I have:
I have a symfony2 form registered as a service that I call in a function in my controller. I am removing a bunch of fields that aren't necessary for this other form I am directing my users to and then adding a few others.
(I realize I could create another form and create another service and such but for my purpose this would be a bit overkill. I'm doing it this way because the form functions the same, however some fields are not needed and a few new specific ones are.)
I would now like to essentially 'edit' one field in this form... The 'occupation' field. This field is a choice field acting as radio buttons populated by an array of choices. It's required and has no empty_value requirement in its original state.
I would like to edit it in my controller function to have the same exact values however with a required value of false and an empty_value of null.
With the commented out code below the result is a dissapearance of the occupation field in my 'new' form and it is replaced by an empty drop down. I realize it's because I'm overriding the whole field below, but I cannot figure out how to simply edit it.
Code:
/**
* Explanation of addAndRemoveFieldsInRegisterForm function:
* The function gets the 'registration' form and removes any
* fields not needed for the 'in_registration' form
* and then adds the necessary fields to the form.
*/
private function addAndRemoveFieldsInRegisterForm($user)
{
$form = $this->createForm('user_registration', $user);
// http://stackoverflow.com/questions/10920006/pass-custom-options-to-a-symfony2-form ---
// --- use that to help. Look at changing the value of array.
$form->remove('title');
$form->remove('company');
$form->remove('username');
$form->remove('city');
$form->remove('state');
$form->remove('country');
$form->remove('gender');
$form->remove('age');
$form->remove('roles');
// $form->remove('occupation');
// $pr = $form->get('occupation');
// $pr->set('required' => false);
// $form->get('occupation')->add('required'=>false, 'empty_value'=>null);
// $form->add('occupation','choice', array(
// 'required' => false,
// 'empty_value' => null,
// ));
// echo "<pre>";
// var_dump(get_class_methods($form));die;
$form->add('occupation','choice', array(
'required' => false,
'empty_value' => null,
));
$form->add('canEmail', 'checkbox', array(
'label' => 'Can Email?',
'required' => false,
));
$form->add('sendEmail', 'choice', array(
'label' => 'Send Welcome Email? ',
'required' => true,
'mapped' => false,
'expanded' => true,
'choices' => array(
"yes" => "Yes",
"no" => "No"
),
));
return $form;
}
Original Form (the one that's used as a service)
private $requireOccupation;
$this->requireOccupation = true;
->add('occupation','choice', $options['occupation'])
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$occupation = array(
"label" => "Which of these currently describes you best? (Occupation):",
"expanded" => true,
'required'=> $this->requireOccupation,
"choices" => array(
"X" => "X",
"B" => "B",
"C" => "C",
"J" => "J",
),
'constraints' => array(
new NotBlank()
));
$resolver->setDefaults(array(
'occupation' => $occupation,
));
}
I think it is better to create another form. It can herit from your already defined form to change only the field you want
class SomeFormType extends OriginalFormType {
public function buildForm(FormBuilderInterface $builder, array $options) {
parent::buildForm($builder, $options);
$builder
->remove('someField')
->add('someField', 'choice', [
"expanded" => true,
"choices" => $yourArray
]);
}
It has the advantage to be mapped on different object
Firstly, I realize the way I wanted to solve this issue is odd when considering I could have created another form with either the fields I wanted to use or just the one field that needed to change and register the form as a service to use it elsewhere, but I was tasked to complete it this way.
Second, my solution is quite simple. I pass values into my form with a default value set in the form.
In the form:
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$requireOccupation = true;
$emptyValue = null;
//whatever other values you want to set here
$resolver->setDefaults(array(
'requireOccupation' => $requireOccupation,
'emptyValue' => $emptyValue,
));
}
and then on the field's properties:
$builder->add('occupation', 'choice', array(
"label" => "Some sort of label",
"required" => $options['requireOccupation'],
"empty_value" => $options['emptyValue'],
...
));
Now in the controller:
$form = $this->createForm('registration', $user, array(
'requireOccupation' => false, 'emptyValue' => null
));
call that where you want to generate your form while passing in the values you want to use for that form.
I am by no means an expert on Symfony and this solution would probably generate some issue with those who are. But it works for me.

PHP Global Multidimensional Array... Or How would I do that?

I'm new to PHP and trying to learn the proper way to do things, I'm currently working on a PHP / HTML form so here is my code for my globa variable:
// General Function
global $variables;
$variables = array(
'login' => array(
'visible' => 'visible',
'required' => 'required',
'position' => get_option('order_username'),
'value' => $_POST['username'],
'error_req' => __('A username is required to register.'),
'error_misspelled' => __('Your username is not properly formatted.'),
'error_unavailable' => __('This username has already been registered.')
),
'province' => array(
'visible' => get_option('show_province'),
'required' => get_option('required_province'),
'position' => get_option('order_province'),
'value' => $_POST['easyreg_province'],
'error_req' => __('You need to fill your province to register.'),
'error_misspelled' => '',
'error_unavailable' => ''
)
);
This works fine and I can access those Variables from every other functions; first I know many people says not to use GLOBAL variables, I don't really understand why because in my case those data will be used and reused inside my form, I would prefer not to redeclare new variables in every function related because those data won't change during the processing.
If it's really not the best way... What could be a good way to do that? As you can see I have about 7 "values" by form "input".
Also, for a GLOBAL variable like that can you "declare" the values from inside a function? What I mean is that if I add a new fields to my form, I would like to have those declaration beside my field, instead of having it in the main PHP (which would also make my code look cleaner).
I would have thought something like that, but it seems to be only declaring it inside the function itself:
function form_display(){
<!-- Email field -->
$GLOBALS['variables']['email'] = array(
'visible' => 'visible',
'required' => 'required',
'position' => get_option('order_email'),
'value' => $_POST['email'],
'error_req' => __('An email is required to register.'),
'error_misspelled' => __('This is not an appropriate email format.'),
'error_unavailable' => __('This email has already been registered.')
);
?>
<div class="regpage_email required"
id="order_<?php echo($GLOBALS['variables']['email']['position']) ?>">
<td id="field_email"><label
for="email"><?php _e('E-mail Address: *') ?></label><br><input
id="email"
type="email"
name="email"
value=""
placeholder=""
required>
</td>
}

Have a relatively complex form and submission process. Need help on slimming it down

I am working on a personal project which is a website that allows users to document there drug usage. The goal of this is for users to be able to quickly reference when the last time they ingested X, and other similar statistics.
Users also store dosages, and units that the dose is measured. And this is where the problem is. In my database I have every unit of measurement associated with a conversion value. The plan was to have this conversion value so that every dose stored would be easy to mold and use when creating things such as graphs.
For example, a gram has a conversion value of 1, while a mg has .001.
Which means if a user enters that he took 1 Gram of X, this data goes through my form submission function, multiple the 1 Gram by the conversion value (1) and stores the final product (1) in the db.
Similarily, if a user enters he took 300 Milligrams of X, the 300 is multiplied by .001 to get 0.3.
Having a system like this allows me to easily add both values and get "1.3 Grams of X taken"
I am not experienced with these kind of complex things, and when I coded this into the site it was a temporary fix, which is very sloppy. Now I know I need to figure out a way better method in storing this.
Below I will add the code that renders the form, and the code that processes the form.
Form:
<?php
echo $this->Form->input('Record.dose_date', array('placeholder' => 'Date of Dose', 'label' => false,'type' => 'text','id' =>'datepicker'));
echo $this->Form->input('RecordDrugUnit.drug_id', array('placeholder' => 'Substance', 'options'=>$drugList,'label' => false,'type' => 'select'));
echo $this->Form->input('RecordDrugUnit.dose', array('placeholder' => 'Dose', 'label' => false, 'class' => 'colLarge left'));
echo $this->Form->input('RecordDrugUnit.unit_id', array('placeholder'=>'Unit', 'options'=>$unitList, 'label' => false,'type'=>'select', 'class' => 'colSmall right'));
echo $this->Form->submit('SUBMIT', array('class' => 'button'));
echo $this->Form->input('RecordDrugUnit.route_id', array('placeholder'=>'Unit', 'options'=>$routeList, 'label' => false,'type'=>'select', 'class' => 'colLarge right'));
echo $this->Form->input('Record.title', array('placeholder' => 'Title', 'label' => false,'type' => 'text'));
echo $this->Form->input('Record.report', array('placeholder' => 'Your Report','label' => false,'type' => 'textarea'));
?>
Controller:
if ($this->request->is('post')) {
$this->Record->create();
$conv_val = $this->Unit->find('first', array(
'conditions' => array(
'id' => $this->request->data['RecordDrugUnit']['unit_id']),
'fields' => array('conversion')
));
$this->request->data['RecordDrugUnit']['dose'] = (float)$this->request->data['RecordDrugUnit']['dose'] * (float)$conv_val['Unit']['conversion'];
$this->request->data['Record']['user_id'] = $this->Auth->user('id');
if ($this->RecordDrugUnit->saveAssociated($this->request->data, array('deep' => TRUE))) {
$this->Session->setFlash('Your post has been saved.');
$this->redirect(array('action' => 'index'));
} else {
$this->Session->setFlash('Unable to add your post.');
}
}
Looking for suggestions on how to simplify this
I think storing the conversions in a table is unnecessary, since it's not likely units will ever change. You could make your form have a "unit" pulldown instead, with hardcoded options array('1' => 'grams', '.001' => 'milligrams', etc.,), then dose will equal (float)$this->request->data['RecordDrugUnit']['dose'] * (float)$this->request->data['RecordDrugUnit']['unit'];

Categories