> */ protected static $file_references_to_class = []; /** * A lookup table used for getting all the files that reference any other file * * @var array> */ protected static $referencing_files = []; /** * @var array> */ protected static $files_inheriting_classes = []; /** * A list of all files deleted since the last successful run * * @var array|null */ protected static $deleted_files = null; /** * A lookup table used for getting all the files referenced by a file * * @var array, i:array}> */ protected static $file_references = []; /** * @return array */ public static function getDeletedReferencedFiles() { if (self::$deleted_files === null) { self::$deleted_files = array_filter( array_keys(self::$file_references), /** * @param string $file_name * * @return bool */ function ($file_name) { return !file_exists($file_name); } ); } return self::$deleted_files; } /** * @param string $source_file * @param string $fq_class_name_lc * * @return void */ public static function addFileReferenceToClass($source_file, $fq_class_name_lc) { self::$referencing_files[$source_file] = true; self::$file_references_to_class[$fq_class_name_lc][$source_file] = true; } /** * @return array> */ public static function getAllFileReferences() { return self::$file_references_to_class; } /** * @param array> $references * @psalm-suppress PossiblyInvalidPropertyAssignmentValue * * @return void */ public static function addFileReferences(array $references) { self::$file_references_to_class = array_merge_recursive($references, self::$file_references_to_class); } /** * @param string $source_file * @param string $fq_class_name_lc * * @return void */ public static function addFileInheritanceToClass($source_file, $fq_class_name_lc) { self::$files_inheriting_classes[$fq_class_name_lc][$source_file] = true; } /** * @param string $file * * @return array */ public static function calculateFilesReferencingFile(ProjectChecker $project_checker, $file) { $referenced_files = []; $file_classes = ClassLikeChecker::getClassesForFile($project_checker, $file); foreach ($file_classes as $file_class_lc => $_) { if (isset(self::$file_references_to_class[$file_class_lc])) { $referenced_files = array_merge( $referenced_files, array_keys(self::$file_references_to_class[$file_class_lc]) ); } } return array_unique($referenced_files); } /** * @param string $file * * @return array */ public static function calculateFilesInheritingFile(ProjectChecker $project_checker, $file) { $referenced_files = []; $file_classes = ClassLikeChecker::getClassesForFile($project_checker, $file); foreach ($file_classes as $file_class_lc => $_) { if (isset(self::$files_inheriting_classes[$file_class_lc])) { $referenced_files = array_merge( $referenced_files, array_keys(self::$files_inheriting_classes[$file_class_lc]) ); } } return array_unique($referenced_files); } /** * @return void */ public static function removeDeletedFilesFromReferences() { $cache_directory = Config::getInstance()->getCacheDirectory(); $deleted_files = self::getDeletedReferencedFiles(); if ($deleted_files) { foreach ($deleted_files as $file) { unset(self::$file_references[$file]); } file_put_contents( $cache_directory . DIRECTORY_SEPARATOR . self::REFERENCE_CACHE_NAME, serialize(self::$file_references) ); } } /** * @param string $file * * @return array */ public static function getFilesReferencingFile($file) { return isset(self::$file_references[$file]['a']) ? self::$file_references[$file]['a'] : []; } /** * @param string $file * * @return array */ public static function getFilesInheritingFromFile($file) { return isset(self::$file_references[$file]['i']) ? self::$file_references[$file]['i'] : []; } /** * @return bool * @psalm-suppress MixedAssignment * @psalm-suppress PossiblyInvalidPropertyAssignmentValue */ public static function loadReferenceCache() { $cache_directory = Config::getInstance()->getCacheDirectory(); if ($cache_directory) { $cache_location = $cache_directory . DIRECTORY_SEPARATOR . self::REFERENCE_CACHE_NAME; if (is_readable($cache_location)) { $reference_cache = unserialize((string) file_get_contents($cache_location)); if (!is_array($reference_cache)) { throw new \UnexpectedValueException('The reference cache must be an array'); } self::$file_references = $reference_cache; return true; } } return false; } /** * @param array $visited_files * * @return void */ public static function updateReferenceCache(ProjectChecker $project_checker, array $visited_files) { $cache_directory = Config::getInstance()->getCacheDirectory(); if ($cache_directory) { $cache_location = $cache_directory . DIRECTORY_SEPARATOR . self::REFERENCE_CACHE_NAME; foreach ($visited_files as $file => $_) { $all_file_references = array_unique( array_merge( isset(self::$file_references[$file]['a']) ? self::$file_references[$file]['a'] : [], FileReferenceProvider::calculateFilesReferencingFile($project_checker, $file) ) ); $inheritance_references = array_unique( array_merge( isset(self::$file_references[$file]['i']) ? self::$file_references[$file]['i'] : [], FileReferenceProvider::calculateFilesInheritingFile($project_checker, $file) ) ); self::$file_references[$file] = [ 'a' => $all_file_references, 'i' => $inheritance_references, ]; } file_put_contents($cache_location, serialize(self::$file_references)); } } }