ToolInfo.php 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122
  1. <?php
  2. declare(strict_types=1);
  3. /*
  4. * This file is part of PHP CS Fixer.
  5. *
  6. * (c) Fabien Potencier <fabien@symfony.com>
  7. * Dariusz Rumiński <dariusz.ruminski@gmail.com>
  8. *
  9. * This source file is subject to the MIT license that is bundled
  10. * with this source code in the file LICENSE.
  11. */
  12. namespace PhpCsFixer;
  13. use PhpCsFixer\Console\Application;
  14. /**
  15. * Obtain information about using version of tool.
  16. *
  17. * @author Dariusz Rumiński <dariusz.ruminski@gmail.com>
  18. *
  19. * @internal
  20. */
  21. final class ToolInfo implements ToolInfoInterface
  22. {
  23. public const COMPOSER_PACKAGE_NAME = 'friendsofphp/php-cs-fixer';
  24. public const COMPOSER_LEGACY_PACKAGE_NAME = 'fabpot/php-cs-fixer';
  25. /**
  26. * @var null|array{name: string, version: string, dist: array{reference?: string}}
  27. */
  28. private $composerInstallationDetails;
  29. /**
  30. * @var null|bool
  31. */
  32. private $isInstalledByComposer;
  33. public function getComposerInstallationDetails(): array
  34. {
  35. if (!$this->isInstalledByComposer()) {
  36. throw new \LogicException('Cannot get composer version for tool not installed by composer.');
  37. }
  38. if (null === $this->composerInstallationDetails) {
  39. $composerInstalled = json_decode(file_get_contents($this->getComposerInstalledFile()), true, 512, JSON_THROW_ON_ERROR);
  40. $packages = $composerInstalled['packages'] ?? $composerInstalled;
  41. foreach ($packages as $package) {
  42. if (\in_array($package['name'], [self::COMPOSER_PACKAGE_NAME, self::COMPOSER_LEGACY_PACKAGE_NAME], true)) {
  43. $this->composerInstallationDetails = $package;
  44. break;
  45. }
  46. }
  47. }
  48. return $this->composerInstallationDetails;
  49. }
  50. public function getComposerVersion(): string
  51. {
  52. $package = $this->getComposerInstallationDetails();
  53. $versionSuffix = '';
  54. if (isset($package['dist']['reference'])) {
  55. $versionSuffix = '#'.$package['dist']['reference'];
  56. }
  57. return $package['version'].$versionSuffix;
  58. }
  59. public function getVersion(): string
  60. {
  61. if ($this->isInstalledByComposer()) {
  62. return Application::VERSION.':'.$this->getComposerVersion();
  63. }
  64. return Application::VERSION;
  65. }
  66. public function isInstalledAsPhar(): bool
  67. {
  68. return str_starts_with(__DIR__, 'phar://');
  69. }
  70. public function isInstalledByComposer(): bool
  71. {
  72. if (null === $this->isInstalledByComposer) {
  73. $this->isInstalledByComposer = !$this->isInstalledAsPhar() && file_exists($this->getComposerInstalledFile());
  74. }
  75. return $this->isInstalledByComposer;
  76. }
  77. /**
  78. * Determines if the tool is run inside our pre-built Docker image.
  79. * The `/fixer/` path comes from our Dockerfile, tool is installed there and added to global PATH via symlinked binary.
  80. */
  81. public function isRunInsideDocker(): bool
  82. {
  83. return is_file('/.dockerenv') && str_starts_with(__FILE__, '/fixer/');
  84. }
  85. public function getPharDownloadUri(string $version): string
  86. {
  87. return sprintf(
  88. 'https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/releases/download/%s/php-cs-fixer.phar',
  89. $version
  90. );
  91. }
  92. private function getComposerInstalledFile(): string
  93. {
  94. return __DIR__.'/../../../composer/installed.json';
  95. }
  96. }