ComposerService::extractPsr4Paths()   A
last analyzed

Complexity

Conditions 5
Paths 8

Size

Total Lines 21
Code Lines 14

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 14
c 1
b 0
f 0
dl 0
loc 21
rs 9.4888
cc 5
nc 8
nop 2
1
<?php
2
3
/**
4
 * webtrees-mod-translationtool: MyArtJaub Translation Tool Module for webtrees
5
 *
6
 * @package MyArtJaub\Webtrees\Module
7
 * @subpackage TranslationTool
8
 * @author Jonathan Jaubart <[email protected]>
9
 * @copyright Copyright (c) 2020-2023, Jonathan Jaubart
10
 * @license http://www.gnu.org/licenses/gpl.html GNU General Public License, version 3
11
 */
12
13
declare(strict_types=1);
14
15
namespace MyArtJaub\Webtrees\Module\TranslationTool\Services;
16
17
use Composer\Composer;
18
use Composer\Factory;
19
use Composer\IO\NullIO;
20
use Composer\Package\PackageInterface;
21
use Fisharebest\Webtrees\FlashMessages;
22
use Fisharebest\Webtrees\I18N;
23
use Fisharebest\Webtrees\Webtrees;
24
use Exception;
25
26
/**
27
 * Service for accessing Composer data for the root package
28
 */
29
class ComposerService
30
{
31
    /**
32
     * Checks whether a Composer package is a MyArtJaub one.
33
     *
34
     * @param PackageInterface $package
35
     * @return bool
36
     */
37
    public function isMyArtJaubPackage(PackageInterface $package): bool
38
    {
39
        list($vendor) = explode('/', $package->getName(), 2);
40
        return $vendor == self::MYARTJAUB_VENDOR;
41
    }
42
43
    /**
44
     * Name of the MyArtJaub modules' vendor
45
     * @var string MYARTJAUB_VENDOR
46
     * */
47
    private const MYARTJAUB_VENDOR = 'jon48';
48
49
    /**
50
     * List all the PSR-4 paths used in MyArtJaub packages autoloading.
51
     * The returned array is composed of items with the structure:
52
     *      - array [
53
     *              0 => Package Name
54
     *              1 => Array of normalised paths
55
     *          ]
56
     *
57
     * @return array<array<PackageInterface|array<string>>>
58
     */
59
    public function listMyArtJaubPackagesPaths(): array
60
    {
61
        if (getenv('HOME') === false) {
62
            putenv('HOME=' . Webtrees::DATA_DIR);
63
        }
64
65
        $maj_packages = [];
66
        try {
67
            $composer = Factory::create(new NullIO(), Webtrees::ROOT_DIR . 'composer.json');
68
69
            $packages = $composer->getRepositoryManager()
70
                ->getLocalRepository()
71
                ->getPackages();
72
73
            foreach ($packages as $package) {
74
                if ($this->isMyArtJaubPackage($package)) {
75
                    $maj_packages[] = $this->extractPsr4Paths($composer, $package);
76
                }
77
            }
78
        } catch (Exception $ex) {
79
            FlashMessages::addMessage(
80
                I18N::translate('No composer.json file could be loaded, some translations may be missing.') . '<br>' .
81
                I18N::translate('This is expected when not running from a development instance.'),
82
                'warning'
83
            );
84
        }
85
86
        return $maj_packages;
87
    }
88
89
    /**
90
     * Extract and normalise the PSR-4 paths used in a package autoloading.
91
     * The returned array is a 2-tuple with the structure:
92
     *      - array [
93
     *              0 => Package Name
94
     *              1 => Array of normalised paths
95
     *          ]
96
     *
97
     * @param Composer $composer
98
     * @param PackageInterface $package
99
     * @return array<PackageInterface|array<string>>
100
     */
101
    private function extractPsr4Paths(Composer $composer, PackageInterface $package): array
102
    {
103
        $autoload_generator = $composer->getAutoloadGenerator();
104
105
        $package_map = $autoload_generator->buildPackageMap(
106
            $composer->getInstallationManager(),
107
            $composer->getPackage(),
108
            [$package]
109
        );
110
        array_shift($package_map);
111
        $autoloads = count($package_map) == 0 ? ['psr-4' => []] :
112
            $autoload_generator->parseAutoloads($package_map, $composer->getPackage());
113
        $psr4_paths = [];
114
        foreach ($autoloads['psr-4'] as $psr4_ns_paths) {
115
            foreach ($psr4_ns_paths as $psr4_ns_path) {
116
                if (false !== $real_path = realpath($psr4_ns_path)) {
117
                    $psr4_paths[] = $real_path;
118
                }
119
            }
120
        }
121
        return [$package, $psr4_paths];
122
    }
123
}
124