diff --git a/composer.json b/composer.json index 843032f..8ad8e51 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" } } 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); +``` diff --git a/src/PeriodActions.php b/src/PeriodActions.php index 59994ed..72d4086 100644 --- a/src/PeriodActions.php +++ b/src/PeriodActions.php @@ -8,49 +8,45 @@ 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 DEFAULT_TIME_UNIT_DURATION = 1; + public function forLastMonth(): static { - $start = $this->now->copy()->subMonth(); - $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_MONTH); } public function forLastYear(): static { - $start = $this->now->copy()->subYear(); - $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_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(); + $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); + } + 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;