summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKore Nordmann <github@kore-nordmann.de>2006-08-09 08:08:43 +0000
committerKore Nordmann <github@kore-nordmann.de>2006-08-09 08:08:43 +0000
commit7590db4ae7a46bf9fdf71813a4e00ce3eb1c67f9 (patch)
tree6368608582d5932a1dc8a8568cebc8a7fdb52471
parent63b5d5f3f2dee22c890d219aeb8e4cc7fd228f41 (diff)
downloadzetacomponents-graph-7590db4ae7a46bf9fdf71813a4e00ce3eb1c67f9.zip
zetacomponents-graph-7590db4ae7a46bf9fdf71813a4e00ce3eb1c67f9.tar.gz
- Added date axis
-rw-r--r--src/axis/date.php385
-rw-r--r--src/graph_autoload.php1
-rw-r--r--tests/date_axis_test.php354
-rw-r--r--tests/suite.php2
4 files changed, 742 insertions, 0 deletions
diff --git a/src/axis/date.php b/src/axis/date.php
new file mode 100644
index 0000000..5f58a32
--- /dev/null
+++ b/src/axis/date.php
@@ -0,0 +1,385 @@
+<?php
+/**
+ * File containing the abstract ezcGraphChartElementDateAxis class
+ *
+ * @package Graph
+ * @version //autogentag//
+ * @copyright Copyright (C) 2005, 2006 eZ systems as. All rights reserved.
+ * @license http://ez.no/licenses/new_bsd New BSD License
+ */
+/**
+ * Class to represent a axe as a chart element
+ *
+ * @package Graph
+ */
+class ezcGraphChartElementDateAxis extends ezcGraphChartElementAxis
+{
+
+ /**
+ * Minimum inserted date
+ *
+ * @var int
+ */
+ protected $minValue = false;
+
+ /**
+ * Maximum inserted date
+ *
+ * @var int
+ */
+ protected $maxValue = false;
+
+ /**
+ * Starting date used to display on axis
+ *
+ * @var float
+ */
+ protected $startDate = false;
+
+ /**
+ * End date used to display on axis
+ *
+ * @var float
+ */
+ protected $endDate = false;
+
+ /**
+ * Time interval between steps on axis
+ *
+ * @var float
+ */
+ protected $interval = false;
+
+ /**
+ * Format of date string
+ *
+ * Like http://php.net/date
+ *
+ * @var string
+ */
+ protected $dateFormat = false;
+
+ /**
+ * Nice time intervals to used if there is no user defined interval
+ *
+ * @var array
+ */
+ protected $predefinedIntervals = array(
+ // Second
+ 1 => 'H:i.s',
+ // Ten seconds
+ 10 => 'H:i.s',
+ // Thirty seconds
+ 30 => 'H:i.s',
+ // Minute
+ 60 => 'H:i',
+ // Ten minutes
+ 600 => 'H:i',
+ // Half an hour
+ 1800 => 'H:i',
+ // Hour
+ 3600 => 'H:i',
+ // Four hours
+ 14400 => 'H:i',
+ // Six hours
+ 21600 => 'H:i',
+ // Half a day
+ 43200 => 'd.m a',
+ // Day
+ 86400 => 'd.m',
+ // Week
+ 604800 => 'W',
+ // Month
+ 2629800 => 'M y',
+ // Year
+ 31536000 => 'Y',
+ // Decade
+ 315360000 => 'Y',
+ );
+
+ /**
+ * Constant used for calculation of automatic definition of major scaling
+ * steps
+ */
+ const MAJOR_COUNT = 10;
+
+ /**
+ * __set
+ *
+ * @param mixed $propertyName
+ * @param mixed $propertyValue
+ * @throws ezcBaseValueException
+ * If a submitted parameter was out of range or type.
+ * @throws ezcBasePropertyNotFoundException
+ * If a the value for the property options is not an instance of
+ * @return void
+ */
+ public function __set( $propertyName, $propertyValue )
+ {
+ switch ( $propertyName )
+ {
+ case 'startDate':
+ $this->startDate = (int) $propertyValue;
+ break;
+ case 'endDate':
+ $this->endDate = (int) $propertyValue;
+ break;
+ case 'interval':
+ $this->interval = (int) $propertyValue;
+ break;
+ case 'dateFormat':
+ $this->dateFormat = (string) $propertyValue;
+ break;
+ default:
+ parent::__set( $propertyName, $propertyValue );
+ break;
+ }
+ }
+
+ /**
+ * Add data for this axis
+ *
+ * @param mixed $value Value which will be displayed on this axis
+ * @return void
+ */
+ public function addData( array $values )
+ {
+ foreach ( $values as $value )
+ {
+ if ( is_numeric( $value ) )
+ {
+ $value = (int) $value;
+ }
+ elseif ( ( $value = strtotime( $value ) ) === false )
+ {
+ throw new ezcGraphErrorParsingDateException( $value );
+ }
+
+ if ( $this->minValue === false ||
+ $value < $this->minValue )
+ {
+ $this->minValue = $value;
+ }
+
+ if ( $this->maxValue === false ||
+ $value > $this->maxValue )
+ {
+ $this->maxValue = $value;
+ }
+ }
+ }
+
+ /**
+ * Calculate nice time interval
+ *
+ * Use the best fitting time interval defined in class property array
+ * predefinedIntervals.
+ *
+ * @param int $min Start time
+ * @param int $max End time
+ * @return void
+ */
+ protected function calculateInterval( $min, $max )
+ {
+ $diff = $max - $min;
+
+ foreach ( $this->predefinedIntervals as $interval => $format )
+ {
+ if ( ( $diff / $interval ) <= self::MAJOR_COUNT )
+ {
+ break;
+ }
+ }
+
+ $this->interval = $interval;
+ }
+
+ protected function calculateLowerNiceDate( $min, $interval )
+ {
+ $dateSteps = array( 60, 60, 24, 7, 52 );
+
+ $date = array(
+ (int) date( 's', $min ),
+ (int) date( 'i', $min ),
+ (int) date( 'H', $min ),
+ (int) date( 'd', $min ),
+ (int) date( 'm', $min ),
+ (int) date( 'Y', $min ),
+ );
+
+ $element = 0;
+ while ( ( $step = array_shift( $dateSteps ) ) &&
+ ( $interval > $step ) )
+ {
+ $interval /= $step;
+ $date[$element++] = (int) ( $element > 2 );
+ }
+
+ $date[$element] -= $date[$element] % $interval;
+
+ return mktime(
+ $date[2],
+ $date[1],
+ $date[0],
+ $date[4],
+ $date[3],
+ $date[5]
+ );
+ }
+
+ public function calculateMinimum( $min, $max )
+ {
+ $this->startDate = $this->calculateLowerNiceDate( $min, $this->interval );
+ }
+
+ public function calculateMaximum( $min, $max )
+ {
+ $this->endDate = $this->calculateLowerNiceDate( $max, $this->interval );
+
+ while ( $this->endDate < $max )
+ {
+ $this->endDate += $this->interval;
+ }
+ }
+
+ /**
+ * Calculate axis bounding values on base of the assigned values
+ *
+ * @abstract
+ * @access public
+ * @return void
+ */
+ public function calculateAxisBoundings()
+ {
+ // Prevent division by zero, when min == max
+ if ( $this->minValue == $this->maxValue )
+ {
+ if ( $this->minValue == 0 )
+ {
+ $this->maxValue = 1;
+ }
+ else
+ {
+ $this->minValue -= ( $this->minValue * .1 );
+ $this->maxValue += ( $this->maxValue * .1 );
+ }
+ }
+
+ // Use custom minimum and maximum if available
+ if ( $this->startDate !== false )
+ {
+ $this->minValue = $this->startDate;
+ }
+
+ if ( $this->endDate !== false )
+ {
+ $this->maxValue = $this->endDate;
+ }
+
+ // Calculate "nice" values for scaling parameters
+ if ( $this->interval === false )
+ {
+ $this->calculateInterval( $this->minValue, $this->maxValue );
+ }
+
+ if ( $this->dateFormat === false && isset( $this->predefinedIntervals[$this->interval] ) )
+ {
+ $this->dateFormat = $this->predefinedIntervals[$this->interval];
+ }
+
+ if ( $this->startDate === false )
+ {
+ $this->calculateMinimum( $this->minValue, $this->maxValue );
+ }
+
+ if ( $this->endDate === false )
+ {
+ $this->calculateMaximum( $this->minValue, $this->maxValue );
+ }
+ }
+
+ /**
+ * Get coordinate for a dedicated value on the chart
+ *
+ * @param ezcGraphBounding $boundings
+ * @param float $value Value to determine position for
+ * @return float Position on chart
+ */
+ public function getCoordinate( $value )
+ {
+ // Force typecast, because ( false < -100 ) results in (bool) true
+ $floatValue = (float) $value;
+
+ if ( ( $value === false ) &&
+ ( ( $floatValue < $this->startDate ) || ( $floatValue > $this->endDate ) ) )
+ {
+ switch ( $this->position )
+ {
+ case ezcGraph::LEFT:
+ case ezcGraph::TOP:
+ return 0.;
+ case ezcGraph::RIGHT:
+ case ezcGraph::BOTTOM:
+ return 1.;
+ }
+ }
+ else
+ {
+ switch ( $this->position )
+ {
+ case ezcGraph::LEFT:
+ case ezcGraph::TOP:
+ return ( $value - $this->startDate ) / ( $this->endDate - $this->startDate );
+ case ezcGraph::RIGHT:
+ case ezcGraph::BOTTOM:
+ return 1 - ( $value - $this->startDate ) / ( $this->endDate - $this->startDate );
+ }
+ }
+ }
+
+ /**
+ * Return count of minor steps
+ *
+ * @return integer Count of minor steps
+ */
+ public function getMinorStepCount()
+ {
+ return false;
+ }
+
+ /**
+ * Return count of major steps
+ *
+ * @return integer Count of major steps
+ */
+ public function getMajorStepCount()
+ {
+ return (int) ( ( $this->endDate - $this->startDate ) / $this->interval );
+ }
+
+ /**
+ * Get label for a dedicated step on the axis
+ *
+ * @param integer $step Number of step
+ * @return string label
+ */
+ public function getLabel( $step )
+ {
+ return date( $this->dateFormat, $this->startDate + ( $step * $this->interval ) );
+ }
+
+ /**
+ * Is zero step
+ *
+ * Returns true if the given step is the one on the initial axis position
+ *
+ * @param int $step Number of step
+ * @return bool Status If given step is initial axis position
+ */
+ public function isZeroStep( $step )
+ {
+ return ( $step == 0 );
+ }
+}
+
+?>
diff --git a/src/graph_autoload.php b/src/graph_autoload.php
index 6848661..80502c5 100644
--- a/src/graph_autoload.php
+++ b/src/graph_autoload.php
@@ -60,6 +60,7 @@ return array(
'ezcGraphChartElementLegend' => 'Graph/element/legend.php',
'ezcGraphChartElementBackgroundImage' => 'Graph/element/background.php',
'ezcGraphChartElementAxis' => 'Graph/element/axis.php',
+ 'ezcGraphChartElementDateAxis' => 'Graph/axis/date.php',
'ezcGraphChartElementNumericAxis' => 'Graph/axis/numeric.php',
'ezcGraphChartElementLabeledAxis' => 'Graph/axis/labeled.php',
diff --git a/tests/date_axis_test.php b/tests/date_axis_test.php
new file mode 100644
index 0000000..a78f1cc
--- /dev/null
+++ b/tests/date_axis_test.php
@@ -0,0 +1,354 @@
+<?php
+/**
+ * ezcGraphDateAxisTest
+ *
+ * @package Graph
+ * @version //autogen//
+ * @subpackage Tests
+ * @copyright Copyright (C) 2005, 2006 eZ systems as. All rights reserved.
+ * @license http://ez.no/licenses/new_bsd New BSD License
+ */
+
+/**
+ * Tests for ezcGraph class.
+ *
+ * @package ImageAnalysis
+ * @subpackage Tests
+ */
+class ezcGraphDateAxisTest extends ezcTestCase
+{
+
+ protected $chart;
+
+ public static function suite()
+ {
+ return new ezcTestSuite( "ezcGraphDateAxisTest" );
+ }
+
+ /**
+ * setUp
+ *
+ * @access public
+ */
+ public function setUp()
+ {
+ date_default_timezone_set( 'Europe/Berlin' );
+
+ $this->chart = new ezcGraphLineChart();
+ $this->chart->xAxis = new ezcGraphChartElementDateAxis();
+ }
+
+ /**
+ * tearDown
+ *
+ * @access public
+ */
+ public function tearDown()
+ {
+ unset( $this->chart );
+ }
+
+ public function testManualScaling()
+ {
+ $this->chart->xAxis->startDate = 0;
+ $this->chart->xAxis->endDate = 100;
+ $this->chart->xAxis->interval = 10;
+
+ $this->chart['some data'] = array( 10 => 12, 37 => 235, 43 => 17, 114 => 39 );
+
+ $this->chart->render( 500, 200 );
+
+ $this->assertEquals(
+ 0,
+ $this->getNonPublicProperty( $this->chart->xAxis, 'startDate' ),
+ 'Wrong starting date. '
+ );
+
+ $this->assertEquals(
+ 100,
+ $this->getNonPublicProperty( $this->chart->xAxis, 'endDate' ),
+ 'Wrong end date. '
+ );
+
+ $this->assertEquals(
+ 10,
+ $this->getNonPublicProperty( $this->chart->xAxis, 'interval' ),
+ 'Wrong interval. '
+ );
+ }
+
+ public function testManualBoundingsForScaling()
+ {
+ $this->chart->xAxis->startDate = 0;
+ $this->chart->xAxis->endDate = 100;
+
+ $this->chart['some data'] = array( 10 => 12, 37 => 235, 43 => 17, 114 => 39 );
+
+ $this->chart->render( 500, 200 );
+
+ $this->assertEquals(
+ 0,
+ $this->getNonPublicProperty( $this->chart->xAxis, 'startDate' ),
+ 'Wrong starting date. '
+ );
+
+ $this->assertEquals(
+ 100,
+ $this->getNonPublicProperty( $this->chart->xAxis, 'endDate' ),
+ 'Wrong end date. '
+ );
+
+ $this->assertEquals(
+ 10,
+ $this->getNonPublicProperty( $this->chart->xAxis, 'interval' ),
+ 'Wrong interval. '
+ );
+ }
+
+ public function testManualIntervalForScaling()
+ {
+ $this->chart->xAxis->interval = 10;
+
+ $this->chart['some data'] = array( 10 => 12, 37 => 235, 43 => 17, 114 => 39 );
+
+ $this->chart->render( 500, 200 );
+
+ $this->assertEquals(
+ 10,
+ $this->getNonPublicProperty( $this->chart->xAxis, 'startDate' ),
+ 'Wrong starting date. '
+ );
+
+ $this->assertEquals(
+ 120,
+ $this->getNonPublicProperty( $this->chart->xAxis, 'endDate' ),
+ 'Wrong end date. '
+ );
+
+ $this->assertEquals(
+ 10,
+ $this->getNonPublicProperty( $this->chart->xAxis, 'interval' ),
+ 'Wrong interval. '
+ );
+ }
+
+ public function testAutomagicScalingSingle1()
+ {
+ $this->chart['some data'] = array( 10 => 12, 37 => 235, 43 => 17, 114 => 39 );
+ $this->chart->render( 500, 200 );
+
+ $this->assertEquals(
+ 0,
+ $this->getNonPublicProperty( $this->chart->xAxis, 'startDate' ),
+ 'Wrong starting date. '
+ );
+
+ $this->assertEquals(
+ 120,
+ $this->getNonPublicProperty( $this->chart->xAxis, 'endDate' ),
+ 'Wrong end date. '
+ );
+
+ $this->assertEquals(
+ 30,
+ $this->getNonPublicProperty( $this->chart->xAxis, 'interval' ),
+ 'Wrong interval. '
+ );
+ }
+
+ public function testAutomagicScalingSingle2()
+ {
+ $this->chart['some data'] = array( 30010 => 12, 30037 => 235, 30043 => 17, 30114 => 39 );
+ $this->chart->render( 500, 200 );
+
+ $this->assertEquals(
+ 30000,
+ $this->getNonPublicProperty( $this->chart->xAxis, 'startDate' ),
+ 'Wrong starting date. '
+ );
+
+ $this->assertEquals(
+ 30120,
+ $this->getNonPublicProperty( $this->chart->xAxis, 'endDate' ),
+ 'Wrong end date. '
+ );
+
+ $this->assertEquals(
+ 30,
+ $this->getNonPublicProperty( $this->chart->xAxis, 'interval' ),
+ 'Wrong interval. '
+ );
+ }
+
+ public function testAutomagicScalingSingle3()
+ {
+ $this->chart['some data'] = array(
+ mktime( 10, 13, 57, 5, 7, 2006 ) => 324,
+ mktime( 10, 46, 13, 5, 7, 2006 ) => 324,
+ mktime( 11, 15, 45, 5, 7, 2006 ) => 324,
+ mktime( 12, 32, 01, 5, 7, 2006 ) => 324,
+ );
+ $this->chart->render( 500, 200 );
+
+ $this->assertEquals(
+ 'Sun, 07 May 2006 10:00:00 +0200',
+ date( 'r', $this->getNonPublicProperty( $this->chart->xAxis, 'startDate' ) ),
+ 'Wrong starting date. '
+ );
+
+ $this->assertEquals(
+ 'Sun, 07 May 2006 13:00:00 +0200',
+ date( 'r', $this->getNonPublicProperty( $this->chart->xAxis, 'endDate' ) ),
+ 'Wrong end date. '
+ );
+
+ $this->assertEquals(
+ 1800,
+ $this->getNonPublicProperty( $this->chart->xAxis, 'interval' ),
+ 'Wrong interval. '
+ );
+ }
+
+ public function testAutomagicScalingSingle4()
+ {
+ $this->chart['some data'] = array(
+ mktime( 10, 13, 57, 5, 7, 2006 ) => 324,
+ mktime( 17, 46, 13, 5, 7, 2006 ) => 324,
+ mktime( 11, 15, 45, 5, 8, 2006 ) => 324,
+ mktime( 20, 32, 1, 5, 8, 2006 ) => 324,
+ mktime( 8, 43, 19, 5, 9, 2006 ) => 324,
+ );
+ $this->chart->render( 500, 200 );
+
+ $this->assertEquals(
+ 'Sun, 07 May 2006 06:00:00 +0200',
+ date( 'r', $this->getNonPublicProperty( $this->chart->xAxis, 'startDate' ) ),
+ 'Wrong starting date. '
+ );
+
+ $this->assertEquals(
+ 'Tue, 09 May 2006 12:00:00 +0200',
+ date( 'r', $this->getNonPublicProperty( $this->chart->xAxis, 'endDate' ) ),
+ 'Wrong end date. '
+ );
+
+ $this->assertEquals(
+ 21600,
+ $this->getNonPublicProperty( $this->chart->xAxis, 'interval' ),
+ 'Wrong interval. '
+ );
+ }
+
+ public function testAutomagicScalingSingle5()
+ {
+ $this->chart['some data'] = array(
+ mktime( 1, 0, 0, 1, 1, 2001 ) => 324,
+ mktime( 1, 0, 0, 1, 1, 2002 ) => 324,
+ mktime( 1, 0, 0, 1, 1, 2003 ) => 324,
+ mktime( 1, 0, 0, 1, 1, 2004 ) => 324,
+ );
+ $this->chart->render( 500, 200 );
+
+ $this->assertEquals(
+ 'Mon, 01 Jan 2001 01:00:00 +0100',
+ date( 'r', $this->getNonPublicProperty( $this->chart->xAxis, 'startDate' ) ),
+ 'Wrong starting date. '
+ );
+
+ $this->assertEquals(
+ 'Thu, 01 Jan 2004 01:00:00 +0100',
+ date( 'r', $this->getNonPublicProperty( $this->chart->xAxis, 'endDate' ) ),
+ 'Wrong end date. '
+ );
+
+ $this->assertEquals(
+ 31536000,
+ $this->getNonPublicProperty( $this->chart->xAxis, 'interval' ),
+ 'Wrong interval. '
+ );
+ }
+
+ public function testPositionLeft()
+ {
+ $this->chart['some data'] = array(
+ mktime( 10, 13, 57, 5, 7, 2006 ) => 324,
+ mktime( 17, 46, 13, 5, 7, 2006 ) => 324,
+ mktime( 11, 15, 45, 5, 8, 2006 ) => 324,
+ mktime( 20, 32, 1, 5, 8, 2006 ) => 324,
+ mktime( 8, 43, 19, 5, 9, 2006 ) => 324,
+ );
+ $this->chart->xAxis->position = ezcGraph::LEFT;
+ $this->chart->render( 500, 200 );
+
+ $this->assertEquals(
+ 0.,
+ $this->chart->xAxis->getCoordinate( false ),
+ 'Wrong initial axis position. ',
+ .05
+ );
+
+ $this->assertEquals(
+ 0.,
+ $this->chart->xAxis->getCoordinate( mktime( 6, 0, 0, 5, 7, 2006 ) ),
+ 'Wrong minimal value. ',
+ .05
+ );
+
+ $this->assertEquals(
+ .575,
+ $this->chart->xAxis->getCoordinate( mktime( 13, 1, 34, 5, 8, 2006 ) ),
+ 'Wrong mid value. ',
+ .05
+ );
+
+ $this->assertEquals(
+ 1.,
+ $this->chart->xAxis->getCoordinate( mktime( 12, 0, 0, 5, 9, 2006 ) ),
+ 'Wrong maximum value. ',
+ .05
+ );
+ }
+
+ public function testPositionRight()
+ {
+ $this->chart['some data'] = array(
+ mktime( 10, 13, 57, 5, 7, 2006 ) => 324,
+ mktime( 17, 46, 13, 5, 7, 2006 ) => 324,
+ mktime( 11, 15, 45, 5, 8, 2006 ) => 324,
+ mktime( 20, 32, 1, 5, 8, 2006 ) => 324,
+ mktime( 8, 43, 19, 5, 9, 2006 ) => 324,
+ );
+ $this->chart->xAxis->position = ezcGraph::RIGHT;
+ $this->chart->render( 500, 200 );
+
+ $this->assertEquals(
+ 1.,
+ $this->chart->xAxis->getCoordinate( false ),
+ 'Wrong initial axis position. ',
+ .05
+ );
+
+ $this->assertEquals(
+ 1.,
+ $this->chart->xAxis->getCoordinate( mktime( 6, 0, 0, 5, 7, 2006 ) ),
+ 'Wrong minimal value. ',
+ .05
+ );
+
+ $this->assertEquals(
+ .425,
+ $this->chart->xAxis->getCoordinate( mktime( 13, 1, 34, 5, 8, 2006 ) ),
+ 'Wrong mid value. ',
+ .05
+ );
+
+ $this->assertEquals(
+ 0.,
+ $this->chart->xAxis->getCoordinate( mktime( 12, 0, 0, 5, 9, 2006 ) ),
+ 'Wrong maximum value. ',
+ .05
+ );
+ }
+}
+
+?>
diff --git a/tests/suite.php b/tests/suite.php
index ea08751..71c4aca 100644
--- a/tests/suite.php
+++ b/tests/suite.php
@@ -21,6 +21,7 @@ require_once 'legend_test.php';
require_once 'text_test.php';
require_once 'numeric_axis_test.php';
require_once 'labeled_axis_test.php';
+require_once 'date_axis_test.php';
require_once 'renderer_2d_test.php';
require_once 'renderer_3d_test.php';
require_once 'axis_exact_renderer_test.php';
@@ -51,6 +52,7 @@ class ezcGraphSuite extends ezcTestSuite
$this->addTest( ezcGraphLegendTest::suite() );
$this->addTest( ezcGraphNumericAxisTest::suite() );
$this->addTest( ezcGraphLabeledAxisTest::suite() );
+ $this->addTest( ezcGraphDateAxisTest::suite() );
$this->addTest( ezcGraphRenderer2dTest::suite() );
$this->addTest( ezcGraphRenderer3dTest::suite() );
$this->addTest( ezcGraphAxisExactRendererTest::suite() );
OpenPOWER on IntegriCloud