PHP Make form field read-only conditionally based on date & time - php

I'm trying to have 2 fields in my form become read only after a certain time & date.
I've cobbled together some code from a few places in an attempt to make this work but I'm a total novice so I can't identify where it's going wrong or why.
The fields I want conditionally read-only are 1 & 13 in the example below. I'm not even sure what the numbers 9 & 2 are for. Like I said, absolute beginner.
Adding Angel's time & date definitions from his answer, here's what I have so far...
$W1F1Start = "2020-10-16 12:42:00";
$now = date('Y-m-d H:i:s');
if(strtotime($now) > strtotime($W1F1Start)){
add_filter('frm_setup_new_fields_vars', 'frm_set_read_only_on_create', 9, 2);
add_filter('frm_setup_edit_fields_vars', 'frm_set_read_only_on_create', 9, 2);
function frm_set_read_only_on_create( $values, $field ){
if ( in_array( $field->id, array( 1,13 ) ) ) {
$values['read_only'] = 1;
}
return $values;
}
return $values;
}
If I get this to work, I eventually need to make up to 20 fields read-only at different times and dates in the same form.
My form is a Formidable form on wordpress if it makes a difference.
In their knowledge bank they have 2 bits of code that I assume I can put together somehow to do what I want, but I can't figure out how...
This one 'makes fields read only' based on a thing
add_filter('frm_setup_new_fields_vars', 'frm_set_read_only_on_create', 9, 2);
add_filter('frm_setup_edit_fields_vars', 'frm_set_read_only_on_create', 9, 2);
function frm_set_read_only_on_create( $values, $field ){
// If on the back-end, keep fields editable
if ( FrmAppHelper::is_admin() || current_user_can( 'administrator' ) ) {
return $values;
}
// If on front-end, make specific fields read-only
if ( in_array( $field->id, array( 554,555,556 ) ) ) {
$values['read_only'] = 1;
}
return $values;
}
And this one does something 'based on current date'
add_filter('frm_setup_new_fields_vars', 'remove_field_option_by_date', 30, 2);
add_filter('frm_setup_edit_fields_vars', 'remove_field_option_by_date', 30, 2);
function remove_field_option_by_date( $values, $field ) {
$today = time();
$close_date = strtotime ( "2020-06-20" ); // change 2020-06-20 to the date after which the option should be removed
if ($today id == 13677 ) { // change 13677 to your field id
$options_to_remove = array( 'Option 1' ); // change Option 1 to the value to remove
foreach ( $options_to_remove as $remove ) {
$option_key = array_search( $remove, $values['options'] );
if ( $option_key !== false ) {
unset( $values['options'][ $option_key ] );
}
}
}
return $values;
}
I need to 'make fields read only'-'based on a date'. But I'm at a loss as to how to put those two things together.
Hope this is all the information needed. Is this possible?

1st - in Wordpress "code snippets" go in functions.php, located inside the theme you're using, so can do this without a plugin. Now to compare 2 dates you can have something like this:
// Static W1F1 start date
$W1F1Start = new DateTime();
$W1F1Start->setTimestamp(1602840600);
$now = new DateTime();
if($now > $W1F1Start){
// do whatever
}
Or lets assume your variable $W1F1Start is a string "2020-10-16 09:30:00" (this is the value of formatted $W1F1Start->format('Y-m-d H:i:s')) and you want to compare that to what current time, then you can use strtotime(), which will convert your strings to timestamps:
$W1F1Start = "2020-10-16 09:30:00";
$now = date('Y-m-d H:i:s');
if(strtotime($now) > strtotime($W1F1Start)){
// do whatever
}
So this is your code final look:
add_filter('frm_setup_new_fields_vars', 'frm_set_read_only_on_create', 9, 2);
add_filter('frm_setup_edit_fields_vars', 'frm_set_read_only_on_create', 9, 2);
function frm_set_read_only_on_create( $values, $field ){
// Static W1F1 start date
$W1F1Start = new DateTime();
$W1F1Start->setTimestamp(1602840600);
// current time
$now = new DateTime();
$now->setTimezone(new DateTimeZone('UTC'));
// if cuurent time > W1F1Start
if ($now > $W1F1Start) {
if ( in_array($field->id, array(1,13))) {
$values['read_only'] = 1;
}
return $values;
}
return $values;
}

Related

PHP: determination of the date minus weekends and holidays

There is a WordPress and ACF field with a date in the format 2022-04-30. From this date need to calculate 2 other dates, -2 days and +25 days. The problem is that it is necessary to take into account only working days, i.e. check weekends and holidays.
For example, we set the date May 3, 2022, which is Tuesday. From this date, I need to subtract 2 days, i.e. May 1, 2022, but this is Sunday, so we have to return to the first working day before May 1, i.e. Friday April 29, 2022. It's the same with holidays.
At the moment I have this code:
$setDate = get_field('set_date'); // ACF field, set May 3, 2022 (2022-05-03)
$offDate = wp_date('j F Y', strtotime('-2 days', strtotime($setDate)));
echo $offDate; // returns Sunday, May 1, 2022
I found holidays and weekends in json https://github.com/d10xa/holidays-calendar/blob/master/json/consultant2022.json
So I need to compare the given date with the dates from json and if there is a match, then minus one day and check the received date again. If there is a match, again minus one day and so on until no matches are found. Am I thinking correctly and can you tell me how to implement it? I am a very bad programmer, but there is a task)
At the moment I was only able to compare the dates and return the result found/not found. But I can't figure out how to take days off on the basis of this and send it for verification again(
$setDate = '2022-05-01';
$file = file_get_contents('https://raw.githubusercontent.com/d10xa/holidays-calendar/master/json/consultant2022.json', true);
$data = json_decode($file);
$found = array_search($setDate, $data->holidays);
if ($found === False) {
echo 'Not Found';
} else {
echo 'found';
}
The following has been tested on a few dates and I think it works as it should.
/*
JSON file is saved locally to a sub-directory
for the current working script directory.
This is to avoid unneccessary hits to the
remote site.
*/
$format='Y-m-d';
$url='https://raw.githubusercontent.com/d10xa/holidays-calendar/master/json/consultant2022.json';
$setDate = '2022-05-01';
$filepath=sprintf('%s/json/%s', __DIR__, basename( $url ) );
if( !file_exists( $filepath ) ){
file_put_contents( $filepath, file_get_contents( $url ) );
}
# read the file and generate JSON
$json=json_decode( file_get_contents( $filepath ) );
$hols=$json->holidays;
# create the initial DateTime object and find which weekday we are dealing with
# where 1 (for Monday) through 7 (for Sunday)
$obj=new DateTime( $setDate );
$date=$obj->format( $format );
$day=$obj->format('N');
# Is the given date a holiday/weekend?
if( array_search( $date, $hols ) ){
if( $day > 5 ){
# Date is either Sat or Sun... go back to previous working day
$subtract = 2 - ( 7 - $day );
$int=new DateInterval( sprintf('P%sD', $subtract ) );
$obj=new DateTime( $setDate );
$previous=$obj->sub( $int );
}else{
$previous=$obj->sub( new DateInterval('P2D') );
}
# create the future date ( add 25 days )
$int=new DateInterval('P25D');
$obj=new DateTime( $setDate );
$future=$obj->add( $int );
if( array_search( $future->format( $format ), $hols ) ){
# Future date is a holiday... go back to previous working day
$day=$future->format('N');
$subtract = 2 - ( 7 - $day );
$int=new DateInterval( sprintf('P%sD',$subtract ) );
$future=$future->sub( $int );
}
}else{
# Given date is NOT a holiday...
# take a copy of the original DateTime object for generating future date.
$ref=new DateTime( $setDate );
$int=new DateInterval( 'P2D' );
$previous=$obj->sub( $int );
$day=$previous->format('N');
# Is this a holiday?
if( $day > 5 ){
# yes - go back to previous working day
$subtract = 2 - ( 7 - $day );
$int=new DateInterval( sprintf('P%sD',$subtract ) );
$previous=$previous->sub( $int );
}
$int=new DateInterval('P25D');
$future=$ref->add( $int );
$day=$future->format('N');
# Is this a holiday?
if( $day > 5 ){
$subtract = 2 - ( 7 - $day );
$int=new DateInterval( sprintf('P%sD',$subtract ) );
$future=$future->sub( $int );
}
}
printf(
'<pre>
Given date: %s
Previous (-2): %s
Future (+25): %s
</pre>',
$date,
$previous->format( $format ),
$future->format( $format )
);
Which yields:
Given date: 2022-05-01
Previous (-2): 2022-04-29
Future (+25): 2022-05-26

Obtaining JSON data with foreach in PHP

A site contains monthly data in a JSON format. This can be queried like so:
http://www.example.com?startdate=1-1-1985&enddate=31-1-1985
I want to be able to run a script that will obtain the specific data I am looking for, starting from today's month, then work backward until null data is returned. Each month's value needs to add up. So far, this is what I've got:
//Build base URL:
$userid=$_GET['userid'];
$startdate=/*Beginning of today's month*/;
$enddate=/*End of today's month*/;
$url='http://www.example.com?userid='.$userid.'&startdate='.$startdate.'&enddate='.$enddate;
//Set JSON variables:
$get=file_get_contents($url);
$json=json_decode($get);
//Set loop variables:
$value=0;
$month=0;
/*For each month from today backwards{
$number=$json->integer;
if($number!=null){
$value=$value+$number;
$month=$month+1;
}else{
break;
}
}
echo $value;
echo $month;
*/
The part I'm having problems with is the beginning of the fourth part. How do I run a loop that starts with the range of today's month, obtain $number, then repeat with the previous month, until it reaches a month that returns null?
You could use the DateTime object and it's associated methods ( specifically sub in this case ) to count backwards by subtracting 1month at a time. An array stores the months/dates and the url is constructed using the variable counter $i
Initially this has a maximum backwards range of 20years ( which I guessed would be more than enough ) but it's easy to change.
$df='Y-m-d';
$userid=$_GET['userid'];
$timezone=new DateTimeZone('Europe/London');
$interval=new DateInterval('P1M');
$ts=date( $df, strtotime( date('Y-m-1') ) );
$tf=date( $df, strtotime( date('Y-m-1'). ' - 20 years') );
$start=new DateTime( $ts, $timezone );
$end=new DateTime( $tf, $timezone );
$dates=array();
$i=0;
while( $start->sub( $interval ) > $end ){
$dates[]=$start->format( $df );
if( $i > 1 ){
$startdate=$dates[ $i - 1 ];
$enddate=$dates[ $i ];
$url='http://www.example.com?userid='.$userid.'&startdate='.$startdate.'&enddate='.$enddate;
echo $url,'<br />';
/* uncomment when happy with mechanism */
/*
$data=file_get_contents( $url );
if( $data ) ) {
$json=json_decode( $data );
#process.....
break;
}
*/
}
$i++;
}
A snippet of the output
http://www.example.com?userid=bobodaclown&startdate=2017-10-01&enddate=2017-09-01
http://www.example.com?userid=bobodaclown&startdate=2017-09-01&enddate=2017-08-01
http://www.example.com?userid=bobodaclown&startdate=2017-08-01&enddate=2017-07-01
http://www.example.com?userid=bobodaclown&startdate=2017-07-01&enddate=2017-06-01
http://www.example.com?userid=bobodaclown&startdate=2017-06-01&enddate=2017-05-01
http://www.example.com?userid=bobodaclown&startdate=2017-05-01&enddate=2017-04-01
http://www.example.com?userid=bobodaclown&startdate=2017-04-01&enddate=2017-03-01
By using strtotime() and mktime() functions you can while loop until you get Null results. The below code will print 5 urls for 5 months. Change while condition accordingly.
// define $i
$i=0;
$userid = '343';//$_GET['userid']; //dont forget to replace with userid
do{
$timestring = strtotime("now -$i month");
//get Month
$month = date('m',$timestring);
//get Year
$year = date('Y',$timestring);
// First date Month and Year
$startdate = date('d-m-Y', mktime(0, 0, 0, $month, 1, $year));
// Last date Month and Year
$enddate = date('d-m-Y', mktime(0, 0, 0, $month+1, 0,$year));
$url='http://www.example.com?userid='.$userid.'&startdate='.$startdate.'&enddate='.$enddate;
// commenting your code
//Set JSON variables:
//$get=file_get_contents($url);
//$json=json_decode($get);
// $number=$json->integer;
echo $url;
echo "\n";
$i++;
}while ($i!=5); // change while condition according to your requirement. while ($number!=null)
Out Put:
http://www.example.com?userid=343&startdate=01-12-2017&enddate=31-12-2017
http://www.example.com?userid=343&startdate=01-11-2017&enddate=30-11-2017
http://www.example.com?userid=343&startdate=01-10-2017&enddate=31-10-2017
http://www.example.com?userid=343&startdate=01-09-2017&enddate=30-09-2017
http://www.example.com?userid=343&startdate=01-08-2017&enddate=31-08-2017

Delete ACF Field from the backend with expired date

I have an ACF field called sub seminars, inside this is another field called sub seminars which is a repeater field containing start_date and end_date.
I have posts that have several rows of this field.
I want to delete the row of the repeater field which has an expired date in it from the backend so that it doesn't show up in the front end.
I am using this function to achieve this but somethings are not working.
add_filter('acf/load_value/name=repeater_field_name', 'delete_old_courses_by_date');
function delete_old_courses_by_date($rows, $post_id, $field) {
if (!is_array($value) || !count($value)) {
return $value;
}
// get the current timestamp
$now = time();
// set up a new array to hold the values we keep
$new_value = array();
foreach ($rows as $row) {
// the php strtotime() function could fail depending on
// the return format of the date/time fields
// this requires a valid date/time format as documented here
// http://php.net/manual/en/datetime.formats.php
// if this does not work I probably won't be much help figuring
// our how to covert your return value to something usable
$start = strtotime($row['start_date']);
$end = strtotime($row['end_date']);
if ($start > $now || $end > $now) {
$new_value[] = $row;
}
}
return $new_value;
}
If I put repeater_field_name as start_date, all the start_date rows are deleted.
Please not my date format is Ymd and I don't know if the format is compatible with strtotime() function
Any help would be really appreciated.
This is what finally worked for me
<?php for($i=0;$i<10;$i++){
$ap = get_post_meta($post->ID,'sub_seminars_'.$i.'_start_date',true);
$startdate = date("Ymd", strtotime($ap));
$todaydate = date("Ymd");
if(strtotime($todaydate) > strtotime($startdate) && !empty($ap)){
$del_data = array(
'Ref' => 'sub_seminars_'.$i.'_ref',
'Start date' => 'sub_seminars_'.$i.'_start_date',
'End Date' => 'sub_seminars_'.$i.'_end_date',
'Venue' => 'sub_seminars_'.$i.'_venue',
'Fees' => 'sub_seminars_'.$i.'_fees',
'CPE Credits' => 'sub_seminars_'.$i.'_cpe_credits'
);
delete_row('sub_seminars', 1);
}
} ?>
Hope this helps to someone else.

Wordpress | Apply function at specific times of the day

I have this function to hide a woocommerce category based on category slug. See here:
/* Exclude Category from Shop*/
add_filter( 'get_terms', 'get_subcategory_terms', 10, 3 );
function get_subcategory_terms( $terms, $taxonomies, $args ) {
$new_terms = array();
// if a product category and on the shop page
if ( in_array( 'product_cat', $taxonomies ) && ! is_admin() && is_shop() ) {
foreach ( $terms as $key => $term ) {
if ( ! in_array( $term->slug, array( 'suviche' ) ) ) {
$new_terms[] = $term;
}
}
$terms = $new_terms;
}
return $terms;
}
And I have this other code to Apply Rules If Time is within the frame marked ( 9am - 5pm )
<?php
$hr = date("H"); //get the hour in terms of double digits
$min= date("i"); //get the minutes in terms of double digits
$t = ($hr*60)+$min; //convert the current time into minutes
$f = (60*9); //calculate 9:00AM in minutes
$s = (60*17); //calculate 5:00PM in minutes
if(($t>f || $t<s)) //if the current time is between 9:00am to 5:00pm then don't apply function
{
//DO NOTHIGN
}
else //otherwise show execute function
{
//EXECUTE FUNCTION
}
?>
What I want to do is to run the filter to hide the product category if is out of the time fram ( 9am - 5pm )
Any Ideas would be great!
So far I have this but nothing:
/* Exclude Category from Shop*/
add_filter( 'get_terms', 'get_subcategory_terms', 10, 3 );
function get_subcategory_terms( $terms, $taxonomies, $args ) {
$new_terms = array();
$hr = date("H"); //get the hour in terms of double digits
$min= date("i"); //get the minutes in terms of double digits
$t = ($hr*60)+$min; //convert the current time into minutes
$f = (60*9); //calculate 9:00AM in minutes
$s = (60*17); //calculate 5:00PM in minutes
// if a product category and on the shop page
if ( ( $t>f || $t<s) && in_array( 'product_cat', $taxonomies ) && ! is_admin() ) {
foreach ( $terms as $key => $term ) {
if ( ! in_array( $term->slug, array( 'suviche' ) ) ) {
$new_terms[] = $term;
}
}
$terms = $new_terms;
}
return $terms;
}
Thanks again to whoever might help!
Hi the problem is you're not getting 9am for the day. You are just getting 9am for 1970, January 1st. Also, I wouldn't suggest working with minutes. Work with seconds.
Whenever you work with time in PHP, know that it is often beneficial to use a unix timestamp. A unix timestamp is a running count of the number of seconds that have elapsed since 1st January, 1970.
A handy converter can be found here
Try this instead.
$curTime = strtotime("now"); //get the current time
$finishTime = strtotime('9am '.date('d-m-Y')); //calculate 9:00AM in seconds
$startTime = strtotime('5pm '.date('d-m-Y')); //calculate 5:00PM in seconds
if(!($curTime > $startTime && $curTime < $finishTime)){
//If we get into here then we're outside of the time range.
}
What we're doing here is using strtotime("now") to get the current time, and date() to get todays date, which is being concatenated with the time you want(9am and 5am). We're then using strtotime, to convert the whole thing into a unix timestamp. Which you can then compare later to see if the current time is greater or lesser than.
Also, these variables need $ in front of them.
( $t>$f || $t<$s )
Hope this helps.

I want to add 100 years to the displayed wordpress dates

I'm going to create a "future"-blogg (sort of a sci-fi-adventure in blog form) and want to display all dates +100 years. For instance a post published 2012-05-17 should display the date 2112-05-17.
First I thought I could just easily set the date to 2112-05-17, but it seems that wordpress can't handle dates higher than 2049.
So my next idea is to modify how the dates are displayed. I was thinking of modifying get_the_date() in general-template.php, and make it return the later date.
But here my skills are not enough. I don't know anything about how to work with date values in php.
get_the_date() looks like this:
function get_the_date( $d = '' ) {
global $post;
$the_date = '';
if ( '' == $d )
$the_date .= mysql2date(get_option('date_format'), $post->post_date);
else
$the_date .= mysql2date($d, $post->post_date);
return apply_filters('get_the_date', $the_date, $d);
}
Any ideas on how to modify it? So it adds 100 years to the date before returning it?
Any input would be appriciated :)
Looks like you might need to investigate date_modify and also strtotime
http://php.net/manual/en/datetime.modify.php
http://www.php.net/manual/en/function.strtotime.php
http://www.php.net/manual/en/datetime.add.php
Assuming your mysql dates are of the following format: YYYY-MM-DD
function add100yr( $date="2011-03-04" ) {
$timezone=date_timezone_get();
date_default_timezone_set($timezone);
list($year, $month, $day) = split(':', $date);
$timestamp=mktime(0,0,0, $month, $day, $year);
// 100 years, 365.25 days/yr, 24h/day, 60min/h, 60sec/min
$seconds = 100 * 365.25 * 24 * 60 * 60;
$newdate = date("Y-m-d", $timestamp+$seconds );
// $newdate is now formatted YYYY-mm-dd
}
Now you can:
function get_the_date( $d = '' ) {
global $post;
$the_date = '';
if ( '' == $d )
$the_date .= mysql2date(get_option('date_format'), add100yr($post->post_date));
else
$the_date .= mysql2date($d, add100yr($post->post_date));
return apply_filters('get_the_date', $the_date, $d);
}
Try a custom field: http://codex.wordpress.org/Custom_Fields
You will have to enter the +100 year date for each post, but then you're not going to be relying on php or functions to alter the current date.
WordPress provides the filter get_the_date that allows to modify the value before it is handled over to the theme or plugin.
This filter is used everytime get_the_date() is called.
add_filter( 'get_the_date', 'modify_get_the_date', 10, 3 );
function modify_get_the_date( $value, $format, $post ) {
$date = new DateTime( $post->post_date );
$date->modify( "+100 years" );
if ( $format == "" )
$format = get_option( "date_format" );
return( $date->format( $format ) );
}
This function takes the post_date from the post, adds the time and returns it according to the format given to get_the_date() or with the default format configured in the WordPress options.

Categories