Skip to content

Commit 63971a5

Browse files
authored
Merge pull request #26 from php-fast-forward/feature/11-license-generation
Fix PHPDocs
2 parents 3003cbe + b0ee260 commit 63971a5

10 files changed

+205
-44
lines changed

src/License/Generator.php

Lines changed: 27 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -20,14 +20,29 @@
2020

2121
use Symfony\Component\Filesystem\Filesystem;
2222

23+
/**
24+
* Generates LICENSE files from composer.json metadata.
25+
*
26+
* This class orchestrates the license generation workflow:
27+
* 1. Reads metadata from composer.json via Reader
28+
* 2. Resolves the license identifier to a template filename
29+
* 3. Loads the license template content
30+
* 4. Resolves placeholders with metadata (year, author, project, organization)
31+
* 5. Writes the resulting LICENSE file to the target path
32+
*
33+
* Generation is skipped if a LICENSE file already exists or if the
34+
* license is not supported.
35+
*/
2336
final readonly class Generator implements GeneratorInterface
2437
{
2538
/**
26-
* @param Reader $reader
27-
* @param Resolver $resolver
28-
* @param TemplateLoader $templateLoader
29-
* @param PlaceholderResolver $placeholderResolver
30-
* @param Filesystem $filesystem
39+
* Creates a new Generator instance.
40+
*
41+
* @param Reader $reader The reader for extracting metadata from composer.json
42+
* @param Resolver $resolver The resolver for mapping license identifiers to templates
43+
* @param TemplateLoader $templateLoader The loader for reading template files
44+
* @param PlaceholderResolver $placeholderResolver The resolver for template placeholders
45+
* @param Filesystem $filesystem The filesystem component for file operations
3146
*/
3247
public function __construct(
3348
private Reader $reader,
@@ -38,9 +53,11 @@ public function __construct(
3853
) {}
3954

4055
/**
41-
* @param string $targetPath
56+
* Generates a LICENSE file at the specified path.
57+
*
58+
* @param string $targetPath The full path where the LICENSE file should be written
4259
*
43-
* @return string|null
60+
* @return string|null The generated license content, or null if generation failed
4461
*/
4562
public function generate(string $targetPath): ?string
4663
{
@@ -84,7 +101,9 @@ public function generate(string $targetPath): ?string
84101
}
85102

86103
/**
87-
* @return bool
104+
* Checks whether a supported license is present in composer.json.
105+
*
106+
* @return bool True if a supported license is defined, false otherwise
88107
*/
89108
public function hasLicense(): bool
90109
{

src/License/GeneratorInterface.php

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,17 +18,31 @@
1818

1919
namespace FastForward\DevTools\License;
2020

21+
/**
22+
* Generates LICENSE files from composer.json metadata.
23+
*
24+
* This interface defines the contract for generating license files
25+
* by reading composer.json and producing appropriate license content.
26+
*/
2127
interface GeneratorInterface
2228
{
2329
/**
24-
* @param string $targetPath
30+
* Generates a LICENSE file at the specified path.
2531
*
26-
* @return string|null
32+
* Reads the license from composer.json, validates it's supported,
33+
* loads the appropriate template, resolves placeholders, and writes
34+
* the LICENSE file to the target path.
35+
*
36+
* @param string $targetPath The full path where the LICENSE file should be written
37+
*
38+
* @return string|null The generated license content, or null if generation failed
2739
*/
2840
public function generate(string $targetPath): ?string;
2941

3042
/**
31-
* @return bool
43+
* Checks whether a supported license is present in composer.json.
44+
*
45+
* @return bool True if a supported license is defined, false otherwise
3246
*/
3347
public function hasLicense(): bool;
3448
}

src/License/PlaceholderResolver.php

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,31 @@
2020

2121
use function Safe\preg_replace;
2222

23+
/**
24+
* Resolves placeholders in license templates with metadata values.
25+
*
26+
* This class replaces placeholders like {{ year }}, {{ author }}, {{ project }},
27+
* {{ organization }}, and {{ copyright_holder }} with values from metadata.
28+
* Unresolved placeholders are removed and excess newlines are normalized.
29+
*/
2330
final class PlaceholderResolver implements PlaceholderResolverInterface
2431
{
2532
/**
26-
* @param array{year?: int, organization?: string, author?: string, project?: string} $metadata
27-
* @param string $template
33+
* Resolves placeholders in a license template with the provided metadata.
34+
*
35+
* Supported placeholders:
36+
* - {{ year }} - The copyright year (defaults to current year)
37+
* - {{ organization }} - The organization or vendor name
38+
* - {{ author }} - The primary author name or email
39+
* - {{ project }} - The project/package name
40+
* - {{ copyright_holder }} - Organization or author (organization takes precedence)
41+
*
42+
* Unmatched placeholders are removed, and consecutive blank lines are normalized.
43+
*
44+
* @param string $template The license template content with placeholders
45+
* @param array{year?: int, organization?: string, author?: string, project?: string} $metadata The metadata values to use for replacement
46+
*
47+
* @return string The template with all resolved placeholders
2848
*/
2949
public function resolve(string $template, array $metadata): string
3050
{

src/License/PlaceholderResolverInterface.php

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,21 @@
1818

1919
namespace FastForward\DevTools\License;
2020

21+
/**
22+
* Resolves placeholders in license templates with metadata values.
23+
*
24+
* This interface defines the contract for replacing template placeholders
25+
* such as [year], [author], [project] with actual values.
26+
*/
2127
interface PlaceholderResolverInterface
2228
{
2329
/**
24-
* @param string $template
25-
* @param array{year?: int, organization?: string, author?: string, project?: string} $metadata
30+
* Resolves placeholders in a license template with the provided metadata.
31+
*
32+
* @param string $template The license template content with placeholders
33+
* @param array{year?: int, organization?: string, author?: string, project?: string} $metadata The metadata values to use for replacement
34+
*
35+
* @return string The template with all resolved placeholders
2636
*/
2737
public function resolve(string $template, array $metadata): string;
2838
}

src/License/Reader.php

Lines changed: 47 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -23,22 +23,35 @@
2323

2424
use function Safe\json_decode;
2525

26+
/**
27+
* Reads composer.json and exposes metadata for license generation.
28+
*
29+
* This class parses a composer.json file via SplFileObject and provides
30+
* methods to extract license information, package name, authors, vendor,
31+
* and the current year for copyright notices.
32+
*/
2633
final readonly class Reader implements ReaderInterface
2734
{
2835
private array $data;
2936

3037
/**
38+
* Creates a new Reader instance.
39+
*
3140
* @param SplFileObject $source The source file to read from, typically composer.json
41+
*
42+
* @throws JsonException if the JSON content is invalid
3243
*/
3344
public function __construct(SplFileObject $source)
3445
{
3546
$this->data = $this->readData($source);
3647
}
3748

3849
/**
39-
* @param SplFileObject $source The source file to read from, typically composer.json
50+
* Reads and parses the JSON content from the source file.
51+
*
52+
* @param SplFileObject $source The source file to read from
4053
*
41-
* @return array
54+
* @return array The parsed JSON data as an associative array
4255
*
4356
* @throws JsonException if the JSON is invalid
4457
*/
@@ -50,7 +63,13 @@ private function readData(SplFileObject $source): array
5063
}
5164

5265
/**
53-
* @return string|null
66+
* Retrieves the license identifier from composer.json.
67+
*
68+
* If the license is a single string, returns it directly.
69+
* If it's an array with one element, extracts that element.
70+
* Returns null if no license is set or if multiple licenses are specified.
71+
*
72+
* @return string|null the license string, or null if not set or unsupported
5473
*/
5574
public function getLicense(): ?string
5675
{
@@ -64,15 +83,22 @@ public function getLicense(): ?string
6483
}
6584

6685
/**
67-
* @return string
86+
* Retrieves the package name from composer.json.
87+
*
88+
* @return string the full package name (vendor/package), or empty string if not set
6889
*/
6990
public function getPackageName(): string
7091
{
7192
return $this->data['name'] ?? '';
7293
}
7394

7495
/**
75-
* @return array
96+
* Retrieves the list of authors from composer.json.
97+
*
98+
* Each author is normalized to include name, email, homepage, and role fields.
99+
* Returns an empty array if no authors are defined.
100+
*
101+
* @return array<int, array{name: string, email: string, homepage: string, role: string}>
76102
*/
77103
public function getAuthors(): array
78104
{
@@ -94,7 +120,12 @@ public function getAuthors(): array
94120
}
95121

96122
/**
97-
* @return string|null
123+
* Extracts the vendor name from the package name.
124+
*
125+
* The package name is expected in vendor/package format.
126+
* Returns null if no package name is set or if the package has no vendor prefix.
127+
*
128+
* @return string|null the vendor name, or null if package has no vendor prefix
98129
*/
99130
public function getVendor(): ?string
100131
{
@@ -114,17 +145,24 @@ public function getVendor(): ?string
114145
}
115146

116147
/**
117-
* @return int
148+
* Returns the current year for copyright notices.
149+
*
150+
* @return int the current year as an integer
118151
*/
119152
public function getYear(): int
120153
{
121154
return (int) date('Y');
122155
}
123156

124157
/**
125-
* @param array $license
158+
* Extracts a single license from an array of licenses.
159+
*
160+
* Returns the first license if exactly one element exists.
161+
* Returns null if the array is empty or contains multiple licenses.
162+
*
163+
* @param array<string> $license The license array to extract from
126164
*
127-
* @return string|null
165+
* @return string|null a single license string, or null if extraction is not possible
128166
*/
129167
private function extractLicense(array $license): ?string
130168
{

src/License/ReaderInterface.php

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,30 +18,46 @@
1818

1919
namespace FastForward\DevTools\License;
2020

21+
/**
22+
* Reads and exposes metadata from composer.json for license generation.
23+
*
24+
* This interface provides access to license information, package name,
25+
* authors, vendor, and year data extracted from a project's composer.json.
26+
*/
2127
interface ReaderInterface
2228
{
2329
/**
24-
* @return string|null
30+
* Retrieves the license identifier from composer.json.
31+
*
32+
* @return string|null the license string, or null if not set or unsupported
2533
*/
2634
public function getLicense(): ?string;
2735

2836
/**
29-
* @return string
37+
* Retrieves the package name from composer.json.
38+
*
39+
* @return string the full package name (vendor/package)
3040
*/
3141
public function getPackageName(): string;
3242

3343
/**
44+
* Retrieves the list of authors from composer.json.
45+
*
3446
* @return array<int, array{name: string, email: string, homepage: string, role: string}>
3547
*/
3648
public function getAuthors(): array;
3749

3850
/**
39-
* @return string|null
51+
* Extracts the vendor name from the package name.
52+
*
53+
* @return string|null the vendor name, or null if package has no vendor prefix
4054
*/
4155
public function getVendor(): ?string;
4256

4357
/**
44-
* @return int
58+
* Returns the current year for copyright notices.
59+
*
60+
* @return int the current year as an integer
4561
*/
4662
public function getYear(): int;
4763
}

src/License/Resolver.php

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,12 @@
1818

1919
namespace FastForward\DevTools\License;
2020

21+
/**
22+
* Resolves license identifiers to their corresponding template filenames.
23+
*
24+
* This class maintains a mapping of supported open-source licenses to their
25+
* template files and provides methods to check support and resolve licenses.
26+
*/
2127
final class Resolver implements ResolverInterface
2228
{
2329
private const array SUPPORTED_LICENSES = [
@@ -38,19 +44,25 @@ final class Resolver implements ResolverInterface
3844
];
3945

4046
/**
41-
* @param string $license
47+
* Checks whether the given license identifier is supported.
48+
*
49+
* The check is case-insensitive and handles common license variants.
4250
*
43-
* @return bool
51+
* @param string $license The license identifier to check
52+
*
53+
* @return bool True if the license is supported, false otherwise
4454
*/
4555
public function isSupported(string $license): bool
4656
{
4757
return isset(self::SUPPORTED_LICENSES[$this->normalize($license)]);
4858
}
4959

5060
/**
51-
* @param string $license
61+
* Resolves a license identifier to its template filename.
62+
*
63+
* @param string $license The license identifier to resolve
5264
*
53-
* @return string|null
65+
* @return string|null The template filename if supported, or null if not
5466
*/
5567
public function resolve(string $license): ?string
5668
{
@@ -64,9 +76,11 @@ public function resolve(string $license): ?string
6476
}
6577

6678
/**
67-
* @param string $license
79+
* Normalizes the license identifier for comparison.
80+
*
81+
* @param string $license The license identifier to normalize
6882
*
69-
* @return string
83+
* @return string The normalized license string
7084
*/
7185
private function normalize(string $license): string
7286
{

0 commit comments

Comments
 (0)