summaryrefslogtreecommitdiff
path: root/vendor/aws/aws-sdk-php/src/Script/Composer/Composer.php
blob: e179fe345939e0227946f623d6fc6e9a6e7de16b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
<?php
namespace Aws\Script\Composer;

use Composer\Script\Event;
use Symfony\Component\Filesystem\Exception\IOException;
use Symfony\Component\Filesystem\Filesystem;

class Composer
{
    public static function removeUnusedServices(
        Event      $event,
        Filesystem $filesystem = null
    )
    {
        $composer = $event->getComposer();
        $extra = $composer->getPackage()->getExtra();
        $listedServices = isset($extra['aws/aws-sdk-php'])
            ? $extra['aws/aws-sdk-php']
            : [];

        if ($listedServices) {
            $serviceMapping = self::buildServiceMapping();
            self::verifyListedServices($serviceMapping, $listedServices);
            $filesystem = $filesystem ?: new Filesystem();
            $vendorPath = $composer->getConfig()->get('vendor-dir');
            self::removeServiceDirs(
                $event,
                $filesystem,
                $serviceMapping,
                $listedServices,
                $vendorPath
            );
        } else {
            throw new \InvalidArgumentException(
                'There are no services listed. Did you intend to use this script?'
            );
        }
    }

    public static function buildServiceMapping()
    {
        $serviceMapping = [];
        $manifest = require(__DIR__ . '/../../data/manifest.json.php');

        foreach ($manifest as $service => $attributes) {
            $serviceMapping[$attributes['namespace']] = $service;
        }

        return $serviceMapping;
    }

    private static function verifyListedServices($serviceMapping, $listedServices)
    {
        foreach ($listedServices as $serviceToKeep) {
            if (!isset($serviceMapping[$serviceToKeep])) {
                throw new \InvalidArgumentException(
                    "'$serviceToKeep' is not a valid AWS service namespace. Please check spelling and casing."
                );
            }
        }
    }

    private static function removeServiceDirs(
        $event,
        $filesystem,
        $serviceMapping,
        $listedServices,
        $vendorPath
    ) {
        $unsafeForDeletion = ['Kms', 'S3', 'SSO', 'SSOOIDC', 'Sts'];
        if (in_array('DynamoDbStreams', $listedServices)) {
            $unsafeForDeletion[] = 'DynamoDb';
        }

        $clientPath = $vendorPath . '/aws/aws-sdk-php/src/';
        $modelPath = $clientPath . 'data/';
        $deleteCount = 0;

        foreach ($serviceMapping as $clientName => $modelName) {
            if (!in_array($clientName, $listedServices) &&
                !in_array($clientName, $unsafeForDeletion)
            ) {
                $clientDir = $clientPath . $clientName;
                $modelDir = $modelPath . $modelName;

                if ($filesystem->exists([$clientDir, $modelDir])) {
                    $attempts = 3;
                    $delay = 2;

                    while ($attempts) {
                        try {
                            $filesystem->remove([$clientDir, $modelDir]);
                            $deleteCount++;
                            break;
                        } catch (IOException $e) {
                            $attempts--;

                            if (!$attempts) {
                                throw new IOException(
                                    "Removal failed after several attempts. Last error: " . $e->getMessage()
                                );
                            } else {
                                sleep($delay);
                                $event->getIO()->write(
                                    "Error encountered: " . $e->getMessage() . ". Retrying..."
                                );
                                $delay += 2;
                            }
                    }
                }

                }
            }
        }
        $event->getIO()->write(
            "Removed $deleteCount AWS service" . ($deleteCount === 1 ? '' : 's')
        );
    }
}