*/ protected array $temp_files = []; /** * @var array */ protected static array $open_files = []; /** * @var array */ protected array $open_files_paths = []; public function getContents(string $file_path, bool $go_to_source = false): string { if (!$go_to_source && isset($this->temp_files[$file_path])) { return $this->temp_files[$file_path]['content']; } if (isset(self::$open_files[$file_path])) { return self::$open_files[$file_path]; } if (!file_exists($file_path)) { throw new UnexpectedValueException('File ' . $file_path . ' should exist to get contents'); } if (is_dir($file_path)) { throw new UnexpectedValueException('File ' . $file_path . ' is a directory'); } $file_contents = (string) file_get_contents($file_path); self::$open_files[$file_path] = $file_contents; return $file_contents; } public function setContents(string $file_path, string $file_contents): void { if (isset(self::$open_files[$file_path])) { self::$open_files[$file_path] = $file_contents; } if (isset($this->temp_files[$file_path])) { $this->temp_files[$file_path] = [ 'version'=> null, 'content' => $file_contents, ]; } file_put_contents($file_path, $file_contents); } public function setOpenContents(string $file_path, ?string $file_contents = null): void { if (isset(self::$open_files[$file_path])) { self::$open_files[$file_path] = $file_contents ?? $this->getContents($file_path, true); } } public function getModifiedTime(string $file_path): int { if (!file_exists($file_path)) { throw new UnexpectedValueException('File should exist to get modified time'); } return (int) filemtime($file_path); } public function addTemporaryFileChanges(string $file_path, string $new_content, ?int $version = null): void { if (isset($this->temp_files[$file_path]) && $version !== null && $this->temp_files[$file_path]['version'] !== null && $version < $this->temp_files[$file_path]['version'] ) { return; } $this->temp_files[$file_path] = [ 'version' => $version, 'content' => $new_content, ]; } public function removeTemporaryFileChanges(string $file_path): void { unset($this->temp_files[$file_path]); } public function getOpenFilesPath(): array { return $this->open_files_paths; } public function openFile(string $file_path): void { self::$open_files[$file_path] = $this->getContents($file_path, true); $this->open_files_paths[$file_path] = $file_path; } public function isOpen(string $file_path): bool { return isset($this->temp_files[$file_path]) || isset(self::$open_files[$file_path]); } public function closeFile(string $file_path): void { unset( $this->temp_files[$file_path], self::$open_files[$file_path], $this->open_files_paths[$file_path], ); } public function fileExists(string $file_path): bool { return file_exists($file_path); } /** * @param array $file_extensions * @param null|callable(string):bool $filter * @return list */ public function getFilesInDir(string $dir_path, array $file_extensions, callable $filter = null): array { $file_paths = []; $iterator = new RecursiveDirectoryIterator( $dir_path, FilesystemIterator::CURRENT_AS_PATHNAME | FilesystemIterator::SKIP_DOTS, ); if ($filter !== null) { $iterator = new RecursiveCallbackFilterIterator( $iterator, /** @param mixed $_ */ static function (string $current, $_, RecursiveIterator $iterator) use ($filter): bool { if ($iterator->hasChildren()) { $path = $current . DIRECTORY_SEPARATOR; } else { $path = $current; } return $filter($path); }, ); } /** @var RecursiveDirectoryIterator */ $iterator = new RecursiveIteratorIterator($iterator); $iterator->rewind(); while ($iterator->valid()) { $extension = $iterator->getExtension(); if (in_array($extension, $file_extensions, true)) { $file_paths[] = (string)$iterator->getRealPath(); } $iterator->next(); } return $file_paths; } }