I've set up a hook alter that adds a submit function to a webform submit chain. In that function alongside some other processing I add:
function webform_checkout_form_alter(&$form, &$form_state, $form_id) {
$form['#submit'][] = 'webformSubmitAlteration';
}
function webformSubmitAlteration(&$form, &$form_state) {
global $user;
$user->last_submission = $sids[1];
drupal_set_message('<pre> current user is: '. check_plain(print_r($user, TRUE)) .'</pre>');
}
That function also redirects to the ubercart checkout page.
The printed $user shows as (edited for clarity):
current user is: stdClass Object
(
[uid] => 1
[name] => paul.dambra
[last_submission] => 85
)
I then process the cart through checkout which fires an ubercart conditional action that runs some custom php. Basically when this payment completion is caught I want to use the last_submission value to switch the submitted form from draft to complete so that my users now which applications are done and dusted.
In that code I have added:
global $user;
drupal_set_message('<pre> user is : '. check_plain(print_r($user, TRUE)) .'</pre>');
$sid = $user->last_submission;
drupal_set_message('<pre> sid is : '. check_plain(print_r($sid, TRUE)) .'</pre>');
And when we see the output of those drupal_set_message calls:
user is : stdClass Object
(
[uid] => 1
[name] => paul.dambra
[last_submission] => 47
)
I know that 47 is the last_submission value from prior to processing the form in question. So even though when I submit the form I can see the correct value for last_submission when I immediately afterwards process the cart I see an old value.
Any pointers on what I might be doing wrong would be super!
I had to edit my code to:
global $user;
if ($user) {
$array = array('last_submission' => $sids[1]);
user_save($user, $array);
}
It now works as I expect. Hope that helps someone else...
Related
I have a custom table with serial numbers in WordPress. I have successfully got the serial number to appear on both Order received page after testing with Stripe:
https://prnt.sc/9tz8i3BW7lJR
and it also appears on WooCommerce Admin Orders Page:
https://prnt.sc/jLyb5CQqSAH5
I am using the woocommerce_email_before_order_table action. (on customer_completed_order)
I have the code below and I have echoed the Order ID and the Custom TableName and they BOTH appear in the Thanks for shopping with us email.
It seems the $license query returns nothing and I just can't see why it won't appear.
If I exchange the $woo_order_id for the previous order no, like EMS-0051 the serial number appears.
Is this query too early and it hasn't been populated in the custom table before the query is run?
I cannot get it to work..can anyone see what I have done wrong, please?
The Thanks email and CODE are below.
https://prnt.sc/38wa50jTyr3U
<?php
add_action( 'woocommerce_email_before_order_table', 'add_serial_to_email', 25, 4 );
function add_serial_to_email( $order, $sent_to_admin, $plain_text, $email ) {
global $wpdb;
$ipn_tables = $wpdb->prefix ."ipn_data_tbl";
///////BELOW is using 'seq Order No' plugin..this checks if WOO O/N or plugins O/N.
if (empty($order->get_id)) {
$woo_order_id = $order->get_order_number();
}
elseif (empty($order->get_order_number)) {
$woo_order_id = $order->get_id();
}
///check order ID and Table name are there:
if (!empty($woo_order_id && $ipn_tables )) {
echo '<b>ORDER ID:</b> '.$woo_order_id.'<br>'; // echos the Order ID - appears on "Thanks for shopping with us" email
echo '<b>TABLE NAME:</b> '.$ipn_tables.'<br>'; // echo my Custom table name - appears on "Thanks for shopping with us" email
////But the below $license variable doesn't. I think it's a timing thing.
//$license = $wpdb->get_var(" SELECT serial_no FROM $ipn_tables WHERE woo_order_id = $woo_order_id " );
$license = $wpdb->get_var( $wpdb->prepare( "SELECT * FROM {$ipn_tables} WHERE woo_order_id = %s", $woo_order_id ) );
}
if ( $email->id == 'customer_completed_order' ){
printf( '<p class="custom-text">' .__( 'Your Software Serial Number: '.'<span style="color:red;font-weight:bold;font-size:15px">'.$license ));
}
}//function-END
?>
Forgot to show the MyPHPAdmin table:
https://prnt.sc/A4DH1v2STWrL
edit:
I should have mentioned that I put that license check for orderID and table just to see if it was being checked..it appears my get_var query isn't working (empty?) but that same query is used in the other PHP pages I edited.
Looks like I found the issue. It was the fact that 'woocommerce_payment_complete' hook
was too early BUT the hook 'woocommerce_pre_payment_complete' is called first after payment is made but before order status change and before the email is sent. :)
So all I changed in the add_action was change:
woocommerce_payment_complete' TO woocommerce_pre_payment_complete that's it.
And it worked.
part of the add_action updated code
I want to set the value of a simple text field based on the state of another field in a previous page of a form. I am selecting a hosting provider of 'aws' and later in the form, I am asking for the user name.
For aws hosting, I want to force ec2-user to be shown in the text box, so I am using the filter of
add_filter( 'gform_pre_render_4', 'populate_deployment_user' );
function populate_deployment_user( $form )
{
$hosting_provider = rgpost('input_23');
if (strcmp($hosting_provider, "aws") == 0)
{
foreach ( $form['fields'] as &$field ) {
if ( $field->id == 42) {
$field->text = "ec2-user";
}
}
}
}
but the $field->text is not correct. I can't use the gform_field_value_$field_name as that's only called at the start of the form, and not after my other field 23 has been selected.
I'm a newbie in forms, JS and PHP, so floundering somewhat, although I've tried for a couple of days to get a solution.
Solution is to set
$field->defaultValue = "ec2-user";
I am using Yii2 with Pjax for index/gridview listing. using pjax pagination , search all working fine without postback to server.
My problem starts now,
suppose i am on page number 2, i have clicked on edit record of that 2nd page list, i reach to update view, i have done changes and saved, now i am redirected to view , now i clicked on index link from breadcrumbs.
i want to reach to page number 2 of index rather then 1st page.
Traditional process for this is get refereeing page params an append that in breadcrumbs.
But is there any simple approach to this problem where i can write few lines of code and its applied to every where in backend?
Thanks for reading.
For remembering grid filter, pages i use yii2-grid-view-state
If you need to store page only, isn't it quite easy to pass page param into your view url (<model/view>) like <model>/view?id=<id>&page=<page>?
in your index.php view, edit your ActionColumn as follow:
[
'class' => 'yii\grid\ActionColumn',
'urlCreator' => function ($action, $model, $key, $index) {
return \yii\helpers\Url::to([$action, 'id' => $model->id, 'page' => Yii::$app->request->getQueryParam('page', null)]);
},
],
As you can see, I'm getting page param from request url and pass it to models' action buttons (to all buttons, but in your question it would be enough for view button of course)
And when you click to view model, in our Controller we need to get that page value and pass it to our view.php view (in order to place it in breadcrumbs).
Our ModelController:
public function actionView($id, $page = null)
{
return $this->render('view', [
'model' => $this->findModel($id),
'page' => $page,
]);
}
And finally view.php view will get the page value, and populate the index url (if not null):
/* #var $page int */
$this->title = $model->name;
$this->params['breadcrumbs'][] = ['label' => 'Index', 'url' => ['index', 'page' => $page]];
So when you press the Index breadcrumb, it will open the page, where you entered from.
Some advantages againts session implementation (#user1764431 solution):
Each of your tab can return to it's own last page
Simple and stupid solution
Some disadvantages:
If you need to store some filter params, url could stretch very long
Just add following Code in every controller of actionIndex() rest all things will take care
$searchModel = new CentervideosSearch();
$dataProvider = $searchModel->search(Yii::$app->request->queryParams);
/*Code insertion block begin*/
$params = Yii::$app->request->queryParams;
if (count($params) <= 1)
{
$params = Yii::$app->session['customerparams'];
if(isset(Yii::$app->session['customerparams']['page']))
$_GET['page'] = Yii::$app->session['customerparams']['page'];
if(isset(Yii::$app->session['customerparams']['per-page']))
$_GET['per-page'] = Yii::$app->session['customerparams']['per-page'];
}
else
{
Yii::$app->session['customerparams'] = $params;
}
$dataProvider = $searchModel->search($params);
/*Code insertion block Ends*/
Guess my problem is closely related to this one : Snippet duplicates content when used multiple times on page
The elements of my problem are the following ...
$modx->loadedResources : an (empty) array registered in the main $modx object via a snippet on page load. The array holds resource id's of the resources fetched from the DB randomly, so the same resource isn't shown twice on the same page.
loadRandomResource : a snippet using XPDO-style querying to load a random resource from the DB. It uses $modx->parseChunk() to fill the placeholders in the chunk with the resource data. With each call, it appends the id of the fetched resource being fetched to the $modx->loadResources array.
I used some debugging to check if the resource id's were properly being stored in my array, each time I fetch a new random resource, which happens to be the case. I then checked if the db returns different results, each time I call the loadRandomResource snippet, and it does. I can also confirm that it doesn't return duplicate results (I exclude the already loaded resource ID's in my XPDO query).
However, when calling the snippet at 3 various locations throughout my page template, all 3 snippet calls render the same resource, which is weird, since my debug shows that unique data is being loaded from the DB, and being sent to the chunk for rendering.
Please find below both the snippet code, as well as the chunk mark-up.
Does anyone have any ideas? Any help is much appreciated!
loadRandomResource snippet
$criteria = $modx->newQuery('modResource');
$criteria->select(array('id','pagetitle'));
$criteria->sortby('RAND()');
$criteria->limit(1);
$whereOptions = array(
'parent' => 2,
'deleted' => false,
'hidemenu' => false,
'published' => true
);
if (!empty($modx->loadedResources)) {
$whereOptions['id:NOT IN'] = $modx->loadedResources;
}
$criteria->where($whereOptions);
$resources = $modx->getCollection('modResource', $criteria);
$output = '';
foreach ($resources as $resource) {
$fields = $resource->toArray();
$fields['tv.tvPersonalPicture'] = $resource->getTVValue('tvPersonalPicture');
$fields['tv.tvJobTitle'] = $resource->getTVValue('tvJobTitle');
$output .= $modx->parseChunk('cnkTeamListItem', $fields);
$modx->loadedResources[] = $fields['id'];
}
return $output;
cnkTeamListItem chunk
<div>
<img src="[[+tv.tvPersonalPicture]]" alt="[[+pagetitle]]" />
<h2>[[+pagetitle]]<br /><span>[[+tv.tvJobTitle]]</span></h2>
</div>
I found the answer myself, solution is a bit odd though ...
I was calling my custom snippet 3 times in my template, uncached. Each call though exactly looked the same ...
[[!loadRandomResource? &type='teammember']]
Even though I had the exclamation mark in place, still ModX was caching the call, within the same page request.
So when I added a random unique value to each of the 3 calls, the issue was solved.
Call 1 : [[!loadRandomResource? &type='teammember' &unique='123465']]
Call 2 : [[!loadRandomResource? &type='teammember' &unique='987654']]
Call 1 : [[!loadRandomResource? &type='teammember' &unique='666666']]
Don't know if this is a bug or a feature, but I thought that the exclamation mark prevented caching, both across different pageviews, as well as within the same page view. Anyhow, thx for helping.
I use this code for rendering chunks in snippents:
<?php
// get chunk or template
$tplRow = $modx->getOption('tplRow', $scriptProperties, '');
// get template
if (substr($tplRow, 0, 6) == "#CODE:") {
$tplRow = substr($tplRow, 6);
} elseif ($chunk = $modx->getObject('modChunk', array('name' => $tplRow), true)) {
$tplRow = $chunk->getContent();
} else {
$tplRow = false;
}
// render template
$field = array(); // your fields
if ($tplRow) {
$chunk = $modx->newObject('modChunk');
$chunk->setCacheable(false);
$chunk->setContent($tplRow);
$output[]= $chunk->process($fields);
} else {
$output[]= '<pre>' . print_r($fields, 1) . '</pre>';
}
You do realize you could have done this with getResources, don't you?
http://rtfm.modx.com/display/ADDON/getResources
&sortby=`RAND()`&limit=`1`
Using CakePHP 1.3
I have a controller with a non standard action name - say:
class WidgetsController extends AppController {
function modifyColor($id = null) {
// Some code that modifies the background color of a widget
}
}
and a companion view views/widgets/modifyColor.ctp
The modifyColor template POSTS to the action:
echo $this->Form->create('User',array('url' => array('controller' => 'widgets', 'action' => 'modifyColor')));
I get a 404 on the POST since the CakePHP Security component is trying to validate the form
and I would like to be able to validate the POST.
The only way I can get this to work seems to be to turn off POST validation
if ($this->action == 'modifyColor') {
$this->Security->validatePost = false;
}
This seems a bad solution.
How do I use the Security component on a non standard action?
allowedActions doesn't seem to work
Thanks
Danny
Answering my own question.
A. There is no problem with using any-named actions in CakePHP
B. A conceptual bug with CakePHP related to using the same function for the Form GET and Form POST
On the Form GET I had this:
if (empty($this->data)) {
$this->data = $this->Widget->read(null, $id);
}
The Form itself had some code like this:
echo $this->Form->input('id');
echo $this->formView('Current color', 'CurrentColor');
echo $this->formView('New color', 'NewColor');
echo $this->formView('New background color', 'BackgrdColor');
Which was fine, except that none of these fields appear in the Widget model - and the CakePHP Security component interprets this as a sort of XSRF attack - since it is finding fields in the form that don't belong to the model. That's why:
$this->Security->validatePost = false;
solved the "problem".
The correct solution is simply not to populate $this->data with the model in the controller action and handle the field assignments on the POST:
function modcolor () {
$this->layout = 'app_ui_listview';
if (!empty($this->data)) {
$id = $this->Session->read('Auth.User.id');
$u = $this->Widget->read(null, $id);
// Assign fields from the form to the model....
}
}
the problem is you are trying to pass url and you are trying to pass the controller stuff too.
echo $this->Form->create('Widget', array('controller' => 'widgets', 'action' => 'modifyColor'));
or
echo $this->Form->create('Widget', array('url' => '/widgets/modifyColor'));