1 | <?php |
||
2 | |||
3 | namespace Sfneal\Helpers\Laravel\Support; |
||
4 | |||
5 | use ErrorException; |
||
6 | use Illuminate\Support\Facades\Cache; |
||
7 | |||
8 | class Changelog |
||
9 | { |
||
10 | // todo: add ability to replace package names (user/package) with github links |
||
11 | |||
12 | /** |
||
13 | * @var string |
||
14 | */ |
||
15 | private $path; |
||
16 | |||
17 | /** |
||
18 | * Changelog constructor. |
||
19 | * |
||
20 | * @param string|null $path |
||
21 | */ |
||
22 | public function __construct(string $path = null) |
||
23 | { |
||
24 | $this->path = $path ?? config('app-info.changelog_path'); |
||
25 | } |
||
26 | |||
27 | /** |
||
28 | * Read the application's changelog & return an array of changes. |
||
29 | * |
||
30 | * @return array |
||
31 | */ |
||
32 | public function changelog(): array |
||
33 | { |
||
34 | return Cache::rememberForever((new CacheKey("changelog:$this->path", 'changelog'))->execute(), function () { |
||
35 | // Read the changelog |
||
36 | $file_lines = file($this->path); |
||
37 | $changes = []; |
||
38 | |||
39 | for ($row = 0; $row < count($file_lines); $row++) { |
||
0 ignored issues
–
show
|
|||
40 | // Check if line starts with 'version' |
||
41 | if (substr(strtolower($file_lines[$row]), 0, strlen('version')) == 'version') { |
||
42 | $version_date = explode(', ', $file_lines[$row]); |
||
43 | |||
44 | // Extract version and date |
||
45 | $date = $version_date[1]; |
||
46 | $version = explode(' ', $version_date[0])[1]; |
||
47 | $changes[$version] = ['date' => trim($date), 'changes' => []]; |
||
48 | |||
49 | // Skip ahead two lines to skip sep line |
||
50 | $row += 2; |
||
51 | |||
52 | // Keep iterating over rows until we get to a blank line |
||
53 | while ($row < count($file_lines) && strlen(trim($file_lines[$row])) > 1) { |
||
54 | if (substr(trim($file_lines[$row]), 0, 1) == '-') { |
||
55 | $changes[$version]['changes'][] = str_replace('- ', '', trim($file_lines[$row])); |
||
56 | $row++; |
||
57 | } else { |
||
58 | break; |
||
59 | } |
||
60 | } |
||
61 | } |
||
62 | } |
||
63 | |||
64 | return $changes; |
||
65 | }); |
||
66 | } |
||
67 | |||
68 | /** |
||
69 | * Retrieve an array of changes made to a particular application version. |
||
70 | * |
||
71 | * @param string|null $version |
||
72 | * @return array|null |
||
73 | */ |
||
74 | public function versionChanges(string $version): ?array |
||
75 | { |
||
76 | return Cache::rememberForever( |
||
77 | // Cache key |
||
78 | (new CacheKey("changelog:$this->path", $version))->execute(), |
||
79 | |||
80 | // Value to cache |
||
81 | function () use ($version) { |
||
82 | try { |
||
83 | return $this->changelog()[$version]; |
||
84 | } catch (ErrorException $exception) { |
||
85 | return null; |
||
86 | } |
||
87 | } |
||
88 | ); |
||
89 | } |
||
90 | |||
91 | /** |
||
92 | * Retrieve an array of the version history. |
||
93 | * |
||
94 | * - optionally include the release date in the array values |
||
95 | * |
||
96 | * @param bool $releaseDates |
||
97 | * @return array |
||
98 | */ |
||
99 | public function versions(bool $releaseDates = false): array |
||
100 | { |
||
101 | // Flat array of versions |
||
102 | $versions = array_keys($this->changelog()); |
||
103 | |||
104 | // Return an array of version keys & release date values |
||
105 | if ($releaseDates) { |
||
106 | // todo: optimize this |
||
107 | return array_combine( |
||
108 | $versions, |
||
109 | array_map( |
||
110 | function ($array) { |
||
111 | return $array['date']; |
||
112 | }, |
||
113 | array_values($this->changelog()) |
||
114 | ) |
||
115 | ); |
||
116 | } |
||
117 | |||
118 | // Return a array of versions |
||
119 | else { |
||
120 | return $versions; |
||
121 | } |
||
122 | } |
||
123 | } |
||
124 |
If the size of the collection does not change during the iteration, it is generally a good practice to compute it beforehand, and not on each iteration: