I have a function that processes sales via a third-party service, processes the result and returns an array with the Status "Success" or "Invalid." This sales call is made using the gform_after_submission hook applied to the specific form.
What I need to do is store the "Success" or "Invalid" result in the array as a variable that I can later pass to a function to validate or invalidate the credit card field, using gform_validation hook.
I'm declaring the variable in a function, like so:
function foo {
...code to sell product through API...
$status = $checkoutShoppingCartRequest['Result']['Status'];
}
When I print the variable $status within the function, it is showing either Success or Invalid like it should.
Here is other function where I need to use this variable, passed to gform_validation, which fails every time regardless of Success or Invalid result:
function MBvalidate( $validation_result ) {
$form = $validation_result['form'];
if ( $status !== "Success") {
$validation_result['is_valid'] = false;
foreach( $form['fields'] as &$field ) {
if ( $field->id == '34' ) {
$field->failed_validation = true;
$field->validation_message = 'Your credit card could not be processed.';
break;
}
}
}
//Assign modified $form object back to the validation result
$validation_result['form'] = $form;
return $validation_result;
}
add_filter( 'gform_validation_47', 'MBvalidate' );
I have tried passing the variable a number of different ways, via globals and sessions, etc.
I am new to GF development so I am sure I'm missing something. I'd appreciate any direction.
The gform_after_submission action hook runs after gform_validation.
Anyway, assuming you can find a hook that runs earlier, what I would do is store a unique variable for each submitted form using the Transients API's set_transient() and get_transient() functions. For example you can create a hidden field in every form which you populate with a random ID. Use this random ID as a key to store and retrieve the Success/Invalid result.
$status here is a local variable which has never been defined before you try to use it in if-condition. So, it's always null.
Maybe you missed
$status = $validation_result['Result']['Status'];
or something like this before checking the condition.
Related
In Suitecrm/SugarCRM 6.5
I need to modify the ListView. Showing the value of a field based on a certain condition.
In the Account module, the name field may be empty based on certain conditions, I require that when this occurs show the value of a custom field. To do this, first I tryied using 'customCode' + smarty as usual in Edit/Detail vies, but in several posts mention that this is not possible in the ListView. The concession is to use logic hooks + a non-db field to store the calculated field. Following this SO answer I have written the following:
Custom field at custom/Extension/modules/Accounts/Ext/Vardefs/custom_field_name_c.php
<?php
$dictionary['Account']['fields']['name_c']['name'] = 'account_name_c';
$dictionary['Account']['fields']['name_c']['vname'] = 'LBL_ACCOUNT_NAME_C';
$dictionary['Account']['fields']['name_c']['type'] = 'varchar';
$dictionary['Account']['fields']['name_c']['len'] = '255';
$dictionary['Account']['fields']['name_c']['source'] = 'non-db';
$dictionary['Account']['fields']['name_c']['dbType'] = 'non-db';
$dictionary['Account']['fields']['name_c']['studio'] = 'visible';
Label at suitecrm/custom/Extension/modules/Accounts/Ext/Language/es_ES.account_name_c.php
<?php
$mod_strings['LBL_ACCOUNT_NAME_C'] = 'Nombre de cuenta';
Logic hook entry at custom/modules/Accounts/logic_hooks.php
$hook_array['process_record'] = Array();
$hook_array['process_record'][] = Array(
2,
'Get proper name',
'custom/modules/Accounts/hooks/ListViewLogicHook.php',
'ListViewLogicHook',
'getProperName'
);
Logic hook at custom/modules/Accounts/hooks/ListViewLogicHook.php
<?php
class ListViewLogicHook
{
public function getProperName(&$bean, $event, $arguments)
{
if (empty($bean->fetched_row['name'])) {
$bean->account_name_c = $bean->fetched_row['person_name_c'];
} else {
$bean->account_name_c = $bean->fetched_row['name'];
}
// Here I also tried, but same result
// $bean->account_name_c = empty($bean->name) ? $bean->person_name_c : $bean->name;
}
}
listviewdefs.php at custom/modules/Accounts/metadata/listviewdefs.php
I added the field
'NAME_C' =>
array (
'width' => '20%',
'label' => 'LBL_ACCOUNT_NAME_C',
'default' => true,
),
After these modifications and repair I hope to see the field full with the right value. But it appears empty. I have verified that the logic hook is properly called, but the name andperson_name_c fields are always empty. In case it is relevant I have verified in Studio that the name fields in Account is typename I do not know what this means when it comes to obtaining its value.
I appreciate your comments
The problem is in the logic hook is due to first that the $bean does not have access to the custom fields, so I have to invoke them using $bean->custom_fields->retrieve(); Also the name field is always empty, I had to use DBManager to get only the name field.
The logic of the final logic hook is the following:
<?php
class ListViewLogicHook
{
public function getProperName($bean, $event, $arguments)
{
// Get access to custom fields from $bean
$bean->custom_fields->retrieve();
// Get access to name property using DBManager because $bean->name return null
$sql = "SELECT name FROM accounts WHERE id = '{$bean->id}'";
$name = $GLOBALS['db']->getOne($sql);
// Assign a value to non-db field
$bean->name_c = empty($name) ? $bean->nombre_persona_c : $name;
}
}
I was not familiar with the method $bean->custom_fields->retrieve() and at the moment I do not know why is empty the name field and I understand others fields remain empty.
I hope this is useful
We achieved that doing an after_retrieve hook, very fast and simple - This is taken from a working example.
public function RemoveCost(&$bean, $event, $arguments)
{
global $current_user;
include_once(‘modules/ACLRoles/ACLRole.php’);
$roles = ACLRole::getUserRoleNames($current_user->id);
if(!array_search("CanSeeCostRoleName",$roles)){
$bean->cost = 0;
$bean->cost_usdollar = 0;
}
}
All you need is to define and add this function to the module logic_hooks.php
You can even tailor down to specific calls:
if (isset($_REQUEST['module'],$_REQUEST['action']) && $_REQUEST['module'] == 'Opportunities' && $_REQUEST['action'] == 'DetailView')
As some times there are views you do want to show the field, for example quicksearch popup.
I have a POS and need to check 2 things before I save a sale in MySQL
Code to get and check the information I need
$invoice=mysqli_real_escape_string($db,$_POST['same_invoice']);
$customer=mysqli_real_escape_string($db,$_POST['same_customer']);
If invoice is empty the customer is also empty because is the first prodyct in this invoice so we assign a invoice number and we ask the customer to show identification, the invoice is generated automatic so we input the ID-number of the customer and save to MySQL
Now the problem
If the customer wants to buy 2 products we dont need to give the order a new invoice number neither the ID but we must check both in MySQL
code I am trying but not working
if( $invoice is empty && $customer is also empty)
{ we create new invoice an ask customer for id first time }
if( $invoice is empty && $customer is NOT empty)
{ we create new invoice but do not ask customer for id }
else
{ we use the $invoice and $customer comming from the form }
Any idea how to check that?
You should check that the $_POST values are actually set, first. I would guess that is where your error is coming from.
$invoice = (isset($POST['same_invoice']) ? $_POST['same_invoice'] : null;
$customer = (isset($POST['same_customer']) ? $_POST['customer'] : null;
if(empty($customer) || empty($invoice)) {
//Use values from form
} else {
//Create new invoice
}
Determine whether a variable is considered to be empty. A variable is considered empty if it does not exist or if its value equals FALSE. empty() does not generate a warning if the variable does not exist.
$invoice=mysqli_real_escape_string($db,$_POST['same_invoice']);
$customer=mysqli_real_escape_string($db,$_POST['same_customer']);
if(!empty($invoice)&&!empty($invoice)){
//do whatever you want to do with it.
}
No warning is generated if the variable does not exist. That means
empty() is essentially the concise equivalent to !isset($var) || $var
== false.
I have created a simple product selector. In the phtml, I created a form that post data and these data are received by controller to be validated before registering to a registry.
I also have product collection that gets the data to be filter coming from the registry. I have several filters and if one fails, the system should display a message.
This is what I have done so far.
My Controller:
public function indexAction() {
if ($data = $this->getRequest()->getPost()) {
$data['ta'] = $this->getRequest()->getPost('torqueAction');
$data['tr'] = $this->getRequest()->getPost('torqueRequired');
$data['tm'] = $this->getRequest()->getPost('torqueMetric');
$data['tmax'] = $data['tr'] / 80 * 100;
if (validation is equal to true) {
Mage::register('t-action', $data['ta']);
Mage::register('t-req', $data['tr']);
Mage::register('t-metric', $data['tm']);
Mage::register('t-max', $data['tmax']);
$this->_redirect('productselector/index/result');
}else {
// Display message about the error
}
}
}
My Collection located in the phtml:
$collection = Mage::getModel('catalog/product')
->getCollection()
->addFieldTofilter($attr_name, array(
'eq' => Mage::getResourceModel('catalog/product')
->getAttribute($attr_name)
->getSource()
->getOptionId($attr_val)
))
->addAttributeToSelect('*')
->addFieldTofilter($metric, array('gteq' => $metric_val_min))
->addFieldTofilter($metric, array('lteq' => $metric_val_max))
->load();
if ($collection == NULL) { // not sure how to validate it if one filter fails
echo "sorry, no product available";
}else {
//Display some errors
}
QUESTIONS:
How to validate form post in the controller and checks if empty and no malicious code?
How to check product collection if one filter was not met?
How do I display these errors from controller and product collection?
Thanks
How to validate form post in the controller and checks if empty and no malicious code?
You can check an empty post like this.
if ($this->getRequest()->getPost('field_name', false)) {
//yes 'fiel_name' is not empty. do something with it.
}
This is because getPost() will accept two parameters. If the parameter-1 is not set, then it will return the default value that we specified as parameter-2. In this case, default value is false and hence condition fails if field_name is empty.
I didn't get the "malicious" part in the question. The answer for is, it depends from situation to situation.
How to check product collection if one filter was not met?
Honestly, question is not clear for me. However if the filters that you have applied using addFieldToFilter fails, then you will get an empty collection. You can check the count of a collection like this.
if ($collection->getSize() > 0) {
//do something with collection
} else {
//show some error
}
How do I display these errors from controller and product collection?
Errors, warning, success messages are setting on session variable and thus you can get the session in the redirecting page and show them in frontend.
These are the avaialble notifications in Magento.
$session = Mage::getSingleton('customer/session');
//use to show error
$session->addError('add some error message');
//use to show warning
$session->addWarning('add some warning message');
//use to show notice
$session->addNotice('add some notice message');
//use to show success message
$session->addSuccess('add some success message');
You can set them in controller. Now this is how you can grab all these items and show in frontend. Use them in the form template wisely.
$messages = Mage::getSingleton('customer/session')->getMessages();
foreach ($messages as $message) {
echo $message;
}
Hope that makes sense.
Can anyone advice how best to set a temporary variable with scope to be used between hooks?
I have a custom module with the purpose of checking and warning if an attempted file upload matches an existing file on the system.
I am using hook_form_alter to identify the specific upload form and hook_file_validate to check if the file was previously uploaded.
My problem is those two hooks don't share a common parameter - I need to pass information from hook_form_alter back to hook_validate.
The information I want the functions to share is a simple boolean which should be destroyed immediately the file upload is done/dismissed, so using variable_set to persist it to the database is overkill. I don't believe a session or cookie approach is best either.
UPDATES:
Globals approach:
function duplicate_uploads_warning_init(){
$GLOBALS['processed'] = 'testing';
}
function duplicate_uploads_warning_file_validate($file){
drupal_set_message("PROCESSED[file-validate]: {$GLOBALS['processed']}", 'warning');
}
function duplicate_uploads_warning_form_alter(&$form, &$form_state, $form_id){
if( $form_id == 'file_entity_add_upload' ){
drupal_set_message("PROCESSED[form-alter]: {$GLOBALS['processed']}", 'error');
$GLOBALS['processed'] = 'tested';
$form['#validate'][] = 'duplication_validate';
}
}
The code above sets GLOBALS[processed] in the init hook and that value in immediately confirmed in the hook_form_alter.
However the attempt to reassign the value to tested fails. The reassigned value is what I hoped to see in hook_file_validate but I still get the initial value of testing.
Hook_form_alter validation approach:
I tried adding a custom validation function but the upload of the image still took place where I intend to stop it. My code is as follows:
function duplication_validate($form, &$form_state) {
$data = duplicates($form_state['complete form']['upload']['#file']->filename);
if( sizeof($data) > 0 ){
form_set_error('test', 'testing validation');
return false;
}
}
I can confirm my $data variable has content and the sizeof test returns greater than 0.
using variable_set to persist it to the database is overkill
I don't agree they are overkill (you can easily delete variables), and as #2pha have mentioned globals are not recommended. I think you could use variable_set($name, $value), variable_get($name), and variable_del($name) without worrying unless you need to super-optimise your sites database queries. If you really don't want to use the variable_* functions, then maybe cache_set() and cache_get() might work because you can give it a temporary status.
Edit, variables approach:
function duplicate_uploads_warning_init(){
$account = \Drupal::currentUser();
variable_set($account->id() . '_processed', 'testing');
}
function duplicate_uploads_warning_file_validate($file){
$account = \Drupal::currentUser();
$processed_var = variable_get($account->id() . '_processed');
drupal_set_message("PROCESSED[file-validate]: {$processed_var}", 'warning');
}
function duplicate_uploads_warning_form_alter(&$form, &$form_state, $form_id){
if( $form_id == 'file_entity_add_upload' ){
$account = \Drupal::currentUser();
$processed_var = variable_get($account->id() . '_processed');
drupal_set_message("PROCESSED[form-alter]: {$processed_var}", 'error');
variable_set($account->id() . '_processed', 'tested');
$form['#validate'][] = 'duplication_validate';
}
}
… and in a success or #submit callback function run variable_del($account->id() . '_processed') to delete the variable.
maybe $GLOBALS['processed'] was initialized with the static keyword elsewhere....?
I bought Quform wordpress plugin from codecanyon. The plugins is great - it allows you create custom validator for your forms as shown here http://support.themecatcher.net/quform-wordpress/guides/customization/creating-a-custom-validator.
The example above however only deals with one validating against a single value. What if I have 500 of them?
This is code that I have.
function custom_validator($valid, $value, $element, $rcnumber)
{
$rcnumber = array('103184','104351','104359','103912','104389','104400','100505','102180','103530','104455','79162','74233','26451','75140','289752','101785','103141','26646','103178','100567','75159','103744','103244','78557','103330','102602'<500 numbers....>,);
if ($value != $rcnumber) {
$element->addError('Invalid RC Number');
$valid = false;
}
return $valid;
}
add_filter('iphorm_element_valid_iphorm_14_11', 'custom_validator', 10, 3);
The problem with this code is that no matter what value I enter in rcnumber field I keep getting 'Invalid RC Number' error even though the number IS among 500 listed in the rcnubmer array. What am I doing wrong?
Thank you!
Not sure of what you want to get here, but it looks like you want to check if a value exists in an array.
Try this:
if (!in_array($value, $rcnumber))
Instead of:
if ($value != $rcnumber)
in_array function will look for a value in an array, your current code checks if $value is different that the given array.