Hello,

I have a plugin, which is calculating pregnancy weeks. But I want it to save the selected values after user has selected the submit button. Because now, when user clicks on submit button, all the values reset.

Here's the code

function pregwcalc_add_page()
{
	add_submenu_page('plugins.php', 'Pregnancy week calculator', 'Pregnancy week calculator', 8, __FILE__, 'pregwcalc_options');
}

// pregwcalc_options() displays the page content for the pregwcalc Options submenu
function pregwcalc_options($widget_mode=false) 
{
    // Read in existing option value from database
    $pregwcalc_table = stripslashes( get_option( 'pregwcalc_table' ) );

// See if the user has posted us some information
// If they did, this hidden field will be set to 'Y'
if( $_POST[ 'pcalc_update' ] == 'Y' ) 
{
    // Read their posted value
    $pregwcalc_table = $_POST[ 'pregwcalc_table' ];


    // Save the posted value in the database
    update_option( 'pregwcalc_table', $pregwcalc_table );

    // Put an options updated message on the screen
	?>
	<div class="updated"><p><strong><?php _e('Options saved.', 'pregwcalc_domain' ); ?></strong></p></div>
	<?php		
 }

	 // Now display the options editing screen
	    echo '<div class="wrap">';		
	    // header
	    echo "<h2>" . __( 'Pregnancy week calculator Options', 'pregwcalc_domain' ) . "</h2>";		
	    // options form		    
	    ?>

    <?php if(!$widget_mode):?>
	<form name="form1" method="post" action="<?php echo str_replace( '%7E', '~', $_SERVER['REQUEST_URI']); ?>">
    <?php endif;?>    
	<input type="hidden" name="pcalc_update" value="Y">

	<p><?php _e("<p>You can use this calculator in two ways: as a standard Wordpress widget or by placing it in your post or page. For the latter please include the tag <b>[pregnancy-calculator]</b> in the content of your page or post and the calculator will appear there.</p>
    <p>These options are accessible both from the \"Pregnancy calculator\" page under your Plugins menu or from your Widgets section.</p>
    <p>Check out some more of our <a href='http://calendarscripts.info/free-calculators.html' target='_blank'>free calculators</a>.</p>
    <p>CSS class definition for the predictor wrapper div &lt;div&gt;:</p>", 'pregwcalc_domain' ); ?> 
	<textarea name="pregwcalc_table" rows='5' cols='70'><?php echo stripslashes ($pregwcalc_table); ?></textarea>
	</p><hr />

    <?php if(!$widget_mode):?>
		<p class="submit">
		<input type="submit" name="Submit" value="<?php _e('Update Options', 'pregwcalc_domain' ) ?>" />
		</p>

		</form>
    <?php endif;?>
	</div>
	<?php
}

function pregwcalc_datechooser($name,$value="")
{
	$daySelected = '';
	if (isset($_POST['day'])) { $daySelected = $_POST['day']; }


$months=array('','Sausis','Vasaris','Kovas','Balandis','Geguž&#279;','Birželis','Liepa','Rugpj&#363;tis',
'Rugs&#279;jis','Spalis','Lapkritis','Gruodis');

if(empty($value)) $value=date("Y-m-d");

$parts=explode("-",$value);

$day=$parts[2]+0;
$month=$parts[1]+0;
$year=$parts[0];

$chooser="";

$chooser.="<select name=".$name."day>";
for($i=1;$i<=31;$i++)
{
	if($i==$day) $selected='selected';
	else $selected='';
	$chooser.="<option $selected>$i</option>";
}
$chooser.="</select>  ";

$chooser.="<select name=".$name."month>";
for($i=1;$i<=12;$i++)
{
	if($i==$month) $selected='selected';
	else $selected='';
	$chooser.="<option $selected value=$i>$months[$i]</option>";
}
$chooser.="</select>  ";

$chooser.="<select name=".$name."year>";
for($i=(date("Y")-1);$i<=(date("Y")+1);$i++)
{
	if($i==$year) $selected='selected';
	else $selected='';
	$chooser.="<option $selected>$i</option>";
}
$chooser.="</select> ";	

return $chooser;
}

function pregwcalc_generate_html()
{
    //construct the calculator page	
	$prcalc="<style type=\"text/css\">
	.pregwcalc_table
	{
		".get_option('pregwcalc_table')."
	}
	</style>\n\n";

if(!empty($_POST['calculator_ok']))
{
	//last cycle date
	$date="$_POST[dateyear]-$_POST[datemonth]-$_POST[dateday]";

	//convert to time
	$lasttime=mktime(0,0,0,$_POST[datemonth],$_POST[dateday],$_POST[dateyear]);

	//first fertile day
	$firstdaytime=$lasttime + $_POST[days]*24*3600 - 16*24*3600;
	$firstday=date("Y.m.d",$firstdaytime);

	//last fertile day
	$lastdaytime=$lasttime + $_POST[days]*24*3600 - 12*24*3600;
	$lastday=date("Y.m.d",$lastdaytime);

	//current date
	$currentDate = strtotime(date("Y-m-d"));

	//pregnancy week
	$pregnancyweektime=$currentDate - $lasttime;
	$pregnancyweeknumber=$pregnancyweektime / 86400 / 7;
	$pregnancyweek=ceil($pregnancyweeknumber);

	//have to adjust due date?
	$diff=$_POST[days] - 28;

	//due date $date + 280 days
	$duedatetime=$lasttime + 280*24*3600 + $diff*24*3600;
	$duedate=date("Y.m.d",$duedatetime);

	//due date in days
	$duedateindaystime= $duedatetime - $currentDate;
	$duedateindaysvalue=$duedateindaystime / 86400;
	if ( $duedateindaysvalue <= 0 )
		{
	$duedateindays = 0;
		}
	else {
	$duedateindays=$duedateindaysvalue;
		}


	//the result is here



	$prcalc.='<div class="nestumo-skaiciuokle">
	<form method="post">
	Pirmoji paskutini&#371; m&#279;nesini&#371; diena:<br /><br />
	'.pregwcalc_datechooser("date",date("Y-m-d")).'<br><br>
	M&#279;nesini&#371; ciklo trukm&#279;: <select name="days">';

	for($i=20;$i<=45;$i++)
	{
		if($i==28) $selected='selected';
		else $selected='';
		$prcalc.="<option $selected value='$i'>$i</option>";
	}

	$prcalc.='</select>
	<p align="left"><input type="submit" name="calculator_ok" value="Skai&#269;iuoti"></p>
	</form>		
	</div><br />';

		if ($duedateindaysvalue < -7 )
			{
			$prcalc.='<div class="pregwcalc_table">
	<h2> Vaikelis tur&#279;jo gimti </h2>
	</div>';
			}

		if ($duedateindaysvalue >= -7 & $pregnancyweeknumber <= 41 &$pregnancyweeknumber >= 5 )
			{

	$prcalc.='<div class="nestumo-skaiciuokle">

	<p> <a href="http://www.mamuturgus.lt/nestumas/nestumo-kalendorius/savaite/'.$pregnancyweek.'/">
	<img class="nestumo-savaites-nuotrauka" src="http://www.mamuturgus.lt/wp-content/uploads/2012/05/nestumo-savaite-'.$pregnancyweek.'.jpg" height="150" width="180"></a>
	<a class="nestumo-savaite" href="http://www.mamuturgus.lt/nestumas/nestumo-kalendorius/savaite/'.$pregnancyweek.'/"> '.$pregnancyweek.' n&#279;štumo savait&#279;, iki gimdymo liko '.$duedateindays.' dien&#371;. </a>
	<br />
	<br />
	Apytiksl&#279; gimdymo data: <strong>'.$duedate.'.</strong>
	<br />
	<br />
	<br />
	<span class="nestumo-savaites-aprasymas"> <a href="http://www.mamuturgus.lt/nestumas/nestumo-kalendorius/savaite/'.$pregnancyweek.'/"> Išsamiai apie tavo n&#279;štumo savait&#281;</a></span>
	</p>
	</div>';
			}
		if ($pregnancyweeknumber > 0 & $pregnancyweeknumber < 5 )
				{
		$prcalc.='<div class="nestumo-skaiciuokle">
	Jei m&#279;nesin&#279;s v&#279;luoja, gali b&#363;ti, kad tu laukiesi. <br />
	<a href="http://www.mamuturgus.lt/nestumas/nestumo-kalendorius/savaite/'.$pregnancyweek.'/">
	<img class="nestumo-savaites-nuotrauka" src="http://www.mamuturgus.lt/wp-content/uploads/2012/05/nestumo-savaite-'.$pregnancyweek.'.jpg" height="150" width="180"></a>
	Jei tikrai pastojai, <br />apytiksl&#279; gimdymo data b&#363;t&#371;: <strong>'.$duedate.' </strong> <br />
	<p>Tuomet tai b&#363;t&#371; <a class="nestumo-savaite" href="http://www.mamuturgus.lt/nestumas/nestumo-kalendorius/savaite/'.$pregnancyweek.'/"> '.$pregnancyweek.' n&#279;štumo savait&#279;. </a></p><br />
	<p class="nestumo-savaites-aprasymas"><a href="http://www.mamuturgus.lt/nestumas/nestumo-kalendorius/savaite/'.$pregnancyweek.'/"> Išsamiai apie tavo n&#279;štumo savait&#281;</a></p>
	</div>';
				}
		if ($pregnancyweeknumber <= 0)
				{
	$prcalc.='<div class="nestumo-skaiciuokle">
	J&#363;s&#371; sekantis vaisingiausias periodas yra nuo <strong>'.$firstday.' iki '.$lastday.'</strong>.<br ><br />
	Jeigu pastosite šio termino metu, vaikelis gims <strong>'.$duedate.'</strong>	
	</div>';
				}
}
else
{
	$prcalc.='<div class="nestumo-skaiciuokle">
	<form method="post">
	Pirmoji paskutini&#371; m&#279;nesini&#371; diena:<br /><br />
	'.pregwcalc_datechooser("date",date("Y-m-d")).'<br><br>
	M&#279;nesini&#371; ciklo trukm&#279;: <select name="days">';

	for($i=20;$i<=45;$i++)
	{
		if($i==28) $selected='selected';
		else $selected='';
		$prcalc.="<option $selected value='$i'>$i</option>";
	}

	$prcalc.='</select>
	<p align="left"><input type="submit" name="calculator_ok" value="Skai&#269;iuoti"></p>
	</form>		
	</div>';
}

return $prcalc;
}

I would be very pleased if you could help me with this problem. Since I have very little knowledge about the php, please write the solution as it would be for a noob 🙂

Thanks!

    1. I strongly recommend that you change your functions so that they do not output anything (remove echoes and prints). This also takes care of the issue with functions jumping in and out of php parsing mode. While all this works, reading the code becomes difficult, since it tangles logic and presentation together.
    2. Why do you have stripslashes here and there in your code? Is magipc_quotes_gpc (GPC = GET POST COOKIES) turned on in php.ini? If so, disable it and escape things as needed for each particular purpose. I.e. use your db specific escape mechanism, such as mysqli::escape_string, when inserting strings into the database, htmlentities when outputting strings to a web page, urlencode when outputting strings in urls etc.

    I havn't gone through all the code in depth due to the issue with entanglement of logic and presentation. But from what I understand I'd change pregwcalc_options into a function which checks if the user has stored an option selection in the db by calling pregwcalc_getuseroption(), and after that retrieves options from the database by calling pregwcalc_getoptions($selected_value). By passing on the selected value to getoptions, you can

    SELECT same, fields, as_before, option_value = $selected_value AS selected
    FROM ...
    

    Then, when you output your options (NOT in this function), you simply check if the option was selected, see pregwcalc_renderoptions() further down. Handling the comparison in SQL works well if you're using PDO where you would not iterate over the result set, but simply call PDO::fetchAll() to get all rows. If you have to cycle over the result set to get all rows, you might want to drop the comparison from the query, and instead do it while iterating over the result set.

    Finally, you may actually have functions that do output things, but then they should do nothing else. If you don't go with functions for this, do it in separate php pages. You should note that this approach means that you no longer have to distringuish between page and widget in any of your functions handling logic. It's only when you come to presentation that there will be a difference! Also, since the options as such are (probably) the same, output of the actual options can also be handled generically. Thus, only the rest of the page / widget has to be dealt with separately.

    if ($widget)
    {
    	pregwcalc_renderwidget($options);
    }
    else
    {
    	pregwcalc_renderpage($options);
    }
    
    # and somewhere inside each of those functions, a call to
    function pregwcalc_renderoptions($options)
    {
    	foreach ($options as $o)
    	{
    		printf('<option value="%d"%s>%s</option>',
    			$o['value'],
    			$o['selected'] ? ' selected="selected"' : '',
    			$o['txt']
    		);
    	}
    }
    

    To use the exact same code when a user posts a new value, start by updating the database

    $errors = array();
    if (isset($_POST['submit_option']))
    {
    	$o = $_POST['submit_option']
    	# whatever checks are necessary to assertain valid data
    	if (!is_numeric($o) || $o < 1 || $o > 53)
    	{
    		$errors[] = 'Unable to save data';		
    	}
    	else
    	{
    		# INSERT / UPDATE here
    	}
    }
    
    # Reest of the code as shown earlier in my post comes here.
    

    Finally, in each of the renderwidget and renderpage functions, add a new parameter $errors and wherever it's appropriate from a layout perspective add a call to

    render_errors($errors);
    

    A minor thing by the way, if someone else will ever look at your code, I'd change the naming from pregw to something else, like for example pw, since there is allready a preg_ family of functions. Or wrap all functions in a pregnancy_week namespace and drop the prefix alltogether.

      Thanks for your wide reply!

      But since I have no understanding in php, only in some simple logic algorithms, like if (from old school turbo pascal, which I learned in my school), I don't understand a heck, what you wrote in explanation...Sorry for that, but thats how it is.

      Thats why I wont be able to optimise the code, but I am happy with it. Only what bothers me, is that values are not remembered after user clicks submit button. Is there any simple way to do it, without changing logics and so on? I would be grateful for the help...

        Write a Reply...