Gravity Forms - Get a Date value and adjust it, make it into a merge tag - gravity-forms-plugin

So what I want to be able to do is take a field value, a date field, and add a set period of time to it and then make that into a merge tag that I can then add back into that value or use else where.
I know how to make a new merge tag, that's not the issue. My question is how do I get a field value to use in that calculation?
add_filter( 'gform_replace_merge_tags', 'new_date_plus_30', 10, 7 );
function new_date_plus_30( $text, $form, $entry, $url_encode, $esc_html, $nl2br, $format ) {
$merge_tag = '{date_plus_30}';
$new_date = date('m/d/Y', strtotime('+30 days'));
return str_replace( $merge_tag, $new_date, $text );
}
So where I do the new date calculation, I need to be able to pull in a field from that post and use it.
I was also thinking of doing a If / Else script where I would do the date calculation based on what was set in a form. So if a user said repeat this every 15 days, I would have something like:
add_filter( 'gform_replace_merge_tags', 'new_date_plus_30', 10, 7 );
function new_date_plus_30( $text, $form, $entry, $url_encode, $esc_html, $nl2br, $format ) {
if ( $form_id == 34 && $field_id == 2 && $value == 'add 30 days') {
$merge_tag = '{date_plus_30}';
$new_date = date('m/d/Y', strtotime('+30 days'));
}
else if ( $form_id == 34 && $field_id == 2 && $value == 'first of month') {
$merge_tag = '{first_of_month}';
$new_date = date('m/d/Y', strtotime('first of next month'));
}
}
return str_replace( $merge_tag, $new_date, $text );
}
But my issue is still the same. How can I use two filters at the same time? I assume I need to use the gform_get_input_value. Kindly review my code and give feedback is there other way?

Or maybe something like this...
add_filter( 'gform_merge_tag_filter', function ( $value, $merge_tag, $options, $field, $raw_value ) {
if ( $field->id == '2' && $value == 'first of the month') {
$merge_tag = '{the_next_date}';
$thedatetochange = 'Not sure how to get the date value here...';
$value = date('m/d/Y', strtotime($thedatetochange . 'first of the next month'));
return $value;
}
else if ( $field->id == '2' && $value == 'the 15th') {
$merge_tag = '{the_next_date}';
$thedatetochange = 'Not sure how to get the date value here...';
$the_first_date = date('m/d/Y', strtotime($thedatetochange . 'first of the next month' ));
$value = date('m/d/Y', strtotime($the_first_date . '+15 days' ));
return $value;
}
}, 10, 5 );

So after doing more digging, would I be able to use something like this to get the value of the field?
$theDateToChange = rgar( $entry, ‘3’);
This assumes that the field 3 is a date value. Would this work for retrieving the current entry date?

The $entry is passed through the gform_replace_merge_tags filter. You can fetch any field value from the $entry by its field ID. For example, if your field ID was 1:
$value = $entry[1];
Alternately, if you're open to capturing this modified date as a secondary Date field in your form, we have a snippet that can handle the functionality for you.
https://gravitywiz.com/populate-dates-gravity-form-fields/
new GW_Populate_Date( array(
'form_id' => 1,
'target_field_id' => 2,
'modifier' => '+30 days'
) );

So here is my current working code...
add_action( 'gform_admin_pre_render', 'add_merge_tags' );
function add_merge_tags( $form ) {
?>
<script type="text/javascript">
gform.addFilter('gform_merge_tags', 'add_merge_tags');
function add_merge_tags(mergeTags, elementId, hideAllFields, excludeFieldTypes, isPrepop, option){
mergeTags["custom"].tags.push({ tag: '{the_next_date}', label: 'The Next Date' });
return mergeTags;
}
</script>
<?php
//return the form object from the php hook
return $form;
}
add_action('wp', 'add_merge_tags');
/** MY MERGE TAGS HERE */
add_filter( 'gform_replace_merge_tags', 'new_date', 10, 7 );
function new_date( $value, $merge_tag, $options, $field, $raw_value, $entry, $text, $form, $url_encode, $esc_html, $nl2br, $format ) {
$pmoptions = $entry[7];
if ( $pmoptions == 'Monthly') {
$merge_tag = '{the_next_date}';
$old_date = $entry[2];
$new_date = date('m/d/Y', strtotime( $old_date . '+1 month'));
return str_replace( $merge_tag, $new_date, $text );
}
else if ( $pmoptions == 'Quarterly') {
$merge_tag = '{the_next_date}';
$old_date = $entry[2];
$new_date = date('m/d/Y', strtotime( $old_date . '+3 month'));
return str_replace($merge_tag, $new_date, $text);
}
}
apply_filters( 'gform_replace_merge_tags', $value, $merge_tag, $options, $field, $raw_value, $entry, $text, $form, $url_encode, $esc_html, $nl2br, $format );

Related

How to conditionally add function to completed order when custom field to order_id is set in woocommerce

I try to add a function to the completed order email in woocommerce if a specific custom field is set.
I am certain the custom field is attached to the order, as i can output it on the admin order page.
so far i have:
function test(){
global $woocommerce, $post;
$check = get_post_meta( $order->ID, '_digital', TRUE);
if (!empty($check)){
function order_completed_email_add_cc_bcc( $headers, $email_id, $order ) {
if ( 'customer_completed_order' == $email_id ) {
$headers .= "Bcc: admin <admin#example.com>" . "\r\n";
}
return $headers;
}
add_filter( 'woocommerce_email_headers', 'order_completed_email_add_cc_bcc', 9999, 3 );
}
}
However, this doesn't work...
Ok i found it.
function order_completed_email_add_cc_bcc( $headers, $email_id, $order ) {
$check = $order->get_meta('_digital',true);
if ( 'customer_completed_order' == $email_id && !empty($check)) {
$headers .= "Bcc: admin <admin#example.com>" . "\r\n";
}
return $headers;
}
add_filter( 'woocommerce_email_headers', 'order_completed_email_add_cc_bcc', 9999, 3 );

Import a huge among of data from Elasticsearch 2 to Mongodb fails on memory limit

I need help with import about 25 millions items from Elasticsearch to Mongodb. I wrote php script to do it but when the script reaches 16 millions items it fails on memory limit and throws me an error: VirtualAlloc() failed: [0x000005af] The paging file is too small for this operation to complete. I changed the system settings - virtual memory (paging file) to 100 000 according this web, but it is still not enough. I dont understand why it allocates so much memory. To get data from Elasticsearch I use scroll api. Look at the script:
<?php
error_reporting( E_ALL );
ini_set( 'memory_limit', -1 );
ini_set( 'max_execution_time', -1 );
/** #var \Nette\DI\Container $container */
$container = require( __DIR__ . '/../app/bootstrap.php' );
echo "----------------------------------------------------------------\n";
echo "--------------------- EVENT INDEX IMPORT -----------------------\n";
echo "----------------------------------------------------------------\n";
echo 'memory_limit: ' . ini_get( 'memory_limit' ) . "\n";
/** #var MongoConnect $mongo */
$mongo = $container->getService( 'mongo' );
/** #var \MongoDB\Collection $eventsCollection */
$eventsCollection = $mongo->selectCollection( 'Events', 'events' );
/** #var Elastica\Client $elastic */
$elastic = new Elastica\Client();
/** #var Elastica\Index $elasticIndex */
$elasticScrollData = $elastic->getIndex( 'event' )->request( '_search?scroll=10s', 'GET', ['size' => 250, 'sort' => ['_doc']] )->getData();
$countAll = $elasticScrollData['hits']['total'];
echo 'ES ALL ITEMS COUNT ' . $countAll . "\n";
$offset = 0;
saveToMongo( $elasticScrollData, $countAll, $offset, $elastic, $eventsCollection );
function saveToMongo( $scrollData, $countAll, $offset, \Elastica\Client $elastic, \MongoDB\Collection $mongoCollection )
{
$documents = [];
foreach ( $scrollData['hits']['hits'] as $item )
{
$doc = [];
$doc['ico'] = (array)$item['_source']['ico'];
$doc['data'] = $item['_source'];
if( isset( $item['_type'] ) ) $doc['type'] = $item['_type'];
if( isset( $item['_source']['key'] ) ) $doc['key'] = $item['_source']['key'];
if( isset( $item['_source']['action'] ) ) $doc['action'] = $item['_source']['action'];
if( isset( $item['_source']['publishDate'] ) ) $doc['publishDate'] = stringToDate( $item['_source']['publishDate'] );
if( isset( $item['_source']['generateDate'] ) ) $doc['generateDate'] = stringToDate( $item['_source']['generateDate'] );
if( isset( $item['_source']['eventDate'] ) ) $doc['eventDate'] = stringToDate( $item['_source']['eventDate'] );
$documents[] = $doc;
$offset++;
}
try
{
$mongoCollection->insertMany( $documents, ['ordered' => FALSE] );
echo '--- offest ' . ( $offset ) . ' OK' . "\n";
}
catch( \Exception $e )
{
echo '+++ insert exception: ' . $e->getMessage() . "\n";
}
if( $offset < $countAll )
{
$scrollData = $elastic->request( '_search/scroll', 'GET', ['scroll' => '10s', 'scroll_id' => $scrollData['_scroll_id']] )->getData();
saveToMongo( $scrollData, $countAll, $offset, $elastic, $mongoCollection );
}
}
function stringToDate( $string )
{
if( preg_match( '/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d+\+[\d:]+$/', $string ) ) $format = 'Y-m-d\TH:i:s.uT';
elseif( preg_match( '/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d+$/', $string ) ) $format = 'Y-m-d\TH:i:s.u';
elseif ( preg_match( '/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\+[\d:]+$/', $string ) ) $format = 'Y-m-d\TH:i:sT';
elseif ( preg_match( '/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}$/', $string ) ) $format = 'Y-m-d\TH:i:s';
elseif ( preg_match( '/^\d{4}-\d{2}-\d{2}\+[\d:]+$/', $string ) ) $format = 'Y-m-dT';
elseif ( preg_match( '/^\d{4}-\d{2}-\d{2}$/', $string ) ) $format = 'Y-m-d';
return DateTime::createFromFormat( $format, $string );
}
echo "------------------------------------------------------------------------\n";
echo "------------------------- EVERYTHING IS DONE ---------------------------\n";
echo "------------------------------------------------------------------------\n";

How do I attach a pdf file to a Gravity Forms Notification?

Gravity forms offers a way to attach files from the file uploader (See code below), but how would I change this code to simply attach my own PDF file from either a hidden field value or simply paste the pdf file within this code? I tried a few things but it didn't work. Any help would be appreciated!
add_filter( 'gform_notification', 'change_user_notification_attachments', 10, 3 );
function change_user_notification_attachments( $notification, $form, $entry ) {
//There is no concept of user notifications anymore, so we will need to target notifications based on other criteria, such as name
if ( $notification['name'] == 'User Notification' ) {
$fileupload_fields = GFCommon::get_fields_by_type( $form, array( 'fileupload' ) );
if(!is_array($fileupload_fields))
return $notification;
$attachments = array();
$upload_root = RGFormsModel::get_upload_root();
foreach( $fileupload_fields as $field ) {
$url = $entry[ $field['id'] ];
$attachment = preg_replace( '|^(.*?)/gravity_forms/|', $upload_root, $url );
if ( $attachment ) {
$attachments[] = $attachment;
}
}
$notification['attachments'] = $attachments;
}
return $notification;
}
Based on that code, something like this should work. Replace the $url value with the URL to your PDF.
add_filter( 'gform_notification', 'change_user_notification_attachments', 10, 3 );
function change_user_notification_attachments( $notification, $form, $entry ) {
if ( $notification['name'] == 'User Notification' ) {
$url = 'http://yoursite.com/path/to/file.pdf';
$notification['attachments'][] = $url;
}
return $notification;
}

Laravel selectRange blank option

I am creating a "day" select dropdown. With a selectRange I can do this:
{{ Form::selectRange('day', 1, 31, $day) }}
The problem is, when the form loads, if $day is not set it selects 1 by default. Is it possible to use selectRange to give them a "Please Choose" option that has a NULL value?
Use Form::select instead.
{{ Form::select('day', array('' => 'Please Choose...') + range(1,31)) }}
Use Form Select with range and array_combine if you want to modify the option value:
{{ Form::select('month', array('all' => 'all') + array_combine(range(1,12),range(1,12)) ) }}
I don't believe there is a way of achieving this with the built in selectRange, however it is possible using form macros. The following macro performs roughly what you're looking for, though may require some cleanup.
Form::macro('selectRangeWithDefault', function($name, $start, $end, $selected = null, $default = null, $attributes = [])
{
if ($default === null) {
return Form::selectRange($name, $start, $end, $selected, $attributes);
}
$items = [];
if (!in_array($default, $items)) {
$items['NULL'] = $default;
}
if($start > $end) {
$interval = -1;
$startValue = $end;
$endValue = $start;
} else {
$interval = 1;
$startValue = $start;
$endValue = $end;
}
for ($i=$startValue; $i<$endValue; $i+=$interval) {
$items[$i . ""] = $i;
}
$items[$endValue] = $endValue;
return Form::select($name, $items, isset($selected) ? $selected : $default, $attributes);
});
Usage is as follows:
{{ Form::selectRangeWithDefault('day', 1, 31, $day, 'Please Choose...') }}
Note that I got the idea and the basis for my code from: https://stackoverflow.com/a/25069699/3492098
this one works with reverse list :
Form::macro('selectRangeWithDefault', function($name, $begin, $end, $selected = null, $default = null, $attributes = [])
{
if (!is_array($default) || $default === null) {
return Form::selectRange($name, $begin, $end, $selected, $attributes);
}
$range = $default + array_combine($range = range($begin, $end), $range);
return Form::select($name, $range, $selected, $attributes);
});
Exemple :
{!! Form::selectRangeWithDefault('year', date('Y'), 1915, $user->getBirthYear(), ['' => 'YYYY']) !!}
And if you are looking how to add a macro : Where to put HTML macros in laravel 5?
Use Form::select instead of Form::selectRange
Also, according to the best practices you can use the placeholder parameter in order to create a blank option.
{{ Form::select('day', range(1, 31), null, ['placeholder' => '']) }}
use placeholder
{{ Form::selectRange('day', 1, 31, $day,['class' => 'form-control input-lg','id'=>'day','placeholder' => 'Please Choose']) }}

CodeIgniter: how to return data from a form validation callback

Here is my CI form validation rule:
$datetime_string = $this->form_validation->set_rules('event_date', 'Select', 'callback_date_validate');
Here is my callback:
function date_validate($select_value)
{
$year = '';
$month = '';
$day = '';
$hour = '';
$minutes = '';
$datetime = $this->input->post('event_date');
if (strpos($datetime, ' # ') !== 'FALSE' && $datetime != '')
{
$datetime_explode = explode(' # ', $datetime);
if (strpos($datetime_explode[0], '/') !== 'FALSE' && $datetime_explode != '')
{
$date_explode = explode('/', $datetime_explode[0]);
$year = $date_explode[2];
$month = $date_explode[1];
$day = $date_explode[0];
}
if (strpos($datetime_explode[1], ':') !== 'FALSE')
{
$time_explode = explode(':', $datetime_explode[1]);
$hour = $time_explode[0];
if (strpos($time_explode[1], ' ') !== 'FALSE')
{
$minutes_explode = explode(' ', $time_explode[1]);
$minutes = $minutes_explode[0];
$am_pm = $minutes_explode[1];
if ($am_pm == 'PM' || $am_pm == 'pm')
$hour += 12;
}
}
}
$datetime_string = $year . '-' . $month . '-' . $day . ' ' . $hour . ':' . $minutes . ':00';
if (!preg_match('/^\d{4}-\d{2}-\d{2} 2[0-3]|[01][0-9]:[0-5][0-9]:[0-5][0-9]$/', $datetime_string))
{
$this->form_validation->set_message('date_validate', 'Oops');
}
else // user picked something
{
return $datetime_string;
}
}
According to the CI documentation, you can return data from a form validation callback, but by setting the rule equal to a variable, I get this error:
Object of class CI_Form_validation could not be converted to string
What am I doing wrong?
I think the problem is in this line:
$datetime = $this->input->post('event_date');
The value of event_date field is captured in a parameter of your function $select_value try using your parameter instead of post data.
$this->form_validation->set_rules(...); should be called inline and not assigned to a variable. You have assigned it to $datetime_string. Remove this assignment.
I don't know if you ever solved this but I was scratching around the documentation wondering the same thing as your question.
First of all, you just want...
$this->form_validation->set_rules('event_date', 'Select', 'callback_date_validate');
Don't assign it to a variable.
Next, you want to run your validation rules/callbacks...
if ($this->form_validation->run() == TRUE) {
// VALIDATION OK, CHECK OUR CALLBACK DATA
var_dump($this->input->post());
}
Now you should see your data returned from the callback in... $this->input->post('event_date');
The thing that confused me about returning data from callbacks was this thread on the official CI forums... http://codeigniter.com/forums/viewthread/191087/ where people are suggesting that the callback doesn't change the POSTed data. They are only partially correct. It doesn't change it under $_POST['whatever'] but it does change it in $this->input->post('whatever')
As this was the 3rd result in Google I hope this helps someone out.