bakame / period-visualizer
Requires
- php: ^7.2
- ext-json: *
- league/period: ^4.4
Requires (Dev)
- friendsofphp/php-cs-fixer: ^2.0
- phpstan/phpstan: ^0.11.1
- phpstan/phpstan-phpunit: ^0.11.0
- phpstan/phpstan-strict-rules: ^0.11.0
- phpunit/phpunit: ^8.1
Suggests
- league/climate: to implement a better CLI console output
- symfony/console: to implement a better CLI console output
README
此包包含League Period的可视化工具。
它受到@thecrypticace在以下PRVisualization Helper的工作的启发。
<?php use Bakame\Period\Visualizer\Dataset; use Bakame\Period\Visualizer\GanttChart; use League\Period\Datepoint; use League\Period\Period; use League\Period\Sequence; $sequence = new Sequence( Datepoint::create('2018-11-29')->getYear(Period::EXCLUDE_START_INCLUDE_END), Datepoint::create('2018-05-29')->getMonth()->expand('3 MONTH'), Datepoint::create('2017-01-13')->getQuarter(Period::EXCLUDE_ALL), Period::around('2016-06-01', '3 MONTHS', Period::INCLUDE_ALL) ); $dataset = Dataset::fromSequence($sequence); $dataset->append('gaps', $sequence->gaps()); (new GanttChart())->stroke($dataset);
结果
A (--------------------] B [-----------) C (----) D [---------] gaps (------] [---------------]
系统要求
您需要
- PHP >= 7.2,但推荐使用最新稳定版PHP
- League/Period 4.4+,但推荐使用最新稳定版
安装
$ composer require bakame/period-visualizer
使用
基本使用
生成一个简单的图表。
要生成图表,您需要向Dataset
构造函数提供一个对列表。每个对是一个包含2个值的array
。
- 键
0
的值表示标签 - 键
1
是League\Period\Period
或League\Period\Sequence
对象
<?php use Bakame\Period\Visualizer\Dataset; use Bakame\Period\Visualizer\GanttChart; use League\Period\Period; $dataset = new Dataset([ ['A', new Period('2018-01-01', '2018-02-01')], ['B', new Period('2018-01-15', '2018-02-01')], ]); (new GanttChart())->stroke($dataset);
结果
A [----------------------------------------------) B [-------------------------)
追加要显示的项目
如果您想显示一个Sequence
及其一些操作。您可以使用Dataset::append
方法追加操作结果。
<?php use Bakame\Period\Visualizer\Dataset; use Bakame\Period\Visualizer\GanttChart; use League\Period\Period; use League\Period\Sequence; $sequence = new Sequence( new Period('2018-01-01', '2018-03-01'), new Period('2018-05-01', '2018-08-01') ); $dataset = new Dataset(); $dataset->append('A', $sequence[0]); $dataset->append('B', $sequence[1]); $dataset->append('GAPS', $sequence->gaps()); (new GanttChart())->stroke($dataset);
结果
A [-------------) B [----------------) GAPS [------------)
Dataset
实现了Countable
和IteratorAggregate
接口。它还公开了以下方法
<?php public function Dataset::fromSequence(Sequence $sequence, ?LabelGenerator $labelGenerator = null): self; //Creates a new Dataset from a Sequence and a LabelGenerator. public function Dataset::fromCollection(iterable $collection): self; //Creates a new Dataset from a generic iterable structure. public function Dataset::appendAll(iterable $pairs): void; //adds multiple pairs at once. public function Dataset::isEmpty(): bool; //Tells whether the collection is empty. public function Dataset::labels(): string[]; //the current labels used public function Dataset::items(): Sequence[]; //the current objects inside the Dataset public function Dataset::boundaries(): ?Period; //Returns the collection boundaries or null if it is empty. public function Dataset::labelMaxLength(): int; //Returns the label max length. public function Dataset::withLabels(LabelGenerator $labelGenerator): self; //Update the labels used for the dataset.
设置数据集标签
默认情况下,您必须为添加到Dataset
对象中的每个项目提供一个标签。此包提供了一种简单的生成和创建可视化标签的LabelGenerator
接口。
需要实现以下方法的LabelGenerator
类
Dataset::fromSequence
,从Sequence
对象创建一个新实例;Dataset::withLabels
,更新当前实例中的关联标签;
默认情况下,当使用Dataset::fromSequence
时,如果没有提供LabelGenerator
类,将使用LatinLetter
标签生成器。
当前包附带以下LabelGenerator
实现类
LatinLetter
根据拉丁字母生成标签。
<?php use Bakame\Period\Visualizer\Dataset; use Bakame\Period\Visualizer\GanttChart; use Bakame\Period\Visualizer\LatinLetter; use League\Period\Period; use League\Period\Sequence; $dataset = Dataset::fromSequence( new Sequence(new Period('2018-01-01', '2018-02-01'), new Period('2018-01-15', '2018-02-01')), new LatinLetter('aa') ); (new GanttChart())->stroke($dataset);
结果
aa [-----------------------------------) ab [----------)
LatinLetter
还公开了以下方法
<?php public function LatinLetter::startingAt(): string; //returns the first letter to be used public function LatinLetter::startsWith(): self; //returns a new object with a new starting letter
DecimalNumber
根据十进制数系统生成标签。
<?php use Bakame\Period\Visualizer\Dataset; use Bakame\Period\Visualizer\DecimalNumber; use Bakame\Period\Visualizer\GanttChart; use League\Period\Period; use League\Period\Sequence; $dataset = Dataset::fromSequence( new Sequence(new Period('2018-01-01', '2018-02-01'), new Period('2018-01-15', '2018-02-01')), new DecimalNumber(42) ); (new GanttChart())->stroke($dataset);
结果
42 [-----------------------------------) 43 [----------)
DecimalNumber
还公开了以下方法
<?php public function DecimalNumber::startingAt(): string; //returns the first decimal number to be used public function DecimalNumber::startsWith(): self; //returns a new object with a new starting decimal number
RomanNumber
使用 DecimalNumber
标签生成器类来生成罗马数字标签。
<?php use Bakame\Period\Visualizer\Dataset; use Bakame\Period\Visualizer\DecimalNumber; use Bakame\Period\Visualizer\GanttChart; use Bakame\Period\Visualizer\RomanNumber; use League\Period\Period; use League\Period\Sequence; $labelGenerator = new RomanNumber(new DecimalNumber(5), RomanNumber::LOWER); $dataset = Dataset::fromSequence( new Sequence(new Period('2018-01-01', '2018-02-01'), new Period('2018-01-15', '2018-02-01')), $labelGenerator ); (new GanttChart())->stroke($dataset);
结果
v [-----------------------------------) vi [----------)
RomanNumber
还公开了以下方法
<?php const RomanNumber::UPPER = 1; const RomanNumber::LOWER = 2; public function RomanNumber::startingAt(): string; //returns the first decimal number to be used public function RomanNumber::startsWith(): self; //returns a new object with a new starting decimal number public function RomanNumber::withLetterCase(int $lettercase): self; //returns a new object with a new letter casing public function RomanNumber::isUpper(): bool; //Tells whether the roman letter is upper cased. public function RomanNumber::isLower(): bool; //Tells whether the roman letter is lower cased.
附加标签
使用任何实现了 labelGenerator
类来添加前缀和/或后缀字符串到生成的标签。
<?php use Bakame\Period\Visualizer\AffixLabel; use Bakame\Period\Visualizer\Dataset; use Bakame\Period\Visualizer\DecimalNumber; use Bakame\Period\Visualizer\GanttChart; use Bakame\Period\Visualizer\RomanNumber; use League\Period\Period; use League\Period\Sequence; $labelGenerator = new AffixLabel( new RomanNumber(new DecimalNumber(5), RomanNumber::LOWER), '*', //prefix '.)' //suffix ); $dataset = Dataset::fromSequence( new Sequence(new Period('2018-01-01', '2018-02-01'), new Period('2018-01-15', '2018-02-01')), $labelGenerator ); (new GanttChart())->stroke($dataset);
结果
* v .) [-----------------------------------) * vi .) [----------)
AffixLabel
还公开了以下方法
<?php public function AffixLabel::prefix(): string; //returns the current prefix public function AffixLabel::suffix(): string; //returns the current suffix public function AffixLabel::withPrefix(string $prefix): self; //returns a new object with a new prefix public function AffixLabel::withSuffix(string $suffix): self; //returns a new object with a new suffix
反转标签
使用任何实现了 labelGenerator
类来反转生成的标签顺序。
<?php use Bakame\Period\Visualizer\AffixLabel; use Bakame\Period\Visualizer\Dataset; use Bakame\Period\Visualizer\DecimalNumber; use Bakame\Period\Visualizer\GanttChart; use Bakame\Period\Visualizer\ReverseLabel; use Bakame\Period\Visualizer\RomanNumber; use League\Period\Period; use League\Period\Sequence; $labelGenerator = new DecimalNumber(5); $labelGenerator = new RomanNumber($labelGenerator, RomanNumber::LOWER); $labelGenerator = new AffixLabel($labelGenerator, '', '.'); $labelGenerator = new ReverseLabel($labelGenerator); $dataset = Dataset::fromSequence( new Sequence(new Period('2018-01-01', '2018-02-01'), new Period('2018-01-15', '2018-02-01')), $labelGenerator ); (new GanttChart())->stroke($dataset);
结果
vi. [-----------------------------------) v. [----------)
自定义标签生成器
您可以通过实现 Bakame\Period\Visualizer\LabelGenerator
接口来创建自己的标签生成器,如下所示
<?php use Bakame\Period\Visualizer\AffixLabel; use Bakame\Period\Visualizer\Dataset; use Bakame\Period\Visualizer\GanttChart; use Bakame\Period\Visualizer\LabelGenerator; use League\Period\Period; use League\Period\Sequence; $samelabel = new class implements LabelGenerator { public function generate(int $nbLabels): array { return array_fill(0, $nbLabels, $this->format('foobar')); } public function format($str): string { return (string) $str; } }; $labelGenerator = new AffixLabel($samelabel, '', '.'); $dataset = Dataset::fromSequence( new Sequence(new Period('2018-01-01', '2018-02-01'), new Period('2018-01-15', '2018-02-01')), $labelGenerator ); (new GanttChart())->stroke($dataset);
结果
foobar. [-----------------------------------) foobar. [----------)
显示数据集
GanttChart
类通过实现控制台的 Graph
接口,负责从 Dataset
生成图表。
GanttChart::stroke
方法期望一个唯一的 Dataset
对象作为其参数。
如果您想在另一个媒介上展示图表,如网页或图片,您需要实现您自己的接口。
<?php use Bakame\Period\Visualizer\Dataset; use Bakame\Period\Visualizer\GanttChart; use League\Period\Period; $graph = new GanttChart(); $graph->stroke(new Dataset([ ['first', new Period('2018-01-01 08:00:00', '2018-01-01 12:00:00')], ['last', new Period('2018-01-01 10:00:00', '2018-01-01 14:00:00')], ]));
结果
first [---------------------------) last [------------------------------)
自定义图表外观
GanttChart
类可以通过提供 GanttChartConfig
来自定义,该配置定义了
- 输出媒介通过实现
OutputWriter
类。 - 图表设置。(如何绘制间隔)
- 设置图表宽度
- 设置图表颜色
- 设置标签与行之间的间隔
- 设置标签对齐方式
- 输出设置(如何创建间隔)
- 设置单个字符表示边界类型
- 设置单个字符表示主体和空格
您可以使用像 League CLImate
或 Symfony Console
这样的库轻松地创建一个实现 OutputWriter
类。如果没有,该包附带了最小化的 ConsoleOutput
类,如果未提供自己的实现,则使用该类。
<?php use Bakame\Period\Visualizer\AffixLabel; use Bakame\Period\Visualizer\ConsoleOutput; use Bakame\Period\Visualizer\Dataset; use Bakame\Period\Visualizer\DecimalNumber; use Bakame\Period\Visualizer\GanttChart; use Bakame\Period\Visualizer\GanttChartConfig; use Bakame\Period\Visualizer\ReverseLabel; use Bakame\Period\Visualizer\RomanNumber; use League\Period\Datepoint; use League\Period\Period; use League\Period\Sequence; $config = GanttChartConfig::createFromRainbow() ->withOutput(new ConsoleOutput(STDOUT)) ->withStartExcluded('🍕') ->withStartIncluded('🍅') ->withEndExcluded('🎾') ->withEndIncluded('🍔') ->withWidth(30) ->withSpace('💩') ->withBody('😊') ->withGapSize(2) ->withLeftMarginSize(1) ->withLabelAlign(GanttChartConfig::ALIGN_RIGHT) ; $labelGenerator = new DecimalNumber(42); $labelGenerator = new RomanNumber($labelGenerator, RomanNumber::UPPER); $labelGenerator = new AffixLabel($labelGenerator, '', '.'); $labelGenerator = new ReverseLabel($labelGenerator); $sequence = new Sequence( Datepoint::create('2018-11-29')->getYear(Period::EXCLUDE_START_INCLUDE_END), Datepoint::create('2018-05-29')->getMonth()->expand('3 MONTH'), Datepoint::create('2017-01-13')->getQuarter(Period::EXCLUDE_ALL), Period::around('2016-06-01', '3 MONTHS', Period::INCLUDE_ALL) ); $dataset = Dataset::fromSequence($sequence, $labelGenerator); $dataset->append($labelGenerator->format('gaps'), $sequence->gaps()); $graph = new GanttChart($config); $graph->stroke($dataset);
结果
XLV. 💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩🍕😊😊😊😊😊😊😊😊😊🍔 XLIV. 💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩🍅😊😊😊😊😊🎾💩💩💩 XLIII. 💩💩💩💩💩💩💩💩🍕😊😊🎾💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩 XLII. 🍅😊😊😊😊🍔💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩 GAPS. 💩💩💩💩💩🍕😊😊🍔💩💩🍅😊😊😊😊😊😊😊🍔💩💩💩💩💩💩💩💩💩💩
在符合 POSIX 的控制台上,所有行都有不同的颜色
GanttChartConfig
类公开了以下额外的常量和方法
<?php const GanttChartConfig::ALIGN_LEFT = 1; const GanttChartConfig::ALIGN_RIGHT = 0; const GanttChartConfig::ALIGN_CENTER = 2; public function GanttChartConfig::__construct(OutputWriter $output); public function GanttChartConfig::output(): OutputWriter; //Returns the OutputWriter instance. public function GanttChartConfig::startExcluded(): string; //Retrieves the excluded start block character. public function GanttChartConfig::startIncluded(): string; //Retrieves the included start block character. public function GanttChartConfig::endExcluded(): string; //Retrieves the excluded end block character. public function GanttChartConfig::endIncluded(): string; //Retrieves the included end block character. public function GanttChartConfig::width(): int; //Retrieves the max size width. public function GanttChartConfig::body(): string; //Retrieves the body block character. public function GanttChartConfig::space(): string; //Retrieves the space block character. public function GanttChartConfig::colors(): string[]; //The selected colors for each row. public function GanttChartConfig::gapSize(): int; //Retrieves the gap sequence between the label and the line. public function GanttChartConfig::labelAlign(): int; //Returns how label should be aligned. public function GanttChartConfig::leftMarginSize(): int; //Retrieves the margin between the label and the console left side.
GanttChartConfig
是不可变的,修改其属性将返回一个具有更新值的新的实例。
变更日志
请参阅 CHANGELOG 了解最近更改的详细信息。
贡献
欢迎贡献,并将得到充分认可。请参阅 CONTRIBUTING 了解详细信息。
测试
该库有一个
- 一个 PHPUnit 测试套件
- 一个使用 PHP CS Fixer 的编码风格合规性测试套件。
- 一个使用 PHPStan 的代码分析合规性测试套件。
要运行测试,请从项目文件夹运行以下命令。
$ composer test
安全
如果您发现任何安全相关的问题,请通过电子邮件 nyamsprod@gmail.com 而不是使用问题跟踪器。
鸣谢
许可证
MIT 许可证(MIT)。请参阅许可证文件以获取更多信息。