From 419ecd75e5bbdac0c5de1f674a8d9f6286fb0898 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nikola=20Peri=C5=A1i=C4=87?= Date: Wed, 22 Jan 2025 13:49:41 +0100 Subject: [PATCH 1/3] Update readme.md --- readme.md | 58 ++++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 42 insertions(+), 16 deletions(-) diff --git a/readme.md b/readme.md index 0064217..35d2504 100644 --- a/readme.md +++ b/readme.md @@ -8,21 +8,23 @@ What's a heatmap? It is a data visualization technique that shows magnitude of a ![./docs/github.png](./docs/github.png) ### Installation -The Heatmap is distributed as Composer library via Packagist. To add it to your project, just run: -``` +The Heatmap is distributed as Composer library via [Packagist](https://packagist.org/packages/blumilksoftware/heatmap). To add it to your project, execute the following command: + +```bash composer require blumilksoftware/heatmap ``` ### Usage You can use any set of data you want. By default, dates will be taken from `"created_at"` key of arrays or objects implementing `\ArrayAccess` interface. Builder accepts also objects implementing `\Blumilk\HeatmapBuilder\Contracts\TimeGroupable` contract with mandatory `getTimeGroupableIndicator()` method returning a string with proper date: + ```php $data = [ - ["created_at" => "2022-11-01 00:00:00", /** (...) */], - ["created_at" => "2022-11-03 00:00:00", /** (...) */], - ["created_at" => "2022-11-16 00:00:00", /** (...) */], - ["created_at" => "2022-11-16 00:00:00", /** (...) */], - ["created_at" => "2022-11-18 00:00:00", /** (...) */], - ["created_at" => "2022-11-19 00:00:00", /** (...) */], + ["created_at" => "2025-11-01 00:00:00", /** (...) */], + ["created_at" => "2025-11-03 00:00:00", /** (...) */], + ["created_at" => "2025-11-16 00:00:00", /** (...) */], + ["created_at" => "2025-11-16 00:00:00", /** (...) */], + ["created_at" => "2025-11-18 00:00:00", /** (...) */], + ["created_at" => "2025-11-19 00:00:00", /** (...) */], ]; ``` @@ -36,44 +38,68 @@ Method `build()` returns array of tiles that can be serialized into JSON with si ```json [ { - "label": "2022-11-16", + "label": "2025-11-16", "count": 2, "description": "" }, { - "label": "2022-11-17", + "label": "2025-11-17", "count": 0, "description": "" }, { - "label": "2022-11-18", + "label": "2025-11-18", "count": 1, "description": "" }, { - "label": "2022-11-19", + "label": "2025-11-19", "count": 1, "description": "" }, { - "label": "2022-11-20", + "label": "2025-11-20", "count": 0, "description": "" }, { - "label": "2022-11-21", + "label": "2025-11-21", "count": 0, "description": "" }, { - "label": "2022-11-22", + "label": "2025-11-22", "count": 0, "description": "" }, { - "label": "2022-11-23", + "label": "2025-11-23", "count": 0, "description": "" } ] ``` +### Customizing the Heatmap Builder watching period + +By default, the `HeatmapBuilder` automatically sets its observation period to the last seven days if no custom period (`$period`) is provided during instantiation. This default behavior ensures a rolling seven-day view from the current day. + +If you need to specify a custom period (e.g., the entire month of January), you can achieve this by explicitly passing a `CarbonPeriod` instance to the builder, as shown in the example below: + +```php +// Define a custom period for the entire month of January 2025 +$period = CarbonPeriod::create( + Carbon::parse('2025-01-01'), + '1 day', + Carbon::parse('2025-01-31') +); + +// Instantiate the HeatmapBuilder with the custom period +$builder = new HeatmapBuilder( + now: Carbon::now(), + periodInterval: PeriodInterval::Daily, + period: $period // Include the custom period +); + +// Generate the heatmap data +$result = $builder->build($data); +``` From 5613b95216efcbea506ea256f70dabe73bafc726 Mon Sep 17 00:00:00 2001 From: Nikola Date: Wed, 22 Jan 2025 15:20:48 +0100 Subject: [PATCH 2/3] refactor: fix composer script and refactor PeriodActions.php and Tile.php files --- composer.json | 4 +-- src/PeriodActions.php | 57 +++++++++++++++++++++---------------------- src/Tile.php | 2 +- 3 files changed, 31 insertions(+), 32 deletions(-) diff --git a/composer.json b/composer.json index 843032f..dd6616d 100755 --- a/composer.json +++ b/composer.json @@ -29,6 +29,6 @@ "scripts": { "cs": "./vendor/bin/php-cs-fixer fix --dry-run --diff --config codestyle.php", "csf": "./vendor/bin/php-cs-fixer fix --diff --config codestyle.php", - "test": "./vendor/bin/phpunit tests --colors always" + "test": "./vendor/bin/phpunit tests --colors=always" } -} +} \ No newline at end of file diff --git a/src/PeriodActions.php b/src/PeriodActions.php index 59994ed..8bf6df2 100644 --- a/src/PeriodActions.php +++ b/src/PeriodActions.php @@ -8,51 +8,50 @@ trait PeriodActions { - public function forLastMonth(): static + private const UNIT_HOURS = 'hours'; + private const UNIT_DAYS = 'days'; + private const UNIT_WEEKS = 'weeks'; + private const UNIT_MONTH = 'month'; + private const UNIT_YEAR = 'year'; + private const UNIT_DECADE = 'decade'; + private const DEFAULT_TIME_UNIT_DURATION = 1; + + /** + * Generic method to set a period based on the starting point and the duration type. + */ + private function setPeriodFromDuration($duration, string $unit): static { - $start = $this->now->copy()->subMonth(); + $start = $this->now->copy()->sub($duration, $unit); $end = $this->now->copy(); - $this->period = new CarbonPeriod($start, $this->periodInterval->value, $end); return $this; } - public function forLastYear(): static + public function forLastMonth(): static { - $start = $this->now->copy()->subYear(); - $end = $this->now->copy(); - - $this->period = new CarbonPeriod($start, $this->periodInterval->value, $end); + return $this->setPeriodFromDuration(self::DEFAULT_TIME_UNIT_DURATION, self::UNIT_MONTH); + } - return $this; + public function forLastYear(): static + { + return $this->setPeriodFromDuration(self::DEFAULT_TIME_UNIT_DURATION, self::UNIT_YEAR); } public function forLastDecade(): static { - $start = $this->now->copy()->subDecade(); - $end = $this->now->copy(); - - $this->period = new CarbonPeriod($start, $this->periodInterval->value, $end); - - return $this; + return $this->setPeriodFromDuration(self::DEFAULT_TIME_UNIT_DURATION, self::UNIT_DECADE); } public function forNumberOfTiles(int $number): static { - $start = $this->now->copy()->sub( - $number, - match ($this->periodInterval) { - PeriodInterval::Hourly => "hours", - PeriodInterval::Daily => "days", - PeriodInterval::Weekly => "weeks", - PeriodInterval::Monthly => "months", - }, - ); - $end = $this->now->copy(); - - $this->period = new CarbonPeriod($start, $this->periodInterval->value, $end); - - return $this; + $unit = match ($this->periodInterval) { + PeriodInterval::Hourly => self::UNIT_HOURS, + PeriodInterval::Daily => self::UNIT_DAYS, + PeriodInterval::Weekly => self::UNIT_WEEKS, + PeriodInterval::Monthly => self::UNIT_MONTH, + }; + + return $this->setPeriodFromDuration($number, $unit); } } diff --git a/src/Tile.php b/src/Tile.php index c1c116f..5718b16 100644 --- a/src/Tile.php +++ b/src/Tile.php @@ -21,7 +21,7 @@ public function jsonSerialize(): array return [ "label" => $this->label, "count" => $this->count, - "description" => $this->description, + "description" => $this->description ?: null, ]; } } From fbd65932c6e4856407a2cfd9c8835e3012245926 Mon Sep 17 00:00:00 2001 From: Nikola Date: Fri, 7 Mar 2025 14:07:57 +0100 Subject: [PATCH 3/3] chore: resolve PR comments --- composer.json | 2 +- src/PeriodActions.php | 33 +++++++++++++++------------------ src/Tile.php | 2 +- 3 files changed, 17 insertions(+), 20 deletions(-) diff --git a/composer.json b/composer.json index dd6616d..8ad8e51 100755 --- a/composer.json +++ b/composer.json @@ -31,4 +31,4 @@ "csf": "./vendor/bin/php-cs-fixer fix --diff --config codestyle.php", "test": "./vendor/bin/phpunit tests --colors=always" } -} \ No newline at end of file +} diff --git a/src/PeriodActions.php b/src/PeriodActions.php index 8bf6df2..72d4086 100644 --- a/src/PeriodActions.php +++ b/src/PeriodActions.php @@ -8,26 +8,14 @@ trait PeriodActions { - private const UNIT_HOURS = 'hours'; - private const UNIT_DAYS = 'days'; - private const UNIT_WEEKS = 'weeks'; - private const UNIT_MONTH = 'month'; - private const UNIT_YEAR = 'year'; - private const UNIT_DECADE = 'decade'; + private const UNIT_HOURS = "hours"; + private const UNIT_DAYS = "days"; + private const UNIT_WEEKS = "weeks"; + private const UNIT_MONTH = "month"; + private const UNIT_YEAR = "year"; + private const UNIT_DECADE = "decade"; private const DEFAULT_TIME_UNIT_DURATION = 1; - /** - * Generic method to set a period based on the starting point and the duration type. - */ - private function setPeriodFromDuration($duration, string $unit): static - { - $start = $this->now->copy()->sub($duration, $unit); - $end = $this->now->copy(); - $this->period = new CarbonPeriod($start, $this->periodInterval->value, $end); - - return $this; - } - public function forLastMonth(): static { return $this->setPeriodFromDuration(self::DEFAULT_TIME_UNIT_DURATION, self::UNIT_MONTH); @@ -54,4 +42,13 @@ public function forNumberOfTiles(int $number): static return $this->setPeriodFromDuration($number, $unit); } + + protected function setPeriodFromDuration(int $duration, string $unit): static + { + $start = $this->now->copy()->sub($duration, $unit); + $end = $this->now->copy(); + $this->period = new CarbonPeriod($start, $this->periodInterval->value, $end); + + return $this; + } } diff --git a/src/Tile.php b/src/Tile.php index 5718b16..c1c116f 100644 --- a/src/Tile.php +++ b/src/Tile.php @@ -21,7 +21,7 @@ public function jsonSerialize(): array return [ "label" => $this->label, "count" => $this->count, - "description" => $this->description ?: null, + "description" => $this->description, ]; } }