Compare commits

...

3 Commits

Author SHA1 Message Date
Dominique FOURNIER
61f44abb51 Add var/ into .gitignore 2022-11-25 21:58:20 +01:00
Dominique FOURNIER
4574b3ec1e Add the phpcs.xml configuration file 2022-11-25 21:57:55 +01:00
Dominique FOURNIER
f2444f0247 Split all files mith multiple classes into multiple files 2022-11-25 21:54:30 +01:00
22 changed files with 3300 additions and 0 deletions

1
.gitignore vendored
View File

@@ -5,3 +5,4 @@
/test
tags
.php-cs-fixer.cache
var/*

14
phpcs.xml Normal file
View File

@@ -0,0 +1,14 @@
<?xml version="1.0" encoding="UTF-8"?>
<ruleset name="DomFramework" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="vendor/squizlabs/php_codesniffer/phpcs.xsd">
<config name="installed_paths"
value="vendor/object-calisthenics/phpcs-calisthenics-rules/src/,vendor/wp-coding-standards /wpcs/,vendor/escapestudios/symfony2-coding-standard/Symfony/,vendor/slevomat/coding-standard/"/>
<config name="ignore_warnings_on_exit" value="1"/>
<arg name="basepath" value="."/>
<arg name="cache" value="var/.phpcs-cache"/>
<arg name="colors"/>
<arg name="extensions" value="php"/>
<file>src/</file>
<!--<file>Tests/</file>-->
<rule ref="PSR12"/>
</ruleset>

492
src/GraphAxisGeneral.php Normal file
View File

@@ -0,0 +1,492 @@
<?php
/** DomFramework
* @package domframework
* @author Dominique Fournier <dominique@fournier38.fr>
* @license BSD
*/
namespace Domframework;
/** The general axis management */
class GraphAxisGeneral
{
/** The min value of the axis. Do not use it if the axis is composed of labels
*/
protected $min = null;
/** The max value of the axis. Do not use it if the axis is composed of labels
*/
protected $max = null;
/** The label max to display
*/
protected $labelMax;
/** The label min to display
*/
protected $labelMin;
/** The data displayed as values on the axis
*/
protected $data;
/** Set if the axis is only numerical (true) or is composed of labels (false)
*/
protected $numerical;
/** The minimum bottom position in pixels. Used on vertical axis
*/
protected $bottom;
/** The maximum top position in pixels. Used on vertical axis
*/
protected $top;
/** The minimum left position in pixels. Used on horizontal axis
*/
protected $left;
/** The maximum right position in pixels. Used on horizontal axis
*/
protected $right;
/** The fontfile to write the labels
*/
protected $fontfile;
/** The fontsize to write the labels
*/
protected $fontsize = 8;
/** Axis color
*/
protected $axisColor;
/** Grid color on the axis
* Can be set to null or "transparent" to not display the grid
*/
protected $gridColor;
/** Set the min value of the axis if the parameter is provided.
* Get the min value of the axis if the parameter is not provided
* @param integer|null $min The min value of the axis
*/
public function min($min = null)
{
if ($min === null) {
return $this->min;
}
if (! is_numeric($min)) {
throw new \Exception(dgettext(
"domframework",
"Invalid min provided to graph Axis"
) . " " . get_class($this), 406);
}
$this->min = $min;
return $this;
}
/** Set the max value of the axis if the parameter is provided.
* Get the max value of the axis if the parameter is not provided
* @param integer|null $max The max value of the axis
*/
public function max($max = null)
{
if ($max === null) {
return $this->max;
}
if (! is_numeric($max)) {
throw new \Exception(dgettext(
"domframework",
"Invalid max provided to graph Axis"
) . " " . get_class($this), 406);
}
$this->max = $max;
return $this;
}
/** Set the data of the axis if the parameter is provided.
* Get the data of the axis if the parameter is not provided
* @param array|null $data The data of the axis
*/
public function data($data = null)
{
if ($data === null) {
return $this->data;
}
if (! is_array($data)) {
throw new \Exception(dgettext(
"domframework",
"Invalid data provided to graph Axis"
) . " " . get_class($this), 406);
}
$this->data = $data;
if ($this->numerical === null) {
// Look if the provided data are only numerical. Then define the numerical
// property
foreach ($data as $d) {
if (! is_numeric($d)) {
$this->numerical = false;
break;
}
}
if ($this->numerical === null) {
$this->numerical = true;
}
}
return $this;
}
/** Set if the axis is numerical or composed of labels if the parameter is
* provided.
* Get if the axis is numerical if the parameter is not provided
* @param boolean|null $numerical the axis is numerical
*/
public function numerical($numerical = null)
{
if ($numerical === null) {
return $this->numerical;
}
if (! is_bool($numerical)) {
throw new \Exception(dgettext(
"domframework",
"Invalid numerical parameter provided to graph Axis"
) . " " .
get_class($this), 406);
}
$this->numerical = $numerical;
return $this;
}
/** Set the bottom position of the axis if the parameter is provided.
* Get the bottom position of the axis if the parameter is not provided
* @param integer|null $bottom The bottom position of the axis
*/
public function bottom($bottom = null)
{
if ($bottom === null) {
return $this->bottom;
}
if (! is_integer($bottom) || $bottom < 0 || $bottom > 5000) {
throw new \Exception(dgettext(
"domframework",
"Invalid bottom provided to graph Axis"
) . " " . get_class($this), 406);
}
$this->bottom = $bottom;
return $this;
}
/** Set the top position of the axis if the parameter is provided.
* Get the top position of the axis if the parameter is not provided
* @param integer|null $top The top position of the axis
*/
public function top($top = null)
{
if ($top === null) {
return $this->top;
}
if (! is_integer($top) || $top < 0 || $top > 5000) {
throw new \Exception(dgettext(
"domframework",
"Invalid top provided to graph Axis"
) . " " . get_class($this), 406);
}
$this->top = $top;
return $this;
}
/** Set the left position of the axis if the parameter is provided.
* Get the left position of the axis if the parameter is not provided
* @param integer|null $left The left position of the axis
*/
public function left($left = null)
{
if ($left === null) {
return $this->left;
}
if (! is_integer($left) || $left < 0 || $left > 5000) {
throw new \Exception(dgettext(
"domframework",
"Invalid left provided to graph Axis"
) . " " . get_class($this), 406);
}
$this->left = $left;
return $this;
}
/** Set the right position of the axis if the parameter is provided.
* Get the right position of the axis if the parameter is not provided
* @param integer|null $right The right position of the axis
*/
public function right($right = null)
{
if ($right === null) {
return $this->right;
}
if (! is_integer($right) || $right < 0 || $right > 5000) {
throw new \Exception(dgettext(
"domframework",
"Invalid right provided to graph Axis"
) . " " . get_class($this), 406);
}
$this->right = $right;
return $this;
}
/** Set the fontfile of the labels if the parameter is provided.
* Get the fontfile of the labels if the parameter is not provided
* @param string|null $fontfile The fontfile of the title
*/
public function fontfile($fontfile = null)
{
if ($fontfile === null) {
return $this->fontfile;
}
if (
! is_string($fontfile) || strlen($fontfile) < 0 ||
! file_exists($fontfile) || ! is_readable($fontfile)
) {
throw new \Exception(dgettext(
"domframework",
"Invalid fontfile provided to graph title"
), 406);
}
$this->fontfile = $fontfile;
return $this;
}
/** Set the font size of the labels if the parameter is provided.
* Get the font size of the labels if the parameter is not provided
* @param integer|null $fontsize The font size of the title
*/
public function fontsize($fontsize = null)
{
if ($fontsize === null) {
return $this->fontsize;
}
if (! is_integer($fontsize) || $fontsize < 2 || $fontsize > 100) {
throw new \Exception(dgettext(
"domframework",
"Invalid fontsize provided to graph title"
), 406);
}
$this->fontsize = $fontsize;
return $this;
}
/** Set the axis color if the parameter is provided.
* Get the axis color if the parameter is not provided
* @param string|null $axisColor The axis color
*/
public function axisColor($axisColor = null)
{
if ($axisColor === null) {
return $this->axisColor;
}
if (
! is_string($axisColor) ||
! in_array($axisColor, Color::colorList())
) {
throw new \Exception(dgettext(
"domframework",
"Invalid axisColor provided to graph axis"
), 406);
}
$this->axisColor = $axisColor;
return $this;
}
/** Set the grid color if the parameter is provided.
* Get the grid color if the parameter is not provided
* @param string|null $gridColor The grid color
*/
public function gridColor($gridColor = null)
{
if ($gridColor === null) {
return $this->gridColor;
}
if (
! is_string($gridColor) ||
! in_array($gridColor, Color::colorList())
) {
throw new \Exception(dgettext(
"domframework",
"Invalid gridColor provided to graph grid"
), 406);
}
$this->gridColor = $gridColor;
return $this;
}
/** Calculate the labels that will be displayed on the axis
* @param integer $nbMaxValues The maximum number of values to return
* @return array The array of labels to display
*/
protected function labels($nbMaxValues)
{
// Activate the debug of this method
$deb = false;
if (! is_int($nbMaxValues)) {
throw new \Exception(
"Invalid parameter nbMaxValues provided to graphAxisGeneral::labels",
500
);
}
if ($deb) {
echo "=========== LABELS\n";
}
if ($this->min > 0) {
$minLabel = $this->min * 0.90;
} else {
$minLabel = $this->min * 1.05;
}
if ($this->max > 0) {
$maxLabel = $this->max * 1.05;
} else {
$maxLabel = $this->max * 0.90;
}
$minBase = intval(log10($minLabel)) - 1;
$maxBase = intval(log10($maxLabel)) - 1;
$base = max($minBase, $maxBase);
if ($deb) {
echo "minBase=$minBase, maxBase=$maxBase ===> base = $base\n";
}
if ($base < 0 && $base > -1) {
$base = $base - 1;
}
// The while loop reduce the base to not explode the number of labels
// If there is too much labels, remove one digit and retry
while (1) {
$this->labelMin = null;
$this->labelMax = null;
$min = round($minLabel, -1 * $base);
$max = round($maxLabel, -1 * $base);
if ($deb) {
echo "min = $min, max = $max\n";
}
$scale = pow(10, $base);
if ($deb) {
echo "BASE=" . ($base) . ", SCALE = $scale\n";
}
if ($scale === 0 || $scale === 0.0) {
die("Scale equal 0 on line " . __LINE__ . "\n");
}
$labels = array();
if ($this->min <= 0 && $this->max >= 0) {
// Return the 0 label and the values arround it
$zeroAlreadyDraw = false;
for (
$i = 0;
\bccomp($i, 1.2 * $max, abs($base) + 1) < 1;
$i += $scale
) {
if ($i === 0) {
$zeroAlreadyDraw = true;
}
if ($deb) {
echo "Values with Zero : add pos val $i\n";
}
$labels[] = $i;
}
for (
$i = 0;
\bccomp($i, 1.4 * $min, abs($base) + 1) >= 0;
$i -= $scale
) {
if ($zeroAlreadyDraw === true && $i === 0) {
continue;
}
if ($deb) {
echo "Values with Zero : add neg val $i\n";
}
$labels[] = $i;
}
} else {
// No 0 Axis : From $this->min to $this->max
for (
$i = $min;
\bccomp($i, $max, abs($base) + 1) < 1;
$i += $scale
) {
if ($deb) {
echo "Values no Zero : add val $i\n";
}
$labels[] = $i;
}
}
if (count($labels) <= $nbMaxValues) {
foreach ($labels as &$label) {
if ($base < 0) {
$label = sprintf("%0." . intval(abs($base)) . "f", $label);
} else {
$label = sprintf("%" . intval($base) . "d", $label);
}
if (
$this->labelMin === null ||
\bccomp($this->labelMin, $label, abs($base) + 1) >= 0
) {
$this->labelMin = $label;
}
if (
$this->labelMax === null ||
\bccomp($this->labelMax, $label, abs($base) + 1) <= 0
) {
$this->labelMax = $label;
}
}
if (\bccomp($this->labelMin, $this->min, abs($base) + 1) > 0) {
// Add a label in the minimum
$this->labelMin = $this->labelMin - $scale;
if ($deb) {
echo "Force Add Min $this->labelMin\n";
}
if ($base < 0) {
$labels[] = sprintf(
"%0." . intval(abs($base)) . "f",
$this->labelMin
);
} else {
$labels[] = sprintf("%" . intval($base) . "d", $this->labelMin);
}
}
if (\bccomp($this->labelMax, $this->max, abs($base) + 1) < 0) {
$this->labelMax = $this->labelMax + $scale;
if ($deb) {
echo "Force Add Max $this->labelMax\n";
}
if ($base < 0) {
$labels[] = sprintf(
"%0." . intval(abs($base)) . "f",
$this->labelMax
);
} else {
$labels[] = sprintf("%" . intval($base) . "d", $this->labelMax);
}
}
if ($this->labelMin > $this->min) {
die("labelMin > min ($this->labelMin > $this->min)\n");
}
if ($this->labelMax < $this->max) {
die("labelMax < max ($this->labelMax < $this->max)\n");
}
if (count($labels) <= $nbMaxValues) {
$labels = array_unique($labels);
if ($deb) {
print_r($labels);
}
return $labels;
}
}
if ($deb) {
echo "LOOP == " . count($labels) . " > $nbMaxValues ==========\n";
}
$base = $base + 0.1;
}
}
}

111
src/GraphAxisHorizontal.php Normal file
View File

@@ -0,0 +1,111 @@
<?php
/** DomFramework
* @package domframework
* @author Dominique Fournier <dominique@fournier38.fr>
* @license BSD
*/
namespace Domframework;
/** The graph Axis Horizontal class */
class GraphAxisHorizontal extends GraphAxisGeneral
{
/** Calculate the position in pixels for a value
* If the value is out of range, return null to not draw the point
* @param string|float|integer $value The value to position
*/
public function position($value)
{
if ($value === null) {
return null;
}
if (! is_numeric($value) && ! is_string($value)) {
throw new \Exception(dgettext(
"domframework",
"Invalid value provided to graph Axis for position"
) . " " .
get_class($this), 406);
}
if ($this->numerical === null) {
throw new \Exception(dgettext(
"domframework",
"No numerical type defined for Axis"
) . " " . get_class($this), 406);
}
if ($this->numerical) {
// Numerical axis, use a standard scale
if ($value < $this->min || $value > $this->max) {
return null;
}
if (($this->max - $this->min) == 0) {
$dividor = 1;
} else {
$dividor = ($this->max - $this->min);
}
$scale = ($value - $this->min) / $dividor;
return intval($this->left + $scale * ($this->right - $this->left));
} else {
// Label axis, count them
if (! is_array($this->data)) {
throw new \Exception(dgettext(
"domframework",
"No data defined for Axis"
) . " " . get_class($this), 406);
}
$pos = array_search($value, $this->data);
if ($pos === false) {
return null;
}
$width = ($this->right - $this->left) / count($this->data);
return intval($this->left + $width * $pos + $width / 2);
}
}
/** Calculate the positionMin, used for labeled axies
* If the value is out of range, return null to not draw the point
* @param string|float|integer $value The value to position
*/
public function positionMin($value)
{
if ($this->numerical) {
return $posCenter;
}
if (! is_array($this->data)) {
throw new \Exception(dgettext(
"domframework",
"No data defined for Axis"
) . " " . get_class($this), 406);
}
$pos = array_search($value, $this->data);
if ($pos === false) {
return null;
}
$width = ($this->right - $this->left) / count($this->data);
return intval($this->left + $width * $pos);
}
/** Calculate the positionMax, used for labeled axies
* If the value is out of range, return null to not draw the point
* @param string|float|integer $value The value to position
*/
public function positionMax($value)
{
$posCenter = $this->position($value);
if ($this->numerical) {
return $posCenter;
}
if (! is_array($this->data)) {
throw new \Exception(dgettext(
"domframework",
"No data defined for Axis"
) . " " . get_class($this), 406);
}
$pos = array_search($value, $this->data);
if ($pos === false) {
return null;
}
$width = ($this->right - $this->left) / count($this->data);
return intval($this->left + $width * $pos + $width);
}
}

207
src/GraphAxisVertical.php Normal file
View File

@@ -0,0 +1,207 @@
<?php
/** DomFramework
* @package domframework
* @author Dominique Fournier <dominique@fournier38.fr>
* @license BSD
*/
namespace Domframework;
/** Manage the vertical axis */
class GraphAxisVertical extends GraphAxisGeneral
{
/** The angle choosed to draw the graph
*/
private $angle;
/** The padding between the label and the axis
*/
protected $padding = 7;
/** The width of the labels + padding (it is the base of the graph) in pixels
*/
protected $width;
/** The number of chars to be displayed in one label
*/
protected $nbcharsLabel = 0;
/** Look for the width of the Y axis
* @param resource $gd The resource to modify
*/
public function getWidth($gd)
{
if ($this->numerical) {
if ($this->max === null) {
throw new \Exception(dgettext(
"domframework",
"The max is not defined for graphAxisVertical"
), 406);
}
// Look at the minimum distance between two labeled values
$bbox = imagettfbbox($this->fontsize, 0, $this->fontfile, "NOT");
$height = abs($bbox[5] - $bbox[1]) + $this->padding;
for ($nbMaxValues = 10; $nbMaxValues > 2; $nbMaxValues--) {
if ($nbMaxValues * $height < abs($this->top - $this->bottom)) {
break;
}
}
$labels = $this->labels($nbMaxValues);
$labelBiggest = "";
$this->nbcharsLabel = 0;
foreach ($labels as $label) {
if (strlen($label) > $this->nbcharsLabel) {
$this->nbcharsLabel = strlen($label);
$labelBiggest = $label;
}
}
$bbox = imagettfbbox(
$this->fontsize,
$this->angle,
$this->fontfile,
$labelBiggest
);
$width = abs($bbox[4] - $bbox[0]);
$this->width = $width + 2 * $this->padding;
return $this->width;
} else {
if ($this->data === null) {
return $this->padding;
}
die("TODO : getWidth in labeled line " . __LINE__ . "\n");
}
}
/** Calculate the position in pixels for a value
* If the value is out of range, return null to not draw the point
* @param string|float|integer $value The value to position
*/
public function position($value)
{
if ($value === null) {
return null;
}
if (! is_numeric($value) && ! is_string($value)) {
throw new \Exception(dgettext(
"domframework",
"Invalid value provided to graph Axis for position"
) . " " .
get_class($this), 406);
}
if ($this->numerical === null) {
throw new \Exception(dgettext(
"domframework",
"No numerical type defined for Axis"
) . " " . get_class($this), 406);
}
if ($this->numerical) {
// Numerical axis, use a standard scale
if ($value > $this->labelMax || $value < $this->labelMin) {
return null;
}
$scale = ($value - $this->labelMin) / ($this->labelMax - $this->labelMin);
$pos = intval($this->bottom + $scale * ($this->top - $this->bottom));
return $pos;
} else {
// Label axis, count them
if (! is_array($this->data)) {
throw new \Exception(dgettext(
"domframework",
"No data defined for Axis"
) . " " . get_class($this), 406);
}
$pos = array_search($value, $this->data);
if ($pos === false) {
return null;
}
$width = ($this->top - $this->bottom) / count($this->data);
$pos = intval($this->bottom + $width * $pos + $width / 2);
return $pos;
}
}
/** Calculate the positionMin, used for labeled axies
* If the value is out of range, return null to not draw the point
* @param string|float|integer $value The value to position
*/
public function positionMin($value)
{
if ($this->numerical) {
return $posCenter;
}
if (! is_array($this->data)) {
throw new \Exception(dgettext(
"domframework",
"No data defined for Axis"
) . " " . get_class($this), 406);
}
$pos = array_search($value, $this->data);
if ($pos === false) {
return null;
}
$width = ($this->top - $this->bottom) / count($this->data);
return intval($this->bottom + $width * $pos);
}
/** Calculate the positionMax, used for labeled axies
* If the value is out of range, return null to not draw the point
* @param string|float|integer $value The value to position
*/
public function positionMax($value)
{
$posCenter = $this->position($value);
if ($this->numerical) {
return $posCenter;
}
if (! is_array($this->data)) {
throw new \Exception(dgettext(
"domframework",
"No data defined for Axis"
) . " " . get_class($this), 406);
}
$pos = array_search($value, $this->data);
if ($pos === false) {
return null;
}
$width = ($this->top - $this->bottom) / count($this->data);
return intval($this->bottom + $width * $pos + $width);
}
/** Draw the axis labels and lines
* @param resource $gd The resource to modify
*/
public function draw($gd)
{
$axisColor = Color::allocateFromText($gd, $this->axisColor);
if ($this->numerical) {
// Look at the minimum distance between two labeled values
$bbox = imagettfbbox($this->fontsize, 0, $this->fontfile, "NOT");
$height = abs($bbox[5] - $bbox[1]) + $this->padding;
for ($nbMaxValues = 10; $nbMaxValues > 2; $nbMaxValues--) {
if ($nbMaxValues * $height < abs($this->top - $this->bottom)) {
break;
}
}
$width = $this->getWidth($gd);
$labels = $this->labels($nbMaxValues);
if (count($labels) > $nbMaxValues) {
die("Too much labels to display (" .
count($labels) . " > $nbMaxValues)\n");
}
foreach ($labels as $label) {
$this->drawOne($gd, $width, $label);
$this->drawGrid($gd, $width, $label);
}
$this->drawAxis($gd, $width);
} else {
// Labeled
// If there is no data, there is nothing to draw : return
if ($this->data === null) {
return;
}
die("graphAxisVertical::draw labeled TBD line " . __LINE__ . "\n");
}
}
}

214
src/GraphAxisX.php Normal file
View File

@@ -0,0 +1,214 @@
<?php
/** DomFramework
* @package domframework
* @author Dominique Fournier <dominique@fournier38.fr>
* @license BSD
*/
namespace Domframework;
/** The X axis management */
class GraphAxisX extends GraphAxisHorizontal
{
/** The angle choosed to draw the graph
*/
private $angle;
/** The padding between the label and the axis
*/
private $padding = 7;
/** The heigth of the labels + padding (it is the base of the graph) in pixels
*/
private $height;
/** The number of chars to be displayed in one label
*/
protected $nbcharsLabel = 0;
/** Look for the height of the X axis based on the angle of the text when it
* will be drawn
* @param resource $gd The resource to modify
*/
public function getHeight($gd)
{
// Look for the angle of the value. Start Horizontally (angle=0), then
// try 45°, then finish at 90°. As all the values must in the same angle,
// test all the values. If one is bad, change the angle and retry all the
// values
$width = null;
if ($this->numerical) {
if ($this->max === null) {
throw new \Exception(dgettext(
"domframework",
"The max is not defined for graphAxisHorizontal"
), 406);
}
$powMax = intval(log10($this->max));
$tenPercent = round($this->max / pow(10, $powMax), 1) + 0.1;
$labelMax = $tenPercent * pow(10, $powMax);
$this->nbcharsLabel = strlen($labelMax);
$bbox = imagettfbbox(
$this->fontsize,
$this->angle,
$this->fontfile,
$labelMax
);
$height = abs($bbox[4] - $bbox[0]);
$this->height = $height + 2 * $this->padding;
return $this->height;
} else {
if ($this->data === null) {
return 0;
}
foreach (array(0, 45, 90) as $this->angle) {
$bboxMaxHeight = 0;
foreach ($this->data as $key => $value) {
if ($width === null) {
$width = $this->positionMax($value) - $this->positionMin($value);
}
// Look for the bounding box around the text. The bounding is not
// write on the image and return the coordinates for the text box
$bbox = imagettfbbox(
$this->fontsize,
$this->angle,
$this->fontfile,
$value
);
if (abs($bbox[4] - $bbox[0]) > $width) {
continue 2;
}
$bboxMaxHeight = max($bboxMaxHeight, abs($bbox[5] - $bbox[1]));
}
// All the values are OK : we have found the angle : break the angle
// loop
break;
}
}
$this->height = $bboxMaxHeight + 2 * $this->padding;
return $bboxMaxHeight + 2 * $this->padding;
}
/** Draw the axis
* @param resource $gd The resource to modify
*/
public function draw($gd)
{
$axisColor = Color::allocateFromText($gd, $this->axisColor);
if ($this->numerical) {
if ($this->angle === null) {
$this->getHeight($gd);
}
if ($this->data === null) {
return;
}
foreach ($this->data as $key => $value) {
$position = $this->position($value);
// Draw the labels
$bbox = imagettfbbox(
$this->fontsize,
$this->angle,
$this->fontfile,
$value
);
$width = abs($bbox[4] - $bbox[0]);
$x = $position - $width / 2;
$y = $this->bottom - $this->padding;
// The font color is forced to black
imagettftext(
$gd,
$this->fontsize,
$this->angle,
$x,
$y,
Color::allocateFromText($gd, "black"),
$this->fontfile,
$value
);
// Draw the scale
imageline(
$gd,
$position,
$this->bottom - $this->height + 1,
$position,
$this->bottom - $this->height + 1 + $this->padding,
$axisColor
);
// Draw the grid
$this->drawGrid($gd, $this->bottom - $this->height, $position);
}
// Draw the axis
$y = $this->bottom - $this->height + 1;
imageline($gd, $this->left, $y, $this->right, $y, $axisColor);
} else {
if ($this->angle === null) {
$this->getHeight($gd);
}
if ($this->data === null) {
return;
}
foreach ($this->data as $key => $value) {
$position = $this->position($value);
// Draw the labels
$bbox = imagettfbbox(
$this->fontsize,
$this->angle,
$this->fontfile,
$value
);
$width = abs($bbox[4] - $bbox[0]);
$x = $position - $width / 2;
$y = $this->bottom - $this->padding;
// The font color is forced to black
imagettftext(
$gd,
$this->fontsize,
$this->angle,
$x,
$y,
Color::allocateFromText($gd, "black"),
$this->fontfile,
$value
);
// Draw the separators
$y = $this->bottom - $this->height + 1;
$xmin = $this->positionMin($value);
$xmax = $this->positionMax($value);
imageline($gd, $xmin, $y, $xmin, $y + $this->padding, $axisColor);
imageline($gd, $xmax, $y, $xmax, $y + $this->padding, $axisColor);
// Draw the grid
$this->drawGrid($gd, $this->bottom - $this->height, $position);
}
// Draw the axis
$y = $this->bottom - $this->height + 1;
imageline($gd, $this->left, $y, $this->right, $y, $axisColor);
}
}
/** Draw the grid
* @param resource $gd The resource to modify
* @param integer $width The width of the labels on the axis
* @param integer|float $position The position to draw
*/
protected function drawGrid($gd, $width, $position)
{
if ($this->gridColor === null || $this->gridColor === "transparent") {
return;
}
$gridColor = Color::allocateFromText($gd, $this->gridColor);
if ($position === null) {
return;
}
$y = $this->bottom - $this->height;
imageline($gd, $position, $y, $position, $this->top, $gridColor);
}
}

94
src/GraphAxisY1.php Normal file
View File

@@ -0,0 +1,94 @@
<?php
/** DomFramework
* @package domframework
* @author Dominique Fournier <dominique@fournier38.fr>
* @license BSD
*/
namespace Domframework;
/** The Y1 axis management */
class GraphAxisY1 extends GraphAxisVertical
{
/** Draw one value on the axis
* @param resource $gd The resource to modify
* @param integer $width The width of the labels on the axis
* @param integer|float $val The value to draw
*/
protected function drawOne($gd, $width, $val)
{
$axisColor = Color::allocateFromText($gd, $this->axisColor);
if ($this->numerical) {
// Do not allow the label to be longer than $this->max
if (strlen($val) > $this->nbcharsLabel) {
$itmp = rtrim(substr($val, 0, $this->nbcharsLabel), ".");
} else {
$itmp = $val;
}
// Write the labels align to right
$bbox = imagettfbbox($this->fontsize, 0, $this->fontfile, $itmp);
$labelwidth = abs($bbox[4] - $bbox[0]) + $this->padding;
$labelheight = abs($bbox[5] - $bbox[1]);
$y = $this->position($val);
if ($y === null) {
return;
}
// The color is forced to black
imagettftext(
$gd,
$this->fontsize,
0,
$width - $labelwidth,
$y + $labelheight / 2,
Color::allocateFromText($gd, "black"),
$this->fontfile,
$itmp
);
// Display the separators
imageline(
$gd,
$width - $this->padding,
$y,
$width,
$y,
$axisColor
);
} else {
die("graphAxisY1:: drawOne NOT numerical line " . __LINE__ . "\n");
}
}
/** Draw the axis
* @param resource $gd The resource to modify
* @param integer $width The width of the labels on the axis
*/
protected function drawAxis($gd, $width)
{
$axisColor = Color::allocateFromText($gd, $this->axisColor);
imageline($gd, $width, $this->bottom, $width, $this->top, $axisColor);
}
/** Draw the grid
* @param resource $gd The resource to modify
* @param integer $width The width of the labels on the axis
* @param integer|float $val The value to draw
*/
protected function drawGrid($gd, $width, $val)
{
if ($this->gridColor === null || $this->gridColor === "transparent") {
return;
}
$gridColor = Color::allocateFromText($gd, $this->gridColor);
if ($this->numerical) {
$y = $this->position($val);
if ($y === null) {
return;
}
imageline($gd, $width, $y, $this->right, $y, $gridColor);
} else {
die("graphAxisY1:: drawGrid NOT numerical line " . __LINE__ . "\n");
}
}
}

90
src/GraphAxisY2.php Normal file
View File

@@ -0,0 +1,90 @@
<?php
/** DomFramework
* @package domframework
* @author Dominique Fournier <dominique@fournier38.fr>
* @license BSD
*/
namespace Domframework;
/** The Y2 axis management */
class GraphAxisY2 extends GraphAxisVertical
{
/** Draw one value on the axis
* @param resource $gd The resource to modify
* @param integer $width The width of the labels on the axis
* @param integer|float $val The value to draw
*/
protected function drawOne($gd, $width, $val)
{
$axisColor = Color::allocateFromText($gd, $this->axisColor);
if ($this->numerical) {
// Do not allow the label to be longer than $this->max
if (strlen($val) > $this->nbcharsLabel) {
$itmp = rtrim(substr($val, 0, $this->nbcharsLabel), ".");
} else {
$itmp = $val;
}
// Write the labels align to left
$bbox = imagettfbbox($this->fontsize, 0, $this->fontfile, $itmp);
$labelwidth = abs($bbox[4] - $bbox[0]) + $this->padding;
$labelheight = abs($bbox[5] - $bbox[1]);
$y = $this->position($val);
if ($y === null) {
return;
}
// The color is forced to black
imagettftext(
$gd,
$this->fontsize,
0,
$this->left + $this->padding + 3,
$y + $labelheight / 2,
Color::allocateFromText($gd, "black"),
$this->fontfile,
$itmp
);
// Display the separators
imageline(
$gd,
$this->left,
$y,
$this->left + $this->padding,
$y,
$axisColor
);
} else {
die("graphAxisY2:: drawOne NOT numerical line " . __LINE__ . "\n");
}
}
/** Draw the axis
* @param resource $gd The resource to modify
* @param integer $width The width of the labels on the axis
*/
protected function drawAxis($gd, $width)
{
$axisColor = Color::allocateFromText($gd, $this->axisColor);
imageline(
$gd,
$this->left,
$this->bottom,
$this->left,
$this->top,
$axisColor
);
}
/** Draw the grid
* @param resource $gd The resource to modify
* @param integer $width The width of the labels on the axis
* @param integer|float $val The value to draw
*/
protected function drawGrid($gd, $width, $val)
{
// The grid can't be graphed for Y2 axis : only the Y1 axis is allowed
return;
}
}

305
src/GraphData.php Normal file
View File

@@ -0,0 +1,305 @@
<?php
/** DomFramework
* @package domframework
* @author Dominique Fournier <dominique@fournier38.fr>
* @license BSD
*/
namespace Domframework;
/** Read the data */
class GraphData
{
/** Store the data when the user provided them. Store them in array form
*/
private $data;
/** The titles are on the first line
*/
private $titlesOnFirstLine = null;
/** The titles are on the first column
*/
private $titlesOnFirstColumn = null;
/** The data are stored horizontally
*/
private $horizontalData = null;
/** Get the data from an indexed array
* @param array $array The data array to graph
*/
public function arrayIndexed($array)
{
$this->data = $array;
if (! is_array($this->data)) {
throw new \Exception(
dgettext(
"domframework",
"Invalid Array Parameter provided: not an array"
),
406
);
}
return $this;
}
/** Get the data from an associative array
* The associative array are provided by database results
* @param array $array The data array to graph
*/
public function arrayAssociative($array)
{
if (! is_array($array)) {
throw new \Exception(
dgettext(
"domframework",
"Invalid Array Parameter provided: not an array"
),
406
);
}
$titles = array();
$this->data = array();
foreach ($array as $line => $lineArr) {
foreach ($lineArr as $key => $cell) {
$titles[$key] = "";
$this->data[$line][] = $cell;
}
}
array_unshift($this->data, array_keys($titles));
return $this;
}
/** Get the data from a CSV string
* @param string $csv The CSV string
*/
public function csv($csv)
{
$csv = trim($csv);
$lines = preg_split('/( *\R)+/s', $csv);
$this->data = array_map('str_getcsv', $lines);
if (! is_array($this->data)) {
throw new \Exception(
dgettext(
"domframework",
"Invalid CSV provided: not converted to array"
),
406
);
}
return $this;
}
/** Get the data from a JSON string
* @param string $json The JSON string
*/
public function json($json)
{
$this->data = json_decode($json, true);
if (! is_array($this->data)) {
throw new \Exception(
dgettext(
"domframework",
"Invalid JSON provided: not converted to array"
),
406
);
}
return $this;
}
/** Titles on first line
* Set the value if the parameter is provided, get the value if the parameter
* is not set
* @param boolean|null $titlesOnFirstLine The titles on first line
*/
public function titlesOnFirstLine($titlesOnFirstLine = null)
{
if ($titlesOnFirstLine === null) {
return $this->titlesOnFirstLine;
}
if (! is_bool($titlesOnFirstLine)) {
throw new \Exception(
dgettext(
"domframework",
"Invalid titlesOnFirstLine provided to graph titlesOnFirstLine"
),
406
);
}
$this->titlesOnFirstLine = $titlesOnFirstLine;
return $this;
}
/** Titles on first column
* Set the value if the parameter is provided, get the value if the parameter
* is not set
* @param boolean|null $titlesOnFirstColumn The titles on first column
*/
public function titlesOnFirstColumn($titlesOnFirstColumn = null)
{
if ($titlesOnFirstColumn === null) {
return $this->titlesOnFirstColumn;
}
if (! is_bool($titlesOnFirstColumn)) {
throw new \Exception(
dgettext(
"domframework",
"Invalid titlesOnFirstColumn provided to graph titlesOnFirstColumn"
),
406
);
}
$this->titlesOnFirstColumn = $titlesOnFirstColumn;
return $this;
}
/** The data are stored horizontally in the array
* Set the value if the parameter is provided, get the value if the parameter
* is not set
* @param boolean|null $horizontalData The data are stored horizontally
*/
public function horizontalData($horizontalData = null)
{
if ($horizontalData === null) {
return $this->horizontalData;
}
if (! is_bool($horizontalData)) {
throw new \Exception(
dgettext(
"domframework",
"Invalid horizontalData provided to graph horizontalData"
),
406
);
}
$this->horizontalData = $horizontalData;
return $this;
}
/** Get the series in an array with the associated values
*/
public function getSeries()
{
// 0. If there is no data to graph, nothing to do
if (count($this->data) === 0) {
return array();
}
// 1. If $this->titlesOnFirstLine === null, look if the first line contains
// titles
if ($this->titlesOnFirstLine === null) {
$this->titlesOnFirstLine = true;
if (count($this->data) === 1) {
$this->titlesOnFirstLine = false;
}
if (is_array($this->data[0])) {
foreach ($this->data[0] as $cell) {
if (is_numeric($cell)) {
$this->titlesOnFirstLine = false;
break;
}
}
} else {
$this->titlesOnFirstLine = false;
}
}
// 2. If $this->titlesOnFirstColumn === null, look if the first column
// contains titles
if ($this->titlesOnFirstColumn === null) {
if (count($this->data[0]) === 1) {
$this->titlesOnFirstColumn = false;
} else {
$this->titlesOnFirstColumn = true;
foreach ($this->data as $lineArr) {
if (is_numeric($lineArr[0])) {
$this->titlesOnFirstColumn = false;
break;
}
}
}
}
// 3. If $this->horizontalData === null, look for orientation with the
// titles states
if ($this->horizontalData === null) {
if (
$this->titlesOnFirstColumn === true ||
! array_key_exists(1, $this->data)
) {
$this->horizontalData = true;
} else {
$this->horizontalData = false;
}
}
// 4. Create the series
$colTitles = array();
$lineTitles = array();
$series = array();
foreach ($this->data as $linePos => $lineArr) {
if (! is_array($lineArr)) {
$lineArr = array($lineArr);
}
if ($linePos === 0) {
if ($this->titlesOnFirstLine) {
$colTitles = $lineArr;
if ($this->horizontalData === false) {
// First line with titles and vertical data: get the series names
$series = array_flip($lineArr);
foreach ($series as &$value) {
$value = array();
}
if ($this->titlesOnFirstColumn) {
array_shift($series);
}
}
continue;
} else {
foreach ($lineArr as $i => $value) {
$colTitles[$i] = $i;
}
}
} elseif (count($lineArr) !== count($colTitles)) {
throw new \Exception(sprintf(
dgettext(
"domframework",
"Invalid data provided: line %d doesn't have the same number " .
"of elements as the first line (%d != %d elements)"
),
$linePos + 1,
count($lineArr),
count($colTitles)
), 406);
}
foreach ($lineArr as $colPos => $cell) {
$cell = trim($cell);
if ($colPos === 0) {
if ($this->titlesOnFirstColumn) {
$lineTitles[$linePos] = $cell;
if ($this->horizontalData === true) {
$series[$cell] = array();
}
continue;
} else {
$lineTitles[$linePos] = $linePos;
}
}
if (! is_numeric($cell)) {
$cell = null;
} else {
$cell = $cell + 0.0;
}
if ($this->horizontalData === false) {
$series[$colTitles[$colPos]][$lineTitles[$linePos]] = $cell;
} else {
$series[$lineTitles[$linePos]][$colTitles[$colPos]] = $cell;
}
}
}
return $series;
}
}

271
src/GraphLegend.php Normal file
View File

@@ -0,0 +1,271 @@
<?php
/** DomFramework
* @package domframework
* @author Dominique Fournier <dominique@fournier38.fr>
* @license BSD
*/
namespace Domframework;
/** The graphLegend object */
class GraphLegend
{
/** Show the legend (no legend by default)
*/
private $show = false;
/** The TTF fontfile to use
*/
private $fontfile = null;
/** The font size to use
*/
private $fontsize = 10;
/** The legend color for the font
*/
private $color = "black";
/** The legend background-color
*/
private $bgcolor = "white";
/** The legend border color
*/
private $borderColor = "black";
/** The padding arround the title (in px)
*/
private $padding = 10;
/** Set the legend display status if the parameter is provided.
* Get the legend display status if the parameter is not provided
* @param boolean|null $show The legend display status
*/
public function show($show = null)
{
if ($show === null) {
return $this->show;
}
if (! is_bool($show)) {
throw new \Exception(dgettext(
"domframework",
"Invalid show value provided to graph legend"
), 406);
}
$this->show = $show;
return $this;
}
/** Set the fontfile of the legend if the parameter is provided.
* Get the fontfile of the legend if the parameter is not provided
* @param string|null $fontfile The fontfile of the legend
*/
public function fontfile($fontfile = null)
{
if ($fontfile === null) {
return $this->fontfile;
}
if (
! is_string($fontfile) || strlen($fontfile) < 0 ||
! file_exists($fontfile) || ! is_readable($fontfile)
) {
throw new \Exception(dgettext(
"domframework",
"Invalid fontfile provided to graph legend"
), 406);
}
$this->fontfile = $fontfile;
return $this;
}
/** Set the font size of the legend if the parameter is provided.
* Get the font size of the legend if the parameter is not provided
* @param integer|null $fontsize The font size of the legend
*/
public function fontsize($fontsize = null)
{
if ($fontsize === null) {
return $this->fontsize;
}
if (! is_integer($fontsize) || $fontsize < 2 || $fontsize > 100) {
throw new \Exception(dgettext(
"domframework",
"Invalid fontsize provided to graph legend"
), 406);
}
$this->fontsize = $fontsize;
return $this;
}
/** Set the color of the legend if the parameter is provided.
* Get the color of the legend if the parameter is not provided
* @param string|null $color The color of the legend
*/
public function color($color = null)
{
if ($color === null) {
return $this->color;
}
if (
! is_string($color) ||
! in_array($color, Color::colorList())
) {
throw new \Exception(dgettext(
"domframework",
"Invalid color provided to graph legend"
), 406);
}
$this->color = $color;
return $this;
}
/** Set the background-color of the legend if the parameter is provided.
* Get the background-color of the legend if the parameter is not provided
* @param string|null $bgcolor The background-color of the legend
*/
public function bgcolor($bgcolor = null)
{
if ($bgcolor === null) {
return $this->bgcolor;
}
if (
! is_string($bgcolor) ||
! in_array($bgcolor, Color::colorList())
) {
throw new \Exception(dgettext(
"domframework",
"Invalid bgcolor provided to graph legend"
), 406);
}
$this->bgcolor = $bgcolor;
return $this;
}
/** Set the border color of the legend if the parameter is provided.
* Get the border color of the legend if the parameter is not provided
* @param string|null $borderColor The border color of the legend
*/
public function borderColor($borderColor = null)
{
if ($borderColor === null) {
return $this->borderColor;
}
if (
! is_string($borderColor) ||
! in_array($borderColor, Color::colorList())
) {
throw new \Exception(dgettext(
"domframework",
"Invalid borderColor provided to graph legend"
), 406);
}
$this->borderColor = $borderColor;
return $this;
}
/** Set the padding of the legend if the parameter is provided.
* Get the padding of the legend if the parameter is not provided
* @param integer|null $padding The padding of the legend
*/
public function padding($padding = null)
{
if ($padding === null) {
return $this->padding;
}
if (! is_integer($padding) || $padding < 0 || $padding > 200) {
throw new \Exception(dgettext(
"domframework",
"Invalid padding provided to graph legend"
), 406);
}
$this->padding = $padding;
return $this;
}
/** Draw the legend in the $gd resource provided
* @param resource $gd The resource to modify
* @param array $free The free space coordinates on the graphic
* @param object $series The series to graph
* @return array the new free coordinates array
*/
public function draw($gd, $free, $series)
{
if ($this->show === false) {
return $free;
}
// Look for maxmimum width of the labels
$maxwidth = 0;
$height = 0;
foreach ($series->getList() as $number => $serie) {
$bbox = imagettfbbox($this->fontsize, 0, $this->fontfile, $serie);
$width = abs($bbox[4] - $bbox[0]);
// TODO : If the serie name is too long, split it !
// 20px for the sample + the space before the label
if ((20 + $maxwidth) > (($free[2] - $free[0]) / 2)) {
throw new \Exception(
dgettext(
"domframework",
"The serie name in legend must not takes more than half of the graph"
),
500
);
}
if ($number > 0) {
$height += $this->padding;
}
$height += abs($bbox[5] - $bbox[1]);
$maxwidth = max($maxwidth, $width);
}
$x1 = $free[2] - $maxwidth - 20 - $this->padding * 2;
$x2 = $free[2] - $this->padding;
$y1 = $free[1] + $this->padding;
$y2 = $y1 + $height + $this->padding;
// Size of the border : 1px
$border = 1;
// Draw the background rectangle
imagefilledrectangle(
$gd,
$x1,
$y1,
$x2,
$y2,
Color::allocateFromText($gd, $this->borderColor)
);
imagefilledrectangle(
$gd,
$x1 + $border,
$y1 + $border,
$x2 - $border,
$y2 - $border,
Color::allocateFromText($gd, $this->bgcolor)
);
// Display the serie names
$y = $y1;
foreach ($series->getList() as $number => $serie) {
// Write the label
$bbox = imagettfbbox($this->fontsize, 0, $this->fontfile, $serie);
$height = abs($bbox[5] - $bbox[1]);
$y += $height;
imagettftext(
$gd,
$this->fontsize,
0,
$x1 + 30,
intval($y + $height / 2),
Color::allocateFromText($gd, $this->color),
$this->fontfile,
$serie
);
// Draw the sample
$series->serie($serie)->style()->sample($gd, $x1 + 15, $y);
$y += $this->padding;
}
$free = array($free[0], $free[1], $x1 - 5, $free[3]);
return $free;
}
}

40
src/GraphPalette.php Normal file
View File

@@ -0,0 +1,40 @@
<?php
/** DomFramework
* @package domframework
* @author Dominique Fournier <dominique@fournier38.fr>
* @license BSD
*/
namespace Domframework;
/** The graphPalette class */
class GraphPalette
{
/** Get the complete palette
* @param string $name The palette name to get
*/
public static function getPalette($name)
{
$palette = array(
"basic" => array(
array("bgcolor" => "indianred", "color" => "firebrick"),
array("bgcolor" => "lightblue", "color" => "blue"),
array("bgcolor" => "peru", "color" => "maroon"),
array("bgcolor" => "mediumaquamarine", "color" => "teal"),
array("bgcolor" => "orange", "color" => "goldenrod"),
array("bgcolor" => "limegreen", "color" => "green"),
array("bgcolor" => "darkgrey", "color" => "grey"),
array("bgcolor" => "darkyellow1", "color" => "darkyellow2"),
array("bgcolor" => "grey", "color" => "black"),
),
);
if (! is_string($name) || ! array_key_exists($name, $palette)) {
throw new \Exception(dgettext(
"domframework",
"Unknown palette name provided"
), 406);
}
return $palette[$name];
}
}

307
src/GraphSerie.php Normal file
View File

@@ -0,0 +1,307 @@
<?php
/** DomFramework
* @package domframework
* @author Dominique Fournier <dominique@fournier38.fr>
* @license BSD
*/
namespace Domframework;
/** The serie object */
class GraphSerie
{
/** The name of the serie
*/
private $name;
/** The data values for the serie
*/
private $data;
/** The numericalKey is true if all the keys are numeric
*/
private $numericalKey = null;
/** The minimum key of the serie
*/
private $minKey = null;
/** The maximum key of the serie
*/
private $maxKey = null;
/** The numericalValue is true if all the values are numeric
*/
private $numericalValue = null;
/** The minimum value of the serie
*/
private $minValue = null;
/** The maximum value of the serie
*/
private $maxValue = null;
/** The style object for the serie
*/
private $style;
/** If set, hide this serie and do not display it
*/
private $hide;
/** The axis used to draw the serie.
* If false for main Y axis
* If true for secondary Y axis
*/
private $axisYsecondary = false;
/** When creating the serie, save the name
* @param string $name The name of the serie
*/
public function __construct($name)
{
if (! is_string($name)) {
throw new \Exception(
dgettext(
"domframework",
"Can't create a serie if the name is not a string"
),
406
);
}
$this->name = $name;
}
/** Set the data for the serie
If the parameter is not provided, return the actual $data value
* @param array|null $data The data to store in the serie
*/
public function data($data = null)
{
if ($data === null) {
return $this->data;
}
if (! is_array($data)) {
throw new \Exception(
dgettext(
"domframework",
"Can't create a serie data if the value is not an array"
),
406
);
}
$this->data = $data;
$this->minmax();
return $this;
}
/** Get the minimum and maximum values and keys
*/
private function minmax()
{
if ($this->data === null) {
return null;
}
foreach ($this->data as $key => $value) {
if ($this->minValue === null && is_numeric($value)) {
$this->minValue = $value;
}
if ($this->minKey === null && is_numeric($key)) {
$this->minKey = $key;
}
if (is_numeric($value)) {
$this->minValue = min($this->minValue, $value);
$this->maxValue = max($this->maxValue, $value);
}
if (is_numeric($key)) {
$this->minKey = min($this->minKey, $key);
$this->maxKey = max($this->maxKey, $key);
}
if (! is_numeric($key) && $this->numericalKey === null) {
$this->numericalKey = false;
}
if (
! is_numeric($value) && $value !== null &&
$this->numericalValue === null
) {
$this->numericalValue = false;
}
}
if ($this->numericalKey === null) {
$this->numericalKey = true;
}
if ($this->numericalValue === null) {
$this->numericalValue = true;
}
}
/** Set/get the numeric value of the serie
* If the parameter is not provided, return the actual state
* @param boolean|null $numericalValue The state of the numeric value
*/
public function numericalValue($numericalValue = null)
{
if ($numericalValue === null) {
return $this->numericalValue;
}
if (! is_bool($numericalValue)) {
throw new \Exception(dgettext(
"domframework",
"Invalid numericalValue provided to serie"
), 406);
}
$this->numericalValue = $numericalValue;
return $this;
}
/** The minimum value of the serie
*/
public function minValue()
{
if ($this->minValue === null && $this->data !== null) {
$this->minmax();
}
return $this->minValue;
}
/** The maximum value of the serie
*/
public function maxValue()
{
if ($this->maxValue === null && $this->data !== null) {
$this->minmax();
}
return $this->maxValue;
}
/** Set/get the numeric key of the serie
* If the parameter is not provided, return the actual state
* @param boolean|null $numericalKey The state of the numeric key
*/
public function numericalKey($numericalKey = null)
{
if ($numericalKey === null) {
return $this->numericalKey;
}
if (! is_bool($numericalKey)) {
throw new \Exception(dgettext(
"domframework",
"Invalid numericalKey provided to serie"
), 406);
}
$this->numericalKey = $numericalKey;
return $this;
}
/** The minimum key of the serie
*/
public function minKey()
{
if ($this->minKey === null && $this->data !== null) {
$this->minmax();
}
return $this->minKey;
}
/** The maximum key of the serie
*/
public function maxKey()
{
if ($this->maxKey === null && $this->data !== null) {
$this->minmax();
}
return $this->maxKey;
}
/** The number of elements in the serie
*/
public function count()
{
return count($this->data);
}
/** Set/Get the graph style for the serie
* If the parameter is not provided, return the actual state
* @param string|object|null $style The graph style
*/
public function style($style = null)
{
if ($style === null) {
return $this->style;
}
if (is_object($style)) {
$this->style = clone $style;
return $this->style;
}
if (
! is_string($style) ||
! in_array($style, array("line", "points", "linePoints"))
) {
throw new \Exception(dgettext(
"domframework",
"Invalid style provided to serie"
), 406);
}
$styleClass = "GraphStyle" . $style;
if ($this->style === null) {
$this->style = new $styleClass();
}
return $this->style;
}
/** Set/Get the hidden state of the serie
* If the parameter is not provided, return the actual state
* @param boolean|null $hide The hidden state
*/
public function hide($hide = null)
{
if ($hide === null) {
return $this->hide;
}
if (! is_bool($hide)) {
throw new \Exception(dgettext(
"domframework",
"Invalid hide mode provided to serie"
), 406);
}
$this->hide = $hide;
return $this;
}
/** The serie is based on the secondary Y axis
* Set the value if the parameter is provided, get the value if the parameter
* is not set
* @param boolean|null $axisYsecondary The Serie on secondary Y axis
*/
public function axisYsecondary($axisYsecondary = null)
{
if ($axisYsecondary === null) {
return $this->axisYsecondary;
}
if (! is_bool($axisYsecondary)) {
throw new \Exception(
dgettext(
"domframework",
"Invalid axisYsecondary provided to graph axisYsecondary"
),
406
);
}
$this->axisYsecondary = $axisYsecondary;
return $this;
}
/** Draw the serie with the defined style class
* @param resource $gd The resource to modify
* @param array $free The free space coordinates on the graphic
* @param object $axisX The axis X used on the graph
* @param object $axisY The axis Y used on the graph
*/
public function draw($gd, $free, $axisX, $axisY)
{
if ($this->hide === true) {
return;
}
$this->style->draw($gd, $free, $this->data, $axisX, $axisY);
}
}

73
src/GraphSeries.php Normal file
View File

@@ -0,0 +1,73 @@
<?php
/** DomFramework
* @package domframework
* @author Dominique Fournier <dominique@fournier38.fr>
* @license BSD
*/
namespace Domframework;
/** The series objects */
class GraphSeries
{
/** The series stored */
private $series = array();
/** Return the serie object choosed. If doesn't exists, it is created before
* be returned
* @param string $name The name of the serie to create
*/
public function serie($name)
{
if (is_integer($name)) {
$name = dgettext("domframework", "Serie") . " $name";
}
if (! is_string($name)) {
throw new \Exception(
dgettext(
"domframework",
"Can't get a serie if the name is not a string"
),
406
);
}
if (! array_key_exists($name, $this->series)) {
$this->series[$name] = new GraphSerie($name);
}
return $this->series[$name];
}
/** Get the list of the defined series
*/
public function getList()
{
$series = [];
foreach ($this->series as $name => $serie) {
if ($serie->hide() === true) {
continue;
}
$series[] = $name;
}
return $series;
}
/** Remove an existing serie
* @param string $name The name of the serie to remove
*/
public function remove($name)
{
if (! is_string($name)) {
throw new \Exception(
dgettext(
"domframework",
"Can't remove a serie if the name is not a string"
),
406
);
}
if (array_key_exists($name, $this->series)) {
unset($this->series[$name]);
}
}
}

27
src/GraphStyleLine.php Normal file
View File

@@ -0,0 +1,27 @@
<?php
/** DomFramework
* @package domframework
* @author Dominique Fournier <dominique@fournier38.fr>
* @license BSD
*/
namespace Domframework;
/** The graphStyleLine : draw a graph with line */
class GraphStyleLine extends GraphStyleLinePoints
{
/** The point color background. To hide the points, choose "transparent"
*/
protected $pointBgcolor = "transparent";
/** The point color border
*/
protected $pointColor = "transparent";
/** Return the name of the style */
public function name()
{
return "line";
}
}

View File

@@ -0,0 +1,393 @@
<?php
/** DomFramework
* @package domframework
* @author Dominique Fournier <dominique@fournier38.fr>
* @license BSD
*/
namespace Domframework;
/** The graphStyleLine : draw a graph with lines */
class GraphStyleLinePoints
{
/** The line color. To hide the lines, choose "transparent"
*/
protected $lineColor;
/** The point color background. To hide the points, choose "transparent"
*/
protected $pointBgcolor;
/** The point color border
*/
protected $pointColor;
/** The point shape (square, circle, triangle, lozenge)
*/
protected $pointShape;
/** The point width in pixel
*/
protected $pointWidth;
/** The number of the colors/shapes to use
*/
protected $number;
/** The allowed shapes */
protected $allowedShapes = array("square", "circle", "triangle", "lozenge");
/** The palette to use */
protected $palette;
/** Return the name of the style */
public function name()
{
return "lineAndPoints";
}
/** Set the line color if the parameter is provided.
* Get the line color if the parameter is not provided
* @param string|null $lineColor The line color
*/
public function lineColor($lineColor = null)
{
if ($lineColor === null) {
return $this->lineColor;
}
if (
! is_string($lineColor) ||
($lineColor !== "transparent" &&
! in_array($lineColor, Color::colorList()))
) {
throw new \Exception(dgettext(
"domframework",
"Invalid lineColor provided to line style"
), 406);
}
$this->lineColor = $lineColor;
return $this;
}
/** Set the palette to use if the parameter is provided
* Get the palette if the parameter is not provided
* @param string|null $palette The palette to use
*/
public function palette($palette = null)
{
if ($palette === null) {
return $this->palette;
}
if (! is_string($palette)) {
throw new \Exception(dgettext(
"domframework",
"Invalid palette provided to line style"
), 406);
}
$this->palette = $palette;
return $this;
}
/** Set the point background color if the parameter is provided.
* Get the point background color if the parameter is not provided
* @param string|null $pointBgcolor The point background color
*/
public function pointBgcolor($pointBgcolor = null)
{
if ($pointBgcolor === null) {
return $this->pointBgcolor;
}
if (
! is_string($pointBgcolor) ||
($pointBgcolor !== "transparent" &&
! in_array($pointBgcolor, Color::colorList()))
) {
throw new \Exception(dgettext(
"domframework",
"Invalid pointBgcolor provided to line style"
), 406);
}
$this->pointBgcolor = $pointBgcolor;
return $this;
}
/** Set the point border color if the parameter is provided.
* Get the point border color if the parameter is not provided
* @param string|null $pointColor The point border color
*/
public function pointColor($pointColor = null)
{
if ($pointColor === null) {
return $this->pointColor;
}
if (
! is_string($pointColor) ||
($pointColor !== "transparent" &&
! in_array($pointColor, Color::colorList()))
) {
throw new \Exception(dgettext(
"domframework",
"Invalid pointColor provided to line style"
), 406);
}
$this->pointColor = $pointColor;
return $this;
}
/** Set the point shape if the parameter is provided.
* Get the point shape if the parameter is not provided
* @param string|null $pointShape The point shape
*/
public function pointShape($pointShape = null)
{
if ($pointShape === null) {
return $this->pointShape;
}
if (
! is_string($pointShape) ||
! in_array($pointShape, $this->allowedShapes)
) {
throw new \Exception(dgettext(
"domframework",
"Invalid pointShape provided to line style"
), 406);
}
$this->pointShape = $pointShape;
return $this;
}
/** Set the point width if the parameter is provided.
* Get the point width if the parameter is not provided
* @param string|null $pointWidth The point width
*/
public function pointWidth($pointWidth = null)
{
if ($pointWidth === null) {
return $this->pointWidth;
}
if (! is_integer($pointWidth) || $pointWidth < 3 || $pointWidth > 20) {
throw new \Exception(dgettext(
"domframework",
"Invalid pointWidth provided to line style"
), 406);
}
$this->pointWidth = $pointWidth;
return $this;
}
/** Select the colors, shapes by the serie number.
* Do not change any property if the property is already defined
* If the parameter is not provided, return the value
* @param integer|null $number The serie number
*/
public function number($number = null)
{
if ($number === null) {
return $this->number;
}
if (! is_int($number) || $number < 0) {
throw new \Exception(dgettext(
"domframework",
"Invalid number provided to line style number"
), 406);
}
$this->number = $number;
if ($this->pointShape === null) {
$this->pointShape = $this->allowedShapes[
($number % count($this->allowedShapes))];
}
$palette = graphPalette::getPalette($this->palette);
if ($this->pointBgcolor === null) {
$this->pointBgcolor = $palette[($number % count($palette))]["bgcolor"];
}
if ($this->pointColor === null) {
$this->pointColor = $palette[($number % count($palette))]["color"];
}
if ($this->lineColor === null) {
$this->lineColor = $palette[($number % count($palette))]["color"];
}
}
/** Draw in the $gd resource, in the $free array, the data with the parameter
* of the style
* @param resource $gd The resource to modify
* @param array $free The free space coordinates on the graphic
* @param array $data The data to graph
* @param object $axisX The X axis used to graph
* @param object $axisY The Y axis used to graph
*/
public function draw($gd, $free, $data, $axisX, $axisY)
{
if ($this->lineColor !== "transparent") {
$lineColor = Color::allocateFromText($gd, $this->lineColor);
}
$lastX = null;
$lastY = null;
foreach ($data as $key => $value) {
$posX = $axisX->position($key);
$posY = $axisY->position($value);
if ($posX === null || $posY === null) {
// NULL position : skip the point
$lastX = null;
$lastY = null;
continue;
}
// Draw the lines between points (except if the last point was null, or
// if the line color is "transparent")
if (
$lastX !== null && $lastY !== null &&
$this->lineColor !== "transparent"
) {
imageline($gd, $lastX, $lastY, $posX, $posY, $lineColor);
// Redraw the old point which was scratch by the new created line
$this->drawPoint($gd, $lastX, $lastY);
}
if ($lastX === null) {
$lastX = $posX;
}
if ($lastY === null) {
$lastY = $posY;
}
// Draw the point. Will overwrite the lines
if ($this->pointWidth === null) {
$this->pointWidth = 6;
}
$this->drawPoint($gd, $posX, $posY);
$lastX = $posX;
$lastY = $posY;
}
}
/** Draw a point defined in the property of the class
* @param resource $gd The resource to modify
* @param integer $posX The X position to draw the point
* @param integer $posY The Y position to draw the point
*/
private function drawPoint($gd, $posX, $posY)
{
if ($this->pointColor !== "transparent") {
$pointColor = Color::allocateFromText($gd, $this->pointColor);
}
if ($this->pointBgcolor !== "transparent") {
$pointBgcolor = Color::allocateFromText($gd, $this->pointBgcolor);
}
$half = intval($this->pointWidth / 2);
switch ($this->pointShape) {
case "circle":
if ($this->pointBgcolor !== "transparent") {
imagefilledellipse(
$gd,
$posX,
$posY,
$this->pointWidth,
$this->pointWidth,
$pointBgcolor + 2
);
}
if ($this->pointColor !== "transparent") {
imageellipse(
$gd,
$posX,
$posY,
$this->pointWidth + 2,
$this->pointWidth + 2,
$pointColor
);
}
break;
case "lozenge":
if ($this->pointBgcolor !== "transparent") {
imagefilledpolygon(
$gd,
array($posX - $half - 2, $posY,
$posX, $posY - $half - 2,
$posX + $half + 2, $posY,
$posX, $posY + $half + 2),
4,
$pointBgcolor
);
}
if ($this->pointColor !== "transparent") {
imagepolygon(
$gd,
array($posX - $half - 2, $posY,
$posX, $posY - $half - 2,
$posX + $half + 2, $posY,
$posX, $posY + $half + 2),
4,
$pointColor
);
}
break;
case "square":
if ($this->pointBgcolor !== "transparent") {
imagefilledrectangle(
$gd,
$posX - $half - 1,
$posY - $half - 1,
$posX + $half + 1,
$posY + $half + 1,
$pointBgcolor
);
}
if ($this->pointColor !== "transparent") {
imagerectangle(
$gd,
$posX - $half - 1,
$posY - $half - 1,
$posX + $half + 1,
$posY + $half + 1,
$pointColor
);
}
break;
case "triangle":
if ($this->pointBgcolor !== "transparent") {
imagefilledpolygon(
$gd,
array($posX - $half - 2, $posY + $half + 2,
$posX, $posY - $half - 2,
$posX + $half + 2, $posY + $half + 2),
3,
$pointBgcolor
);
}
if ($this->pointColor !== "transparent") {
imagepolygon(
$gd,
array($posX - $half - 2, $posY + $half + 2,
$posX, $posY - $half - 2,
$posX + $half + 2, $posY + $half + 2),
3,
$pointColor
);
}
break;
default:
throw new \Exception(dgettext(
"domframework",
"Unknown pointShape for serie"
), 406);
}
}
/** Draw a sample of the style for the legend
* @param resource $gd The resource to modify
* @param integer $x The central position of the sample in x
* @param integer $y The central position of the sample in y
*/
public function sample($gd, $x, $y)
{
if ($this->lineColor !== "transparent") {
$lineColor = Color::allocateFromText($gd, $this->lineColor);
imageline($gd, $x - 10, $y, $x + 10, $y, $lineColor);
}
if ($this->pointWidth === null) {
$this->pointWidth = 6;
}
$this->drawPoint($gd, $x, $y);
}
}

23
src/GraphStylePoints.php Normal file
View File

@@ -0,0 +1,23 @@
<?php
/** DomFramework
* @package domframework
* @author Dominique Fournier <dominique@fournier38.fr>
* @license BSD
*/
namespace Domframework;
/** The graphStylePoints : draw a graph with points */
class GraphStylePoints extends GraphStyleLinePoints
{
/** The line color : transparent
*/
protected $lineColor = "transparent";
/** Return the name of the style */
public function name()
{
return "points";
}
}

167
src/GraphTitle.php Normal file
View File

@@ -0,0 +1,167 @@
<?php
/** DomFramework
* @package domframework
* @author Dominique Fournier <dominique@fournier38.fr>
* @license BSD
*/
namespace Domframework;
/** The graphTitle object */
class GraphTitle
{
/** The title text
*/
private $text = null;
/** The TTF fontfile to use
*/
private $fontfile = null;
/** The font size to use
*/
private $fontsize = 14;
/** The title color
*/
private $color = "black";
/** The padding arround the title (in px)
*/
private $padding = 10;
/** Set the text of the title if the parameter is provided.
* Get the text of the title if the parameter is not provided
* @param string|null $text The text of the title
*/
public function text($text = null)
{
if ($text === null) {
return $this->text;
}
if (! is_string($text) || strlen($text) < 0 || strlen($text) > 50) {
throw new \Exception(dgettext(
"domframework",
"Invalid text provided to graph title"
), 406);
}
$this->text = $text;
return $this;
}
/** Set the fontfile of the title if the parameter is provided.
* Get the fontfile of the title if the parameter is not provided
* @param string|null $fontfile The fontfile of the title
*/
public function fontfile($fontfile = null)
{
if ($fontfile === null) {
return $this->fontfile;
}
if (
! is_string($fontfile) || strlen($fontfile) < 0 ||
! file_exists($fontfile) || ! is_readable($fontfile)
) {
throw new \Exception(dgettext(
"domframework",
"Invalid fontfile provided to graph title"
), 406);
}
$this->fontfile = $fontfile;
return $this;
}
/** Set the font size of the title if the parameter is provided.
* Get the font size of the title if the parameter is not provided
* @param integer|null $fontsize The font size of the title
*/
public function fontsize($fontsize = null)
{
if ($fontsize === null) {
return $this->fontsize;
}
if (! is_integer($fontsize) || $fontsize < 2 || $fontsize > 100) {
throw new \Exception(dgettext(
"domframework",
"Invalid fontsize provided to graph title"
), 406);
}
$this->fontsize = $fontsize;
return $this;
}
/** Set the color of the title if the parameter is provided.
* Get the color of the title if the parameter is not provided
* @param string|null $color The color of the title
*/
public function color($color = null)
{
if ($color === null) {
return $this->color;
}
if (
! is_string($color) ||
! in_array($color, Color::colorList())
) {
throw new \Exception(dgettext(
"domframework",
"Invalid color provided to graph title"
), 406);
}
$this->color = $color;
return $this;
}
/** Set the padding of the title if the parameter is provided.
* Get the padding of the title if the parameter is not provided
* @param integer|null $padding The padding of the title
*/
public function padding($padding = null)
{
if ($padding === null) {
return $this->padding;
}
if (! is_integer($padding) || $padding < 0 || $padding > 200) {
throw new \Exception(dgettext(
"domframework",
"Invalid padding provided to graph title"
), 406);
}
$this->padding = $padding;
return $this;
}
/** Draw the title in the $gd resource provided
* @param resource $gd The resource to modify
* @param array $free The free space coordinates on the graphic
* @return array the new free coordinates array
*/
public function draw($gd, $free)
{
if ($this->text === null) {
return $free;
}
// Look for the bounding box around the text. The bounding is not write on
// the image and return the coordinates for the text box
$bbox = imagettfbbox($this->fontsize, 0, $this->fontfile, $this->text);
// Calculate the position of the text to be centered on the graph
// The padding is only on vertical : the x is centered
$x = floor(($free[2] - $free[0] - abs($bbox[4] - $bbox[0])) / 2);
$y = ceil($free[1] + abs($bbox[5] - $bbox[1])) + $this->padding;
$x += $free[0];
$y += $free[1];
imagettftext(
$gd,
$this->fontsize,
0,
$x,
$y,
Color::allocateFromText($gd, $this->color),
$this->fontfile,
$this->text
);
return array(intval($free[0]), intval($free[1] + $y + $this->padding),
intval($free[2]), intval($free[3]));
}
}

64
src/HttpConnection.php Normal file
View File

@@ -0,0 +1,64 @@
<?php
/** DomFramework
* @package domframework
* @author Dominique Fournier <dominique@fournier38.fr>
* @license BSD
*/
namespace Domframework;
/**
* Manage the HTTP Connections.
* Used by HttpServer
*/
class HttpConnection
{
private $tcpserver;
private $clientAddress;
private $clientPort;
private $localAddress;
private $localPort;
private $logger;
public function __construct($tcpserver)
{
$this->tcpserver = $tcpserver;
list($clientAddress, $clientPort, $localAddress, $localPort) =
$tcpserver->getInfo();
// If the address is in IPv4 in IPv6 (syntax : "::ffff:127.0.0.1"),
// update it to IPv4 only
if (substr($clientAddress, 0, 7) === "::ffff:") {
$clientAddress = substr($clientAddress, 7);
}
$this->clientAddress = $clientAddress;
$this->clientPort = $clientPort;
$this->localAddress = $localAddress;
$this->localPort = $localPort;
echo "OK : $localAddress:$localPort";
}
public function __destruct()
{
}
public function getClientAddress()
{
return $this->clientAddress;
}
public function getClientPort()
{
return $this->clientPort;
}
public function getLocalAddress()
{
return $this->localAddress;
}
public function getLocalPort()
{
return $this->localPort;
}
}

144
src/Httpserver.php Normal file
View File

@@ -0,0 +1,144 @@
<?php
/** DomFramework
* @package domframework
* @author Dominique Fournier <dominique@fournier38.fr>
* @license BSD
*/
namespace Domframework;
/**
* Create a HTTP server easily
* The server can listen on multiple IP addresses and multiple ports.
*
* Need HttpConnection
*/
class Httpserver
{
private $tcpserver;
private $listeners = array();
private $runningUser;
private $runningGroup;
private $logger;
private $maxConnection = 500;
private $timeout = 30;
/** Add a new listener. Must all be set before entering in loop
* @param string $ip The Listening IP Address
* @param integer $port the Listening port
* @param callable $callable The method called when a new request enter
*/
public function addListener($ip, $port, $callable)
{
$ipaddresses = new Ipaddresses();
if (! $ipaddresses->validIPAddress($ip)) {
throw new \Exception(
"Httpserver : invalid IP address provided to listen",
500
);
}
if (
! is_numeric($port) || ! ctype_digit($port) || $port < 0 ||
$port > 65535
) {
throw new \Exception(
"Httpserver : invalid port provided to listen " .
"(must be between 0 and 65535)",
500
);
}
if (! is_callable($callable)) {
throw new \Exception(
"Httpserver : invalid callable function provided to listen " .
"(must be callable)",
500
);
}
foreach ($this->listeners as $listener) {
if ($listener["ip"] === $ip && $listener["port"] === $port) {
throw new \Exception("Httpserver : can not add multiple listeners on " .
"the same couple IP/Port", 500);
}
}
$this->listeners[] = ["ip" => $ip,
"port" => $port,
"callable" => $callable];
return $this;
}
private function setLogger($logger)
{
$this->logger = $logger;
return $this;
}
public function getMaxConnection()
{
return $this->maxConnection;
}
public function setMaxConnection($maxConnection)
{
$this->maxConnection = $maxConnection;
return $this;
}
public function getTimeout()
{
return $this->timeout;
}
public function setTimeout($timeout)
{
$this->timeout = $timeout;
return $this;
}
public function getRunningUser()
{
return $this->runningUser;
}
public function setRunningUser($user)
{
$this->runningUser = $user;
return $this;
}
public function getRunningGroup()
{
return $this->runningGroup;
}
public function setRunningGroup($group)
{
$this->runningGroup = $group;
return $this;
}
final public function loop()
{
$tcpserver = new Tcpserver();
if (empty($this->listeners)) {
throw new \Exception("Httpserver : No listener defined");
}
foreach ($this->listeners as $listener) {
$tcpserver->init($listener["ip"], $listener["port"], [$this, "connect"]);
}
$tcpserver->maxChild($this->maxConnection);
$tcpserver->loop();
}
final public function connect($tcpserver)
{
if ($this->runningUser) {
$user = posix_getpwnam($this->runningUser);
posix_setuid($user['uid']);
}
if ($this->runningGroup) {
$group = posix_getgrnam($this->runningGroup);
posix_setgid($group['gid']);
}
$httpConnection = new HttpConnection($tcpserver);
}
}

196
src/RssItem.php Normal file
View File

@@ -0,0 +1,196 @@
<?php
/** DomFramework
* @package domframework
* @author Dominique Fournier <dominique@fournier38.fr>
* @license BSD
*/
namespace Domframework;
/**
* This class manage one RSS Item
*
* Called by Rss
*/
class RssItem
{
/** The title of the item
*/
private $title;
/** The URL of the item
*/
private $link;
/** The item synopsis
*/
private $description;
/** Email address of the author of the item
*/
private $author;
/** URL of a page for comments relating to the item
*/
private $comments;
/** A string that uniquely identifies the item
*/
private $guid;
/** Indicates when the item was published
*/
private $pubDate;
/** Get/Set the value
* @param string|null $title The title to get/set
*/
public function title($title = null)
{
if ($title === null) {
return $this->title;
}
if (! is_string($title)) {
throw new \Exception("Title provided to RSS Item is not a string", 500);
}
if ($title === "") {
$title = null;
}
$this->title = $title;
return $this;
}
/** Get/Set the value
* @param string|null $link The link to get/set
*/
public function link($link = null)
{
if ($link === null) {
return $this->link;
}
if (! is_string($link)) {
throw new \Exception("Link provided to RSS Item is not a string", 500);
}
$verify = new Verify();
if (! $verify->is_URL($link)) {
throw new \Exception("Link provided to RSS Item is not an URL", 500);
}
if ($link === "") {
$link = null;
}
$this->link = $link;
return $this;
}
/** Get/Set the value
* @param string|null $description The description to get/set
*/
public function description($description = null)
{
if ($description === null) {
return $this->description;
}
if (! is_string($description)) {
throw new \Exception(
"Description provided to RSS Item is not a string",
500
);
}
if ($description === "") {
$description = null;
}
$this->description = $description;
return $this;
}
/** Get/Set the value
* @param string|null $author The author to get/set
*/
public function author($author = null)
{
if ($author === null) {
return $this->author;
}
if (! is_string($author)) {
throw new \Exception("Author provided to RSS Item is not a string", 500);
}
if ($author === "") {
$author = null;
}
$this->author = $author;
return $this;
}
/** Get/Set the value
* @param string|null $comments The comments to get/set
*/
public function comments($comments = null)
{
if ($comments === null) {
return $this->comments;
}
if (! is_string($comments)) {
throw new \Exception(
"Comments provided to RSS Item is not a string",
500
);
}
if ($comments === "") {
$comments = null;
}
$this->comments = $comments;
return $this;
}
/** Get/Set the value
* @param string|null $guid The guid to get/set
*/
public function guid($guid = null)
{
if ($guid === null) {
return $this->guid;
}
if (! is_string($guid)) {
throw new \Exception("GUID provided to RSS Item is not a string", 500);
}
if ($guid === "") {
$guid = null;
}
$this->guid = $guid;
return $this;
}
/** Get/Set the value
* @param string|null $pubDate The pubDate to get/set
*/
public function pubDate($pubDate = null)
{
if ($pubDate === null) {
return $this->pubDate;
}
if (! is_string($pubDate)) {
throw new \Exception(
"pubDate provided to RSS Item is not a string",
500
);
}
if (! Verify::staticIs_datetimeSQL($pubDate)) {
throw new \Exception(
"pubDate provided to RSS Item is not a valid date",
500
);
}
if ($pubDate === "") {
$pubDate = null;
} else {
$pubDate = Convert::convertDate(
$pubDate,
"Y-m-d H:i:s",
\DateTime::RFC2822
);
}
$this->pubDate = $pubDate;
return $this;
}
}

24
src/StateMachineState.php Normal file
View File

@@ -0,0 +1,24 @@
<?php
/** DomFramework
* @package domframework
* @author Dominique Fournier <dominique@fournier38.fr>
* @license BSD
*/
namespace Domframework;
class StateMachineState
{
private $methodName;
public function __construct(callable $methodName)
{
$this->methodName = $methodName;
}
public function run()
{
return call_user_func($this->methodName);
}
}

View File

@@ -0,0 +1,43 @@
<?php
/** DomFramework
* @package domframework
* @author Dominique Fournier <dominique@fournier38.fr>
* @license BSD
*/
namespace Domframework;
class StateMachineTransition
{
private $fromStateName;
private $toStateName;
private $methodName;
public function __construct(string $fromStateName, string $toStateName, callable $methodName)
{
$this->fromStateName = $fromStateName;
$this->toStateName = $toStateName;
$this->methodName = $methodName;
}
public function getFromStateName(): string
{
return $this->fromStateName;
}
public function getToStateName(): string
{
return $this->toStateName;
}
public function getMethodName(): callable
{
return $this->methodName;
}
public function run()
{
return call_user_func($this->methodName);
}
}