PDF rausgenommen

This commit is contained in:
aschwarz
2023-01-23 11:03:31 +01:00
parent 82d562a322
commit a6523903eb
28078 changed files with 4247552 additions and 2 deletions

View File

@ -0,0 +1,17 @@
---
engines:
duplication:
enabled: true
config:
languages:
- php
fixme:
enabled: true
phpmd:
enabled: true
ratings:
paths:
- "**.inc"
- "**.php"
exclude_paths:
- tests/

View File

@ -0,0 +1,22 @@
The MIT License (MIT)
Copyright (c) 2015 David Patiashvili
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@ -0,0 +1,145 @@
# Sparkline
PHP Class (using GD) to generate sparklines
[![Build Status](https://travis-ci.org/davaxi/Sparkline.svg)](https://travis-ci.org/davaxi/Sparkline)
[![Latest Stable Version](https://poser.pugx.org/davaxi/sparkline/v/stable)](https://packagist.org/packages/davaxi/sparkline)
[![Total Downloads](https://poser.pugx.org/davaxi/sparkline/downloads)](https://packagist.org/packages/davaxi/sparkline)
[![Latest Unstable Version](https://poser.pugx.org/davaxi/sparkline/v/unstable)](https://packagist.org/packages/davaxi/sparkline)
[![License](https://poser.pugx.org/davaxi/sparkline/license)](https://packagist.org/packages/davaxi/sparkline)
[![Maintainability](https://api.codeclimate.com/v1/badges/9a5da533685204c53989/maintainability)](https://codeclimate.com/github/davaxi/Sparkline/maintainability)
[![Test Coverage](https://api.codeclimate.com/v1/badges/9a5da533685204c53989/test_coverage)](https://codeclimate.com/github/davaxi/Sparkline/test_coverage)
[![Issue Count](https://codeclimate.com/github/davaxi/Sparkline/badges/issue_count.svg)](https://codeclimate.com/github/davaxi/Sparkline)
## Installation
This page contains information about installing the Library for PHP.
### Requirements
- PHP version 5.3.0 or greater
- The GD PHP extension
### Obtaining the client library
There are two options for obtaining the files for the client library.
#### Using Composer
You can install the library by adding it as a dependency to your composer.json.
```
"require": {
"davaxi/sparkline": "^1.1"
}
```
#### Cloning from GitHub
The library is available on [GitHub](https://github.com/davaxi/Sparkline). You can clone it into a local repository with the git clone command.
```
git clone https://github.com/davaxi/Sparkline.git
```
### What to do with the files
After obtaining the files, ensure they are available to your code. If you're using Composer, this is handled for you automatically. If not, you will need to add the `autoload.php` file inside the client library.
```
require '/path/to/sparkline/folder/autoload.php';
```
## Usage
Exemple:
![Sparkline](https://raw.githubusercontent.com/davaxi/Sparkline/master/tests/data/testGenerate2-mockup.png)
```
<?php
require '/path/to/sparkline/folder/autoload.php';
$sparkline = new Davaxi\Sparkline();
$sparkline->setData(array(2,4,5,6,10,7,8,5,7,7,11,8,6,9,11,9,13,14,12,16));
$sparkline->display();
?>
```
## Documentation
```
$sparkline = new Davaxi\Sparkline();
// Change format (Default value 80x20)
$sparkline->setFormat('100x40');
// or
$sparkline->setWidth(100);
$sparkline->setHeight(40);
// Apply padding
$sparkline->setPadding('10'); // > top: 10 | right: 10 | bottom: 10 | left: 10
$sparkline->setPadding('10 20'); // > top: 10 | right: 20 | bottom: 10 | left: 20
$sparkline->setPadding('10 20 30'); // > top: 10 | right: 20 | bottom: 30 | left: 20
$sparkline->setPadding('10 20 30 40'); // > top: 10 | right: 20 | bottom: 30 | left: 40
// Change background color (Default value #FFFFFF)
$sparkline->setBackgroundColorHex('#0f354b');
// or
$sparkline->setBackgroundColorRGB(15, 53, 75);
// or
$sparkline->deactivateBackgroundColor();
// Change line color (Default value #1388db)
$sparkline->setLineColorHex('#1c628b');
// or
$sparkline->setLineColorRGB(28, 98, 139);
// Change line thickness (Default value 1.75 px)
$sparkline->setLineThickness(2.2);
// Change fill color (Default value #e6f2fa)
$sparkline->setFillColorHex('#8b1c2b');
// or
$sparkline->setFillColorRGB(139, 28, 43);
// or
$sparkline->deactivateFillColor();
$sparkline->setData(array(.....)); // Set data set
$sparkline->getData(); // Get seted data
$sparkline->generate(); // If ou want regenerate picture
// Change base of height value (default max($data))
$sparkline->setBase(20);
// Change origin of chart value (yAxis) (default: 0)
$sparkline->setOriginValue(40);
// Add dot on first/last/minimal/maximal value
// Data set before used method
$sparkline->addPoint('minimum', 3, '#efefef');
$sparkline->addPoint('maximum', 3, '#efefef');
$sparkline->addPoint('first', 3, '#efefef');
$sparkline->addPoint('last', 3, '#efefef');
// Or by index
$sparkline->addPoint(1, 3, '#efefef');
// If display
$sparkline->setEtag('your hash'); // If you want add ETag header
$sparkline->setFilename('yourPictureName'); // For filenamen header
$sparkline->setExpire('+1 day'); // If you want add expire header
// or
$sparkline->setExpire(strtotime('+1 day'));
$sparkline->display(); // Display with correctly headers
// If save
$sparkline->save('/your/path/to/save/picture');
$sparkline->destroy(); // Destroy picture after generated / displayed / saved
```

View File

@ -0,0 +1,3 @@
<?php
require_once __DIR__ . '/src/autoload.php';

View File

@ -0,0 +1,47 @@
{
"name": "davaxi/sparkline",
"description": "PHP Class (using GD) to generate sparklines",
"version": "1.1.2",
"type": "library",
"keywords": [
"sparkline",
"php",
"picture"
],
"license": "MIT",
"authors": [
{
"name": "David Patiashvili",
"email": "stratagem.david@gmail.com",
"homepage": "https://www.patiashvili.fr/",
"role": "Developer"
}
],
"support": {
"issues": "https://github.com/davaxi/Sparkline/issues",
"source": "https://github.com/davaxi/Sparkline/releases"
},
"minimum-stability": "stable",
"require": {
"php": ">=5.3.0",
"ext-gd": "*"
},
"require-dev": {
"php": ">=5.3.0",
"codeclimate/php-test-reporter": "dev-master",
"ext-gd": "*",
"phpro/grumphp": "^0.12.0",
"jakub-onderka/php-parallel-lint": "^0.9.2",
"sensiolabs/security-checker": "^4.1",
"povils/phpmnd": "^1.1",
"sebastian/phpcpd": "^3.0",
"squizlabs/php_codesniffer": "^3.1",
"friendsofphp/php-cs-fixer": "^2.8",
"wearejust/grumphp-extra-tasks": "^2.1"
},
"autoload": {
"psr-4": {
"Davaxi\\": "src/"
}
}
}

View File

@ -0,0 +1,39 @@
{
"name": "davaxi/sparkline",
"description": "PHP Class (using GD) to generate sparklines",
"version": "1.1.2",
"type": "library",
"keywords": [
"sparkline",
"php",
"picture"
],
"license": "MIT",
"authors": [
{
"name": "David Patiashvili",
"email": "stratagem.david@gmail.com",
"homepage": "https://www.patiashvili.fr/",
"role": "Developer"
}
],
"support": {
"issues": "https://github.com/davaxi/Sparkline/issues",
"source": "https://github.com/davaxi/Sparkline/releases"
},
"minimum-stability": "stable",
"require": {
"php": ">=5.3.0",
"ext-gd": "*"
},
"require-dev": {
"php": ">=5.3.0",
"codeclimate/php-test-reporter": "dev-master",
"ext-gd": "*"
},
"autoload": {
"psr-4": {
"Davaxi\\": "src/"
}
}
}

View File

@ -0,0 +1,89 @@
parameters:
git_dir: .
bin_dir: vendor/bin
ascii:
failed: ~
succeeded: ~
tasks:
composer:
file: ./composer.json
no_check_all: false
no_check_lock: false
no_check_publish: false
no_local_repository: false
with_dependencies: false
strict: false
jsonlint:
ignore_patterns: []
detect_key_conflicts: false
phpcpd:
directory: '.'
exclude: ['vendor']
names_exclude: []
fuzzy: false
min_lines: 5
min_tokens: 70
triggered_by: ['php']
phpcsfixer2:
allow_risky: true
cache_file: ~
config: .php_cs
rules: []
using_cache: false
config_contains_finder: true
verbose: true
diff: false
triggered_by: ['php']
php_cs_auto_fixerv2:
allow_risky: true
cache_file: ~
config: .php_cs
rules: []
using_cache: true
verbose: true
diff: false
triggered_by: ['php']
metadata:
priority: 1
blocking: false
phpcs:
standard: 'PSR2'
show_warnings: true
tab_width: 4
whitelist_patterns: []
encoding: ~
ignore_patterns: ['\/tests\/']
sniffs: []
triggered_by: ['php']
phplint:
exclude: []
jobs: ~
triggered_by: ['php']
phpmnd:
directory: .
exclude: []
exclude_name: []
exclude_path: []
extensions: []
hint: false
ignore_numbers: []
ignore_strings: []
strings: false
triggered_by: ['php']
phpunit:
config_file: ~
testsuite: ~
group: []
always_execute: false
securitychecker:
lockfile: ./composer.lock
format: ~
end_point: ~
timeout: ~
run_always: false
yamllint:
ignore_patterns: []
object_support: false
exception_on_invalid_type: false
extensions:
- Wearejust\GrumPHPExtra\Extension\Loader

View File

@ -0,0 +1,18 @@
<?xml version="1.0" encoding="UTF-8"?>
<phpunit backupGlobals="false"
backupStaticAttributes="false"
bootstrap="tests/bootstrap.php"
colors="true"
convertErrorsToExceptions="true"
convertNoticesToExceptions="true"
convertWarningsToExceptions="true"
processIsolation="false"
stopOnFailure="false"
syntaxCheck="false"
>
<testsuites>
<testsuite name="General tests">
<directory suffix=".php">./tests/</directory>
</testsuite>
</testsuites>
</phpunit>

View File

@ -0,0 +1,230 @@
<?php
namespace Davaxi;
use Davaxi\Sparkline\DataTrait;
use Davaxi\Sparkline\FormatTrait;
use Davaxi\Sparkline\Picture;
use Davaxi\Sparkline\PointTrait;
use Davaxi\Sparkline\StyleTrait;
/**
* Class Sparkline.
*/
class Sparkline
{
use StyleTrait;
use DataTrait;
use FormatTrait;
use PointTrait;
const MIN_DATA_LENGTH = 2;
const FORMAT_DIMENSION = 2;
const HEXADECIMAL_ALIAS_LENGTH = 3;
const CSS_PADDING_ONE = 1;
const CSS_PADDING_TWO = 2;
const CSS_PADDING_THREE = 3;
const CSS_PADDING = 4;
/**
* @var string
* ex: QUERY_STRING if dedicated url
*/
protected $eTag;
/**
* @var int
*/
protected $expire;
/**
* @var string
*/
protected $filename = 'sparkline';
/**
* @var resource
*/
protected $file;
/**
* @var array
*/
protected $server = [];
/**
* Sparkline constructor.
*
* @codeCoverageIgnore
*/
public function __construct()
{
if (!extension_loaded('gd')) {
throw new \InvalidArgumentException('GD extension is not installed');
}
}
/**
* @param string $eTag
*/
public function setETag($eTag)
{
if (null === $eTag) {
$this->eTag = null;
return;
}
$this->eTag = md5($eTag);
}
/**
* @param string $filename
* Without extension
*/
public function setFilename($filename)
{
$this->filename = $filename;
}
/**
* @param string|int $expire
* time format or string format
*/
public function setExpire($expire)
{
if (null === $expire) {
$this->expire = null;
return;
}
if (is_numeric($expire)) {
$this->expire = $expire;
return;
}
$this->expire = strtotime($expire);
}
public function generate()
{
list($width, $height) = $this->getNormalizedSize();
$count = $this->getCount();
list($polygon, $line) = $this->getChartElements($this->data);
$picture = new Picture($width, $height);
$picture->applyBackground($this->backgroundColor);
$picture->applyThickness($this->lineThickness * $this->ratioComputing);
$picture->applyPolygon($polygon, $this->fillColor, $count);
$picture->applyLine($line, $this->lineColor);
foreach ($this->points as $point) {
$isFirst = $point['index'] === 0;
$lineIndex = $isFirst ? 0 : $point['index'] - 1;
$picture->applyDot(
$line[$lineIndex][$isFirst ? 0 : 2],
$line[$lineIndex][$isFirst ? 1 : 3],
$point['radius'] * $this->ratioComputing,
$point['color']
);
}
$this->file = $picture->generate($this->width, $this->height);
}
/**
* @param array $server
*/
public function setServer(array $server)
{
$this->server = $server;
}
/**
* @param $key
*
* @return mixed|null
*/
public function getServerValue($key)
{
if (isset($this->server[$key])) {
return $this->server[$key];
}
return null;
}
/**
* @return bool
*/
protected function checkNoModified()
{
$httpIfNoneMatch = $this->getServerValue('HTTP_IF_NONE_MATCH');
if ($this->eTag && $httpIfNoneMatch) {
if ($httpIfNoneMatch === $this->eTag) {
$serverProtocol = $this->getServerValue('SERVER_PROTOCOL');
header($serverProtocol . ' 304 Not Modified', true, 304);
return true;
}
}
return false;
}
public function display()
{
if (!$this->file) {
$this->generate();
}
if ($this->checkNoModified()) {
return;
}
header('Content-Type: image/png');
header('Content-Disposition: inline; filename="' . $this->filename . '.png"');
header('Accept-Ranges: none');
if ($this->eTag) {
header('ETag: ' . $this->eTag);
}
if (null !== $this->expire) {
header('Expires: ' . gmdate('D, d M Y H:i:s T', $this->expire));
}
imagepng($this->file);
}
public function save($savePath)
{
if (!$this->file) {
$this->generate();
}
imagepng($this->file, $savePath);
}
/**
* @return string
*/
public function toBase64()
{
if (!$this->file) {
$this->generate();
}
ob_start();
imagepng($this->file);
$buffer = ob_get_contents();
if (ob_get_length()) {
ob_end_clean();
}
return base64_encode($buffer);
}
public function destroy()
{
if ($this->file) {
imagedestroy($this->file);
}
$this->file = null;
}
}

View File

@ -0,0 +1,143 @@
<?php
namespace Davaxi\Sparkline;
/**
* Trait DataTrait.
*/
trait DataTrait
{
/**
* @var int
* Base of value
*/
protected $base;
/**
* @var int
* Original value of chart
*/
protected $originValue = 0;
/**
* @var array
*/
protected $data = [0, 0];
/**
* @param $base
* Set base for values
*/
public function setBase($base)
{
$this->base = $base;
}
/**
* @param float $originValue
* Set origin value of chart
*/
public function setOriginValue($originValue)
{
$this->originValue = $originValue;
}
/**
* @param array $data
*/
public function setData(array $data)
{
$data = array_values($data);
$count = count($data);
if (!$count) {
$this->data = [0, 0];
return;
}
if ($count < static::MIN_DATA_LENGTH) {
$this->data = array_fill(0, 2, $data[0]);
return;
}
$this->data = $data;
}
/**
* @return array
*/
public function getNormalizedData()
{
$data = $this->data;
foreach ($data as $i => $value) {
$data[$i] = max(0, $value - $this->originValue);
}
return $data;
}
/**
* @return array
*/
public function getData()
{
return $this->data;
}
/**
* @return int
*/
public function getCount()
{
return count($this->data);
}
/**
* @return array
*/
protected function getMaxValueWithIndex()
{
$max = max($this->data);
$maxKeys = array_keys($this->data, $max);
$maxIndex = end($maxKeys);
if ($this->base) {
$max = $this->base;
}
return [$maxIndex, $max];
}
/**
* @return float
*/
protected function getMaxValue()
{
if ($this->base) {
return $this->base;
}
return max($this->data);
}
/**
* @return array
*/
protected function getMinValueWithIndex()
{
$min = min($this->data);
$minKey = array_keys($this->data, $min);
$minIndex = end($minKey);
return [$minIndex, $min];
}
/**
* @return array
*/
protected function getExtremeValues()
{
list($minIndex, $min) = $this->getMinValueWithIndex();
list($maxIndex, $max) = $this->getMaxValueWithIndex();
return [$minIndex, $min, $maxIndex, $max];
}
}

View File

@ -0,0 +1,244 @@
<?php
namespace Davaxi\Sparkline;
/**
* Trait FormatTrait.
*/
trait FormatTrait
{
/**
* @var int
* Recommended: 50 < 800
*/
protected $width = 80;
/**
* @var int
* Recommended: 20 < 800
*/
protected $height = 20;
/**
* @var int
*/
protected $ratioComputing = 4;
/**
* @var array
*/
protected $padding = [
'top' => 0,
'right' => 0,
'bottom' => 0,
'left' => 0,
];
/**
* @param string $format (Width x Height)
*/
public function setFormat($format)
{
$values = explode('x', $format);
if (count($values) !== static::FORMAT_DIMENSION) {
throw new \InvalidArgumentException('Invalid format params. Expected string Width x Height');
}
$this->setWidth($values[0]);
$this->setHeight($values[1]);
}
/**
* @param int $width
*/
public function setWidth($width)
{
$this->width = (int)$width;
}
/**
* @param int $height
*/
public function setHeight($height)
{
$this->height = (int)$height;
}
/**
* Set padding : format top right bottom left
* ex: 0 10 0 10.
*
* @param string $padding
*/
public function setPadding($padding)
{
list($top, $right, $bottom, $left) = $this->paddingStringToArray($padding);
$this->padding['top'] = $top;
$this->padding['right'] = $right;
$this->padding['bottom'] = $bottom;
$this->padding['left'] = $left;
}
/**
* @return int
*/
protected function getNormalizedHeight()
{
return $this->height * $this->ratioComputing;
}
/**
* @return int
*/
protected function getInnerHeight()
{
return $this->height - $this->padding['top'] - $this->padding['bottom'];
}
/**
* @return array
*/
protected function getNormalizedPadding()
{
return array_map(
function ($value) {
return $value * $this->ratioComputing;
},
$this->padding
);
}
/**
* @return int
*/
protected function getInnerNormalizedHeight()
{
return $this->getInnerHeight() * $this->ratioComputing;
}
/**
* @return int
*/
protected function getNormalizedWidth()
{
return $this->width * $this->ratioComputing;
}
/**
* @return int
*/
protected function getInnerWidth()
{
return $this->width - ($this->padding['left'] + $this->padding['right']);
}
/**
* @return int
*/
protected function getInnerNormalizedWidth()
{
return $this->getInnerWidth() * $this->ratioComputing;
}
/**
* @return array
*/
protected function getNormalizedSize()
{
return [
$this->getNormalizedWidth(),
$this->getNormalizedHeight(),
];
}
/**
* @return array
*/
protected function getInnerNormalizedSize()
{
return [
$this->getInnerNormalizedWidth(),
$this->getInnerNormalizedHeight(),
];
}
/**
* @param $count
*
* @return float|int
*/
protected function getStepWidth($count)
{
$innerWidth = $this->getInnerNormalizedWidth();
return $innerWidth / ($count - 1);
}
/**
* @param array $data
* @param $height
*
* @return array
*/
protected function getDataForChartElements(array $data, $height)
{
$max = $this->getMaxValue();
$minHeight = 1 * $this->ratioComputing;
$maxHeight = $height - $minHeight;
foreach ($data as $i => $value) {
$value = (int)$value;
if ($value <= 0) {
$value = 0;
}
if ($value > 0) {
$value = round(($value / $max) * $height);
}
$data[$i] = max($minHeight, min($value, $maxHeight));
}
return $data;
}
/**
* @param array $data
*
* @return array
*/
protected function getChartElements(array $data)
{
$count = count($data);
$step = $this->getStepWidth($count);
$height = $this->getInnerNormalizedHeight();
$normalizedPadding = $this->getNormalizedPadding();
$data = $this->getDataForChartElements($data, $height);
$pictureX1 = $pictureX2 = $normalizedPadding['left'];
$pictureY1 = $normalizedPadding['top'] + $height - $data[0];
$polygon = [];
$line = [];
// Initialize
$polygon[] = $normalizedPadding['left'];
$polygon[] = $normalizedPadding['top'] + $height;
// First element
$polygon[] = $pictureX1;
$polygon[] = $pictureY1;
for ($i = 1; $i < $count; ++$i) {
$pictureX2 = $pictureX1 + $step;
$pictureY2 = $normalizedPadding['top'] + $height - $data[$i];
$line[] = [$pictureX1, $pictureY1, $pictureX2, $pictureY2];
$polygon[] = $pictureX2;
$polygon[] = $pictureY2;
$pictureX1 = $pictureX2;
$pictureY1 = $pictureY2;
}
// Last
$polygon[] = $pictureX2;
$polygon[] = $normalizedPadding['top'] + $height;
return [$polygon, $line];
}
}

View File

@ -0,0 +1,174 @@
<?php
namespace Davaxi\Sparkline;
/**
* Class PictureTrait.
*/
class Picture
{
const DOT_RADIUS_TO_WIDTH = 2;
/**
* @var \resource
*/
protected $resource;
/**
* Picture constructor.
*
* @param $width
* @param $height
*/
public function __construct($width, $height)
{
$this->width = $width;
$this->height = $height;
$this->resource = imagecreatetruecolor($width, $height);
}
/**
* @param array $setColor
*
* @return int
*/
protected function getBackground(array $setColor = [])
{
if ($setColor) {
return imagecolorallocate(
$this->resource,
$setColor[0],
$setColor[1],
$setColor[2]
);
}
return imagecolorallocatealpha(
$this->resource,
0,
0,
0,
127
);
}
/**
* @param $lineColor
*
* @return int
*/
public function getLineColor($lineColor)
{
return imagecolorallocate(
$this->resource,
$lineColor[0],
$lineColor[1],
$lineColor[2]
);
}
/**
* @param array $backgroundColor
*/
public function applyBackground(array $backgroundColor)
{
imagesavealpha($this->resource, true);
imagefill(
$this->resource,
0,
0,
$this->getBackground($backgroundColor)
);
}
/**
* @param $lineThickness
*/
public function applyThickness($lineThickness)
{
imagesetthickness($this->resource, $lineThickness);
}
/**
* @param array $polygon
* @param array $fillColor
* @param $count
*/
public function applyPolygon(array $polygon, array $fillColor, $count)
{
if (!$fillColor) {
return;
}
$fillColor = imagecolorallocate($this->resource, $fillColor[0], $fillColor[1], $fillColor[2]);
imagefilledpolygon($this->resource, $polygon, $count + 2, $fillColor);
}
/**
* @param array $line
* @param array $lineColor
*/
public function applyLine(array $line, array $lineColor)
{
$lineColor = $this->getLineColor($lineColor);
foreach ($line as $coordinates) {
list($pictureX1, $pictureY1, $pictureX2, $pictureY2) = $coordinates;
imageline($this->resource, $pictureX1, $pictureY1, $pictureX2, $pictureY2, $lineColor);
}
}
/**
* @param $positionX
* @param $positionY
* @param $radius
* @param array $color
*/
public function applyDot($positionX, $positionY, $radius, $color)
{
if (!$color || !$radius) {
return;
}
$minimumColor = imagecolorallocate(
$this->resource,
$color[0],
$color[1],
$color[2]
);
imagefilledellipse(
$this->resource,
$positionX,
$positionY,
$radius * static::DOT_RADIUS_TO_WIDTH,
$radius * static::DOT_RADIUS_TO_WIDTH,
$minimumColor
);
}
/**
* @param $width
* @param $height
*
* @return resource
*/
public function generate($width, $height)
{
$sparkline = imagecreatetruecolor($width, $height);
imagealphablending($sparkline, false);
imagecopyresampled(
$sparkline,
$this->resource,
0,
0,
0,
0,
$width,
$height,
$this->width,
$this->height
);
imagesavealpha($sparkline, true);
imagedestroy($this->resource);
return $sparkline;
}
}

View File

@ -0,0 +1,67 @@
<?php
namespace Davaxi\Sparkline;
/**
* Trait PointTrait.
*/
trait PointTrait
{
/**
* @var array
*/
protected $points = [];
/**
* @param $index
* @param $dotRadius
* @param $colorHex
*/
public function addPoint($index, $dotRadius, $colorHex)
{
$mapping = $this->getPointIndexMapping();
if (array_key_exists($index, $mapping)) {
$index = $mapping[$index];
if ($index < 0) {
return;
}
}
$this->checkPointIndex($index);
$this->points[] = [
'index' => $index,
'radius' => $dotRadius,
'color' => $this->colorHexToRGB($colorHex),
];
}
/**
* @return array
*/
protected function getPointIndexMapping()
{
$count = $this->getCount();
list($minIndex, $min, $maxIndex, $max) = $this->getExtremeValues();
$mapping = [];
$mapping['first'] = $count > 1 ? 0 : -1;
$mapping['last'] = $count > 1 ? $count - 1 : -1;
$mapping['minimum'] = $min !== $max ? $minIndex : -1;
$mapping['maximum'] = $min !== $max ? $maxIndex : -1;
return $mapping;
}
/**
* @param $index
*/
protected function checkPointIndex($index)
{
$count = $this->getCount();
if (!is_numeric($index)) {
throw new \InvalidArgumentException('Invalid index : ' . $index);
}
if ($index < 0 || $index >= $count) {
throw new \InvalidArgumentException('Index out of range [0-' . $count - 1 . '] : ' . $index);
}
}
}

View File

@ -0,0 +1,186 @@
<?php
namespace Davaxi\Sparkline;
/**
* Trait StyleTrait.
*/
trait StyleTrait
{
/**
* @var array (rgb)
* Default: #ffffff
*/
protected $backgroundColor = [255, 255, 255];
/**
* @var array (rgb)
* Default: #1388db
*/
protected $lineColor = [19, 136, 219];
/**
* @var array (rgb)
* Default: #e6f2fa
*/
protected $fillColor = [230, 242, 250];
/**
* @var float (px)
* Default: 1.75px
*/
protected $lineThickness = 1.75;
/**
* Set background to transparent.
*/
public function deactivateBackgroundColor()
{
$this->backgroundColor = [];
}
/**
* @param string $color (hexadecimal)
*/
public function setBackgroundColorHex($color)
{
list($red, $green, $blue) = $this->colorHexToRGB($color);
$this->setBackgroundColorRGB($red, $green, $blue);
}
/**
* @param int $red
* @param int $green
* @param int $blue
*/
public function setBackgroundColorRGB($red, $green, $blue)
{
$this->backgroundColor = [$red, $green, $blue];
}
/**
* @param string $color (hexadecimal)
*/
public function setLineColorHex($color)
{
list($red, $green, $blue) = $this->colorHexToRGB($color);
$this->setLineColorRGB($red, $green, $blue);
}
/**
* @param int $red
* @param int $green
* @param int $blue
*/
public function setLineColorRGB($red, $green, $blue)
{
$this->lineColor = [$red, $green, $blue];
}
/**
* @param float $thickness (in px)
*/
public function setLineThickness($thickness)
{
$this->lineThickness = (float)$thickness;
}
/**
* Set fill color to transparent.
*/
public function deactivateFillColor()
{
$this->fillColor = [];
}
/**
* @param string $color (hexadecimal)
*/
public function setFillColorHex($color)
{
list($red, $green, $blue) = $this->colorHexToRGB($color);
$this->setFillColorRGB($red, $green, $blue);
}
/**
* @param int $red
* @param int $green
* @param int $blue
*/
public function setFillColorRGB($red, $green, $blue)
{
$this->fillColor = [$red, $green, $blue];
}
/**
* @param string $color (hexadecimal)
* @exceptions \InvalidArgumentException
*
* @return array (r,g,b)
*/
protected function colorHexToRGB($color)
{
if (!$this->checkColorHex($color)) {
throw new \InvalidArgumentException('Invalid hexadecimal value ' . $color);
}
$color = mb_strtolower($color);
$color = ltrim($color, '#');
if (mb_strlen($color) === static::HEXADECIMAL_ALIAS_LENGTH) {
$color = $color[0] . $color[0] . $color[1] . $color[1] . $color[2] . $color[2];
}
$color = hexdec($color);
return [
0xFF & ($color >> 0x10), // Red
0xFF & ($color >> 0x8), // Green
0xFF & $color, // Blue
];
}
/**
* Formats:
* all
* vertical horizontal
* top horizontal bottom
* top right bottom left.
*
* @param string $padding
*
* @return array
*/
protected function paddingStringToArray($padding)
{
$parts = explode(' ', $padding);
switch (count($parts)) {
case static::CSS_PADDING_ONE:
$value = (float)$parts[0];
return [$value, $value, $value, $value];
break;
case static::CSS_PADDING_TWO:
$verticalValue = (float)$parts[0];
$horizontalValue = (float)$parts[1];
return [$verticalValue, $horizontalValue, $verticalValue, $horizontalValue];
case static::CSS_PADDING_THREE:
$parts[3] = $parts[1];
return $parts;
case static::CSS_PADDING:
return $parts;
default:
throw new \InvalidArgumentException('Invalid padding format');
}
}
/**
* @param $color
*
* @return int
*/
protected static function checkColorHex($color)
{
return preg_match('/^#?+[0-9a-f]{3}(?:[0-9a-f]{3})?$/i', $color);
}
}

View File

@ -0,0 +1,16 @@
<?php
spl_autoload_register(
function ($className) {
$classPath = explode('\\', $className);
if ($classPath[0] !== 'Davaxi') {
return;
}
// Drop 'Davaxi', and maximum file path depth in this project is 1
$classPath = array_slice($classPath, 1, 2);
$filePath = __DIR__ . '/' . implode('/', $classPath) . '.php';
if (file_exists($filePath)) {
require_once($filePath);
}
}
);