Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
17 / 17
100.00% covered (success)
100.00%
3 / 3
CRAP
100.00% covered (success)
100.00%
1 / 1
Generator
100.00% covered (success)
100.00%
17 / 17
100.00% covered (success)
100.00%
3 / 3
6
100.00% covered (success)
100.00%
1 / 1
 __construct
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 generate
100.00% covered (success)
100.00%
5 / 5
100.00% covered (success)
100.00%
1 / 1
2
 generateContent
100.00% covered (success)
100.00%
11 / 11
100.00% covered (success)
100.00%
1 / 1
3
1<?php
2
3declare(strict_types=1);
4
5/**
6 * Fast Forward Development Tools for PHP projects.
7 *
8 * This file is part of fast-forward/dev-tools project.
9 *
10 * @author   Felipe SayĆ£o Lobato Abreu <github@mentordosnerds.com>
11 * @license  https://opensource.org/licenses/MIT MIT License
12 *
13 * @see      https://github.com/php-fast-forward/
14 * @see      https://github.com/php-fast-forward/dev-tools
15 * @see      https://github.com/php-fast-forward/dev-tools/issues
16 * @see      https://php-fast-forward.github.io/dev-tools/
17 * @see      https://datatracker.ietf.org/doc/html/rfc2119
18 */
19
20namespace FastForward\DevTools\License;
21
22use Throwable;
23use FastForward\DevTools\Composer\Json\ComposerJsonInterface;
24use FastForward\DevTools\Filesystem\FilesystemInterface;
25use Psr\Clock\ClockInterface;
26use Twig\Environment;
27
28/**
29 * Generates LICENSE files from composer.json metadata.
30 *
31 * This class orchestrates the license generation workflow:
32 * 1. Reads metadata from composer.json via Reader
33 * 2. Resolves the license identifier to a template filename
34 * 3. Uses the central Template Engine and VariablesFactory to map out the substitutions
35 * 4. Writes the resulting LICENSE file to the target path
36 *
37 * Generation is skipped if a LICENSE file already exists or if the
38 * license is not supported.
39 */
40  class Generator implements GeneratorInterface
41{
42    /**
43     * Creates a new Generator instance.
44     *
45     * @param ResolverInterface $resolver The resolver for mapping license identifiers to templates
46     * @param ComposerJsonInterface $composer
47     * @param FilesystemInterface $filesystem The filesystem component for file operations
48     * @param ClockInterface $clock
49     * @param Environment $renderer
50     */
51    public function __construct(
52        private ResolverInterface $resolver,
53        private ComposerJsonInterface $composer,
54        private ClockInterface $clock,
55        private Environment $renderer,
56        private FilesystemInterface $filesystem,
57    ) {}
58
59    /**
60     * Generates a LICENSE file at the specified path.
61     *
62     * @param string $targetPath The full path where the LICENSE file should be written
63     *
64     * @return string|null The generated license content, or null if generation failed
65     */
66    public function generate(string $targetPath): ?string
67    {
68        $content = $this->generateContent();
69
70        if (null === $content) {
71            return null;
72        }
73
74        $this->filesystem->dumpFile($targetPath, $content);
75
76        return $content;
77    }
78
79    /**
80     * Generates license content without writing it to disk.
81     *
82     * @return string|null the generated license content, or null if generation failed
83     */
84    public function generateContent(): ?string
85    {
86        $templateFilename = $this->resolver->resolve($this->composer->getLicense());
87
88        if (null === $templateFilename) {
89            return null;
90        }
91
92        try {
93            $content = $this->renderer->render('licenses/' . $templateFilename, [
94                'copyright_holder' => (string) $this->composer->getAuthors(true),
95                'year' => $this->clock->now()
96                    ->format('Y'),
97            ]);
98        } catch (Throwable) {
99            return null;
100        }
101
102        return $content;
103    }
104}