Elgg  Version master
AutoloadManager.php
Go to the documentation of this file.
1 <?php
2 
3 namespace Elgg;
4 
6 
13 
14  const FILENAME = 'autoload_data.php';
15  const KEY_CLASSES = 'classes';
16  const KEY_SCANNED_DIRS = 'scannedDirs';
17 
21  protected array $scannedDirs = [];
22 
26  protected bool $altered = false;
27 
34  public function __construct(protected ClassLoader $loader, protected AutoloadCache $cache) {
35  $this->loadCache();
36  }
37 
49  public function addClasses(string $dir): static {
50  if (!in_array($dir, $this->scannedDirs)) {
51  $map = $this->loader->getClassMap();
52  $map->mergeMap($this->scanClassesDir($dir));
53  $this->scannedDirs[] = $dir;
54  $this->altered = true;
55  }
56 
57  $this->loader->addFallback($dir);
58 
59  return $this;
60  }
61 
72  protected function scanClassesDir(string $dir): array {
73  if (!is_dir($dir)) {
74  return [];
75  }
76 
77  $dir = new \DirectoryIterator($dir);
78  $map = [];
79 
80  foreach ($dir as $file) {
81  /* @var \SplFileInfo $file */
82  if (!$file->isFile() || !$file->isReadable()) {
83  continue;
84  }
85 
86  $path = $file->getRealPath();
87 
88  if (pathinfo($path, PATHINFO_EXTENSION) !== 'php') {
89  continue;
90  }
91 
92  $class = $file->getBasename('.php');
93  $map[$class] = $path;
94  }
95 
96  return $map;
97  }
98 
104  public function saveCache(): static {
105  $map = $this->loader->getClassMap();
106 
107  if ($this->altered || $map->getAltered()) {
108  $classes = $map->getMap();
109  $scanned_dirs = $this->scannedDirs;
110 
111  if (empty($classes) && empty($scanned_dirs)) {
112  // if there is nothing to cache do not save it
113  return $this;
114  }
115 
116  $this->cache->save(self::FILENAME, [
117  self::KEY_CLASSES => $classes,
118  self::KEY_SCANNED_DIRS => $scanned_dirs,
119  ]);
120  }
121 
122  return $this;
123  }
124 
130  public function loadCache(): bool {
131  $cache = $this->getCacheFileContents();
132  if ($cache) {
133  // the cached class map will have the full scanned core classes, so
134  // don't consider the earlier mappings as "altering" the map
135  $this->loader->getClassMap()
136  ->setMap($cache[self::KEY_CLASSES])
137  ->setAltered(false);
138  $this->scannedDirs = $cache[self::KEY_SCANNED_DIRS];
139 
140  return true;
141  }
142 
143  $this->altered = true;
144 
145  return false;
146  }
147 
153  protected function getCacheFileContents(): ?array {
154  $spec = $this->cache->load(self::FILENAME);
155 
156  return isset($spec[self::KEY_CLASSES]) ? $spec : null;
157  }
158 
164  public function deleteCache(): static {
165  $this->cache->delete(self::FILENAME);
166  $this->loader->getClassMap()->setMap([])->setAltered(true);
167  $this->scannedDirs = [];
168  $this->altered = true;
169 
170  return $this;
171  }
172 }
saveCache()
If necessary, save necessary state details.
loadCache()
Set the state of the manager from the cache.
$classes
Definition: users.php:29
A class/interface/trait autoloader for PHP.
Definition: ClassLoader.php:48
$class
Definition: summary.php:44
$path
Definition: details.php:70
addClasses(string $dir)
Add classes found in this directory to the class map and allow classes in subdirectories to be found ...
Manages core autoloading and caching of class maps.
getCacheFileContents()
Tries to read the contents of the cache file and if valid returns the content.
deleteCache()
Delete the cache file.
scanClassesDir(string $dir)
Scan (non-recursively) a /classes directory for PHP files to map directly to classes.
__construct(protected ClassLoader $loader, protected AutoloadCache $cache)
Constructor.