Composer.php 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131
  1. <?php
  2. namespace Aws\Script\Composer;
  3. use Composer\Script\Event;
  4. use Symfony\Component\Filesystem\Exception\IOException;
  5. use Symfony\Component\Filesystem\Filesystem;
  6. class Composer
  7. {
  8. public static function removeUnusedServicesInDev(Event $event, Filesystem $filesystem = null)
  9. {
  10. self::removeUnusedServicesWithConfig($event, $filesystem, true);
  11. }
  12. public static function removeUnusedServices(Event $event, Filesystem $filesystem = null)
  13. {
  14. self::removeUnusedServicesWithConfig($event, $filesystem, false);
  15. }
  16. private static function removeUnusedServicesWithConfig(Event $event, Filesystem $filesystem = null, $isDev = false)
  17. {
  18. if ($isDev && !$event->isDevMode()){
  19. return;
  20. }
  21. $composer = $event->getComposer();
  22. $extra = $composer->getPackage()->getExtra();
  23. $listedServices = isset($extra['aws/aws-sdk-php'])
  24. ? $extra['aws/aws-sdk-php']
  25. : [];
  26. if ($listedServices) {
  27. $serviceMapping = self::buildServiceMapping();
  28. self::verifyListedServices($serviceMapping, $listedServices);
  29. $filesystem = $filesystem ?: new Filesystem();
  30. $vendorPath = $composer->getConfig()->get('vendor-dir');
  31. self::removeServiceDirs(
  32. $event,
  33. $filesystem,
  34. $serviceMapping,
  35. $listedServices,
  36. $vendorPath
  37. );
  38. } else {
  39. throw new \InvalidArgumentException(
  40. 'There are no services listed. Did you intend to use this script?'
  41. );
  42. }
  43. }
  44. public static function buildServiceMapping()
  45. {
  46. $serviceMapping = [];
  47. $manifest = require(__DIR__ . '/../../data/manifest.json.php');
  48. foreach ($manifest as $service => $attributes) {
  49. $serviceMapping[$attributes['namespace']] = $service;
  50. }
  51. return $serviceMapping;
  52. }
  53. private static function verifyListedServices($serviceMapping, $listedServices)
  54. {
  55. foreach ($listedServices as $serviceToKeep) {
  56. if (!isset($serviceMapping[$serviceToKeep])) {
  57. throw new \InvalidArgumentException(
  58. "'$serviceToKeep' is not a valid AWS service namespace. Please check spelling and casing."
  59. );
  60. }
  61. }
  62. }
  63. private static function removeServiceDirs(
  64. $event,
  65. $filesystem,
  66. $serviceMapping,
  67. $listedServices,
  68. $vendorPath
  69. ) {
  70. $unsafeForDeletion = ['Kms', 'S3', 'SSO', 'SSOOIDC', 'Sts'];
  71. if (in_array('DynamoDbStreams', $listedServices)) {
  72. $unsafeForDeletion[] = 'DynamoDb';
  73. }
  74. $clientPath = $vendorPath . '/aws/aws-sdk-php/src/';
  75. $modelPath = $clientPath . 'data/';
  76. $deleteCount = 0;
  77. foreach ($serviceMapping as $clientName => $modelName) {
  78. if (!in_array($clientName, $listedServices) &&
  79. !in_array($clientName, $unsafeForDeletion)
  80. ) {
  81. $clientDir = $clientPath . $clientName;
  82. $modelDir = $modelPath . $modelName;
  83. if ($filesystem->exists([$clientDir, $modelDir])) {
  84. $attempts = 3;
  85. $delay = 2;
  86. while ($attempts) {
  87. try {
  88. $filesystem->remove([$clientDir, $modelDir]);
  89. $deleteCount++;
  90. break;
  91. } catch (IOException $e) {
  92. $attempts--;
  93. if (!$attempts) {
  94. throw new IOException(
  95. "Removal failed after several attempts. Last error: " . $e->getMessage()
  96. );
  97. } else {
  98. sleep($delay);
  99. $event->getIO()->write(
  100. "Error encountered: " . $e->getMessage() . ". Retrying..."
  101. );
  102. $delay += 2;
  103. }
  104. }
  105. }
  106. }
  107. }
  108. }
  109. $event->getIO()->write(
  110. "Removed $deleteCount AWS service" . ($deleteCount === 1 ? '' : 's')
  111. );
  112. }
  113. }