← All changes
|
app/Http/Endpoints/Responses/DistributionResponse.php
+152
-0
2.0.1
→
2.1.1
View file →
| @@ -1,0 +1,152 @@ | ||
| 1 | +<?php | |
| 2 | + | |
| 3 | +declare(strict_types=1); | |
| 4 | + | |
| 5 | +namespace Metricool\Http\Endpoints\Responses; | |
| 6 | + | |
| 7 | +use Metricool\Support\Builders\StatsChartTableBuilder; | |
| 8 | +use Metricool\Support\Helpers\Collection; | |
| 9 | +use Metricool\Http\Metricool\DTOs\DistributionDTO; | |
| 10 | + | |
| 11 | +/** | |
| 12 | + * A DistributionResponse shows Table and Chart data. The TableData | |
| 13 | + * will have a percentage of the total distribution of the metric. The result | |
| 14 | + * in the Chart holds the values to be used inside the Chart | |
| 15 | + * | |
| 16 | + * These Responses are dynamically created from endpoints/DistributionEndpoint. | |
| 17 | + * @see \Metricool\Http\Endpoints\DistributionEndpoint | |
| 18 | + */ | |
| 19 | +abstract class DistributionResponse extends Response | |
| 20 | +{ | |
| 21 | + /** | |
| 22 | + * A collection of DistributionDTO's that holds the statistics of the | |
| 23 | + * Metricool\Http\Metricool\Entities\DistributionStatistics Entity. | |
| 24 | + * @var Collection|DistributionDTO[] | |
| 25 | + */ | |
| 26 | + protected Collection $statistics; | |
| 27 | + | |
| 28 | + public string $sort = 'percentage'; | |
| 29 | + public string $order = 'desc'; | |
| 30 | + public string $sum = 'amount'; | |
| 31 | + | |
| 32 | + public function __construct(Collection $statistics) | |
| 33 | + { | |
| 34 | + $this->statistics = $statistics; | |
| 35 | + } | |
| 36 | + | |
| 37 | + /** | |
| 38 | + * @param string $sort The column to sort the results on | |
| 39 | + */ | |
| 40 | + public function setSort(string $sort): self | |
| 41 | + { | |
| 42 | + $this->sort = $sort; | |
| 43 | + | |
| 44 | + return $this; | |
| 45 | + } | |
| 46 | + | |
| 47 | + /** | |
| 48 | + * @param string $order Sets the ordering. asc for ascending, desc for descending | |
| 49 | + */ | |
| 50 | + public function setOrder(string $order): self | |
| 51 | + { | |
| 52 | + $this->order = $order; | |
| 53 | + | |
| 54 | + return $this; | |
| 55 | + } | |
| 56 | + | |
| 57 | + /** | |
| 58 | + * @param string $column The column to calculate the total distribution from | |
| 59 | + */ | |
| 60 | + public function setSum(string $column): self | |
| 61 | + { | |
| 62 | + $this->sum = $column; | |
| 63 | + | |
| 64 | + return $this; | |
| 65 | + } | |
| 66 | + | |
| 67 | + /** | |
| 68 | + * @inheritDoc | |
| 69 | + */ | |
| 70 | + public function body(): array | |
| 71 | + { | |
| 72 | + $results = $this->parse()->sortBy($this->sort, $this->order === 'desc'); | |
| 73 | + | |
| 74 | + $response = []; | |
| 75 | + $response['tableData'] = $this->createTableData($results); | |
| 76 | + | |
| 77 | + $chartData = $this->createChartData($results); | |
| 78 | + if ($chartData !== null) { | |
| 79 | + // Only add chartData to the response if there is data to be displayed | |
| 80 | + $response['chartData'] = $chartData; | |
| 81 | + } | |
| 82 | + | |
| 83 | + return $response; | |
| 84 | + } | |
| 85 | + | |
| 86 | + /** | |
| 87 | + * Processes results, this calculates distribution percentages on each result | |
| 88 | + * and serializes every item to the requirements of the endpoint | |
| 89 | + * @return Collection|mixed[] Serialized version of the results to be used in the response body | |
| 90 | + */ | |
| 91 | + protected function parse(): Collection | |
| 92 | + { | |
| 93 | + $total = $this->getTotalAmountOfResults(); | |
| 94 | + | |
| 95 | + // parse | |
| 96 | + return $this->statistics->map(function ($statistic) use ($total) { | |
| 97 | + return $this->parseSingleItem($statistic, $total); | |
| 98 | + }); | |
| 99 | + } | |
| 100 | + | |
| 101 | + /** | |
| 102 | + * Calculates the total amount of the results | |
| 103 | + */ | |
| 104 | + protected function getTotalAmountOfResults(): int | |
| 105 | + { | |
| 106 | + return $this->statistics->sum($this->sum); | |
| 107 | + } | |
| 108 | + | |
| 109 | + /** | |
| 110 | + * Gets the table data to be used in the response body | |
| 111 | + */ | |
| 112 | + protected function createTableData(Collection $results): array | |
| 113 | + { | |
| 114 | + return $results->toArray(); | |
| 115 | + } | |
| 116 | + | |
| 117 | + /** | |
| 118 | + * Gets the properties and labels to be used in the chart and | |
| 119 | + * returns the column headers for the chart. Each property is assigned a label. | |
| 120 | + * Example: ['property' => 'label'] | |
| 121 | + * Leave empty to not include the chart data | |
| 122 | + * @see \Metricool\Http\Endpoints\Responses\Statistics\CountriesResponse::getChartColumns() | |
| 123 | + */ | |
| 124 | + protected function getChartColumns(): array | |
| 125 | + { | |
| 126 | + return []; | |
| 127 | + } | |
| 128 | + | |
| 129 | + | |
| 130 | + /** | |
| 131 | + * Gets the chart to be used in response. If the columns are empty, | |
| 132 | + * no chart will be produced | |
| 133 | + */ | |
| 134 | + protected function createChartData(Collection $results): ?array | |
| 135 | + { | |
| 136 | + $columns = $this->getChartColumns(); | |
| 137 | + | |
| 138 | + if (empty($columns)) { | |
| 139 | + return null; | |
| 140 | + } | |
| 141 | + | |
| 142 | + return (new StatsChartTableBuilder())->setColumns($columns) | |
| 143 | + ->setResults($results) | |
| 144 | + ->build(); | |
| 145 | + } | |
| 146 | + | |
| 147 | + /** | |
| 148 | + * Mutate the DistributionDTO to the requirements of the endpoint and | |
| 149 | + * calculates the distribution percentage | |
| 150 | + */ | |
| 151 | + abstract protected function parseSingleItem(DistributionDTO $item, int $total): object; | |
| 152 | +} | |