FileRemoval.php 2.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100
  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. /**
  14. * Handles files removal with possibility to remove them on shutdown.
  15. *
  16. * @author Adam Klvač <adam@klva.cz>
  17. * @author Dariusz Rumiński <dariusz.ruminski@gmail.com>
  18. *
  19. * @internal
  20. */
  21. final class FileRemoval
  22. {
  23. /**
  24. * List of observed files to be removed.
  25. *
  26. * @var array<string, true>
  27. */
  28. private array $files = [];
  29. public function __construct()
  30. {
  31. register_shutdown_function([$this, 'clean']);
  32. }
  33. public function __destruct()
  34. {
  35. $this->clean();
  36. }
  37. /**
  38. * This class is not intended to be serialized,
  39. * and cannot be deserialized (see __wakeup method).
  40. */
  41. public function __sleep(): array
  42. {
  43. throw new \BadMethodCallException('Cannot serialize '.self::class);
  44. }
  45. /**
  46. * Disable the deserialization of the class to prevent attacker executing
  47. * code by leveraging the __destruct method.
  48. *
  49. * @see https://owasp.org/www-community/vulnerabilities/PHP_Object_Injection
  50. */
  51. public function __wakeup(): void
  52. {
  53. throw new \BadMethodCallException('Cannot unserialize '.self::class);
  54. }
  55. /**
  56. * Adds a file to be removed.
  57. */
  58. public function observe(string $path): void
  59. {
  60. $this->files[$path] = true;
  61. }
  62. /**
  63. * Removes a file from shutdown removal.
  64. */
  65. public function delete(string $path): void
  66. {
  67. if (isset($this->files[$path])) {
  68. unset($this->files[$path]);
  69. }
  70. $this->unlink($path);
  71. }
  72. /**
  73. * Removes attached files.
  74. */
  75. public function clean(): void
  76. {
  77. foreach ($this->files as $file => $value) {
  78. $this->unlink($file);
  79. }
  80. $this->files = [];
  81. }
  82. private function unlink(string $path): void
  83. {
  84. @unlink($path);
  85. }
  86. }