Skip to content

Commit

Permalink
Put in a workaround for the DateTime::modify() bug and moved the mini…
Browse files Browse the repository at this point in the history
…mum PHP version back to 5.3.0. See SF Support Requests #667.

git-svn-id: http://svn.code.sf.net/p/mrbs/code/mrbs/trunk@2973 25f7e783-145e-4f2d-a9f8-dd7182bfe9c7
  • Loading branch information
cimorrison committed Jan 21, 2015
1 parent 1ec9be4 commit cb12673
Show file tree
Hide file tree
Showing 7 changed files with 105 additions and 8 deletions.
2 changes: 1 addition & 1 deletion INSTALL
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ info on setting these up. You need to know how to install, secure, run,
maintain, and back up your chosen database system.

No optional PHP packages (other than the database system) are required for
this application. PHP Version 5.3.6 or later is required.
this application. PHP Version 5.3.0 or later is required.

You can run PHP either as a CGI or with a direct module interface (also called
SAPI). These servers include Apache, Microsoft Internet Information Server,
Expand Down
1 change: 1 addition & 0 deletions web/defaultincludes.inc
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
// are assigned to variables will change depending on the context in which the file
// is called.

require_once "lib/autoload.inc";
require "grab_globals.inc.php";
require_once "systemdefaults.inc.php";
require_once "areadefaults.inc.php";
Expand Down
8 changes: 5 additions & 3 deletions web/functions.inc
Original file line number Diff line number Diff line change
Expand Up @@ -313,15 +313,17 @@ function getPeriodInterval($start_time, $end_time)

$periods_per_day = count($periods);

$startDate = new DateTime();
// Need to use the MRBS version of DateTime to get round a bug in modify()
// in PHP before 5.3.6
$startDate = new MRBS\DateTime();
$startDate->setTimestamp($start_time);
$endDate = new DateTime();
$endDate = new MRBS\DateTime();
$endDate->setTimestamp($end_time);

// Set both dates to noon so that we can compare them and get an integral
// number of days difference. Noon also happens to be when periods start,
// so will be useful in a moment.
$startDate->modify('12:00'); // This won't work in PHP < 5.3.6 (bug)
$startDate->modify('12:00');
$endDate->modify('12:00');

// Calculate the difference in days
Expand Down
3 changes: 1 addition & 2 deletions web/internalconfig.inc.php
Original file line number Diff line number Diff line change
Expand Up @@ -113,8 +113,7 @@
********************************************************/

// Check PHP version
// We need 5.3.6 because it fixes a bug that causes DateTime::modify('noon') not to work
$min_PHP_version = '5.3.6';
$min_PHP_version = '5.3.0';
if (!function_exists('version_compare') || version_compare(PHP_VERSION, $min_PHP_version) < 0)
{
die("MRBS requires PHP $min_PHP_version or above. This server is running version " . PHP_VERSION . ".");
Expand Down
75 changes: 75 additions & 0 deletions web/lib/MRBS/DateTime.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
<?php
namespace MRBS;

class DateTime extends \DateTime
{
// Workaround for a bug that was fixed in PHP 5.3.6
// Only supports a limited range of $modify strings for PHP < 5.3.6. Throws
// an exception if passed a string that it can't handle (maybe it should just
// generate a warning? - that's what the global DateTime does)
public function modify($modify)
{
if (version_compare(PHP_VERSION, '5.3.6') >= 0)
{
return parent::modify($modify);
}

$date = getdate($this->getTimestamp());
$modification = self::parse($modify);

foreach ($modification as $unit => $amount)
{
switch($amount['mode'])
{
case 'absolute':
$date[$unit] = $amount['quantity'];
break;
case 'relative':
$date[$unit] = $date[$unit] + $amount['quantity'];
break;
default:
throw new Exception ("Unknown mode '" . $amount['mode'] . "'");
break;
}
}

$modified_timestamp = mktime($date['hours'], $date['minutes'], $date['seconds'],
$date['mon'], $date['mday'], $date['year']);

return $this->setTimestamp($modified_timestamp);
}


// Parse the $modify string and return an array of any modifications that are necessary.
// The array is indexed at the top level by 'hours', 'minutes', 'seconds', 'mon', 'mday' and
// 'year' - ie the same keys that the output of getdate() uses. Each value is itself an array,
// indexed by 'mode' (can be 'relative' or 'absolute') and then 'quantity'. If the mode is
// relative then the quantity is added to the original, if absolute then it replaces the original.
private static function parse($modify)
{
$modify = self::map($modify);

// Test for a simple hh:mm pattern (or hhmm or hh.mm)
$pattern = '/([01][0-9]|[2][0-3])[.:]?([0-5][0-9])/';
if (preg_match($pattern, $modify, $matches))
{
return array('hours' => array('mode' => 'absolute',
'quantity' => $matches[1]),
'minutes' => array('mode' => 'absolute',
'quantity' => $matches[2]));
}

// Could add more tests later if need be.
throw new Exception("Modify string '$modify' not supported by MRBS");
}


// Replace some simple modify strings with their numeric alternatives.
private static function map($modify)
{
$mappings = array('midnight' => '00:00',
'noon' => '12:00');

return (isset($mappings[$modify])) ? $mappings[$modify] : $modify;
}
}
17 changes: 17 additions & 0 deletions web/lib/autoload.inc
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<?php

// $Id$

spl_autoload_register(function ($class) {

$base_dir = __DIR__ . '/';

// Replace namespace separators with directory separators.
// Append '.php'
$file = $base_dir . str_replace('\\', '/', $class) . '.php';

if (file_exists($file))
{
require $file;
}
});
7 changes: 5 additions & 2 deletions web/report.php
Original file line number Diff line number Diff line change
Expand Up @@ -877,10 +877,13 @@ function accumulate(&$row, &$count, &$hours, $report_start, $report_end,
// on those days. Otherwise if the report starts or ends in the middle of a multi-day
// booking we'll get all those spurious minutes before noon or between the end of
// the last period and midnight
$startDate = new DateTime();

// Need to use the MRBS version of DateTime to get round a bug in modify()
// in PHP before 5.3.6
$startDate = new MRBS\DateTime();
$startDate->setTimestamp($report_start)->modify('12:00');

$endDate = new DateTime();
$endDate = new MRBS\DateTime();
$endDate->setTimestamp($report_end)->modify('12:00');
$endDate->sub(new DateInterval('P1D')); // Go back one day because the $report_end is at 00:00 the day after
$endDate->add(new DateInterval('PT' . $periods_per_day . 'M'));
Expand Down

0 comments on commit cb12673

Please sign in to comment.