Util.php 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  1. <?php declare(strict_types=1);
  2. /**
  3. * @license Apache 2.0
  4. */
  5. namespace OpenApi;
  6. use InvalidArgumentException;
  7. use Symfony\Component\Finder\Finder;
  8. /**
  9. * Convenient utility functions that don't neatly fit anywhere else
  10. */
  11. class Util
  12. {
  13. /**
  14. * Turns the given $fullPath into a relative path based on $basePaths, which can either
  15. * be a single string path, or a list of possible paths. If a list is given, the first
  16. * matching basePath in the list will be used to compute the relative path. If no
  17. * relative path could be computed, the original string will be returned because there
  18. * is always a chance it was a valid relative path to begin with.
  19. *
  20. * It should be noted that these are "relative paths" primarily in Finder's sense of them,
  21. * and conform specifically to what is expected by functions like `exclude()` and `notPath()`.
  22. * In particular, leading and trailing slashes are removed.
  23. *
  24. * @param string $fullPath
  25. * @param string|array $basePaths
  26. * @return string
  27. */
  28. public static function getRelativePath($fullPath, $basePaths)
  29. {
  30. $relativePath = null;
  31. if (is_string($basePaths)) { // just a single path, not an array of possible paths
  32. $relativePath = self::removePrefix($fullPath, $basePaths);
  33. } else { // an array of paths
  34. foreach ($basePaths as $basePath) {
  35. $relativePath = self::removePrefix($fullPath, $basePath);
  36. if (!empty($relativePath)) {
  37. break;
  38. }
  39. }
  40. }
  41. return !empty($relativePath) ? trim($relativePath, '/') : $fullPath;
  42. }
  43. /**
  44. * Removes a prefix from the start of a string if it exists, or null otherwise.
  45. *
  46. * @param string $str
  47. * @param string $prefix
  48. * @return null|string
  49. */
  50. private static function removePrefix($str, $prefix)
  51. {
  52. if (substr($str, 0, strlen($prefix)) == $prefix) {
  53. return substr($str, strlen($prefix));
  54. }
  55. return null;
  56. }
  57. /**
  58. * Build a Symfony Finder object that scans the given $directory.
  59. *
  60. * @param string|array|Finder $directory The directory(s) or filename(s)
  61. * @param null|string|array $exclude The directory(s) or filename(s) to exclude (as absolute or relative paths)
  62. * @param null|string $pattern The pattern of the files to scan
  63. * @throws InvalidArgumentException
  64. */
  65. public static function finder($directory, $exclude = null, $pattern = null)
  66. {
  67. if ($directory instanceof Finder) {
  68. return $directory;
  69. } else {
  70. $finder = new Finder();
  71. $finder->sortByName();
  72. }
  73. if ($pattern === null) {
  74. $pattern = '*.php';
  75. }
  76. $finder->files()->followLinks()->name($pattern);
  77. if (is_string($directory)) {
  78. if (is_file($directory)) { // Scan a single file?
  79. $finder->append([$directory]);
  80. } else { // Scan a directory
  81. $finder->in($directory);
  82. }
  83. } elseif (is_array($directory)) {
  84. foreach ($directory as $path) {
  85. if (is_file($path)) { // Scan a file?
  86. $finder->append([$path]);
  87. } else {
  88. $finder->in($path);
  89. }
  90. }
  91. } else {
  92. throw new InvalidArgumentException('Unexpected $directory value:' . gettype($directory));
  93. }
  94. if ($exclude !== null) {
  95. if (is_string($exclude)) {
  96. $finder->notPath(Util::getRelativePath($exclude, $directory));
  97. } elseif (is_array($exclude)) {
  98. foreach ($exclude as $path) {
  99. $finder->notPath(Util::getRelativePath($path, $directory));
  100. }
  101. } else {
  102. throw new InvalidArgumentException('Unexpected $exclude value:' . gettype($exclude));
  103. }
  104. }
  105. return $finder;
  106. }
  107. }