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;
27use Twig\Markup;
28
29/**
30 * Generates LICENSE files from composer.json metadata.
31 *
32 * This class orchestrates the license generation workflow:
33 * 1. Reads metadata from composer.json via Reader
34 * 2. Resolves the license identifier to a template filename
35 * 3. Uses the central Template Engine and VariablesFactory to map out the substitutions
36 * 4. Writes the resulting LICENSE file to the target path
37 *
38 * Generation is skipped if a LICENSE file already exists or if the
39 * license is not supported.
40 */
41  class Generator implements GeneratorInterface
42{
43    /**
44     * Creates a new Generator instance.
45     *
46     * @param ResolverInterface $resolver The resolver for mapping license identifiers to templates
47     * @param ComposerJsonInterface $composer
48     * @param FilesystemInterface $filesystem The filesystem component for file operations
49     * @param ClockInterface $clock
50     * @param Environment $renderer
51     */
52    public function __construct(
53        private ResolverInterface $resolver,
54        private ComposerJsonInterface $composer,
55        private ClockInterface $clock,
56        private Environment $renderer,
57        private FilesystemInterface $filesystem,
58    ) {}
59
60    /**
61     * Generates a LICENSE file at the specified path.
62     *
63     * @param string $targetPath The full path where the LICENSE file should be written
64     *
65     * @return string|null The generated license content, or null if generation failed
66     */
67    public function generate(string $targetPath): ?string
68    {
69        $content = $this->generateContent();
70
71        if (null === $content) {
72            return null;
73        }
74
75        $this->filesystem->dumpFile($targetPath, $content);
76
77        return $content;
78    }
79
80    /**
81     * Generates license content without writing it to disk.
82     *
83     * @return string|null the generated license content, or null if generation failed
84     */
85    public function generateContent(): ?string
86    {
87        $templateFilename = $this->resolver->resolve($this->composer->getLicense());
88
89        if (null === $templateFilename) {
90            return null;
91        }
92
93        try {
94            $content = $this->renderer->render('licenses/' . $templateFilename, [
95                'copyright_holder' => new Markup((string) $this->composer->getAuthors(true), 'UTF-8'),
96                'year' => $this->clock->now()
97                    ->format('Y'),
98            ]);
99        } catch (Throwable) {
100            return null;
101        }
102
103        return $content;
104    }
105}