Skip to content

Commit 788ab3e

Browse files
committed
missing classes are stored outside of $classes
1 parent 80cd091 commit 788ab3e

File tree

1 file changed

+40
-46
lines changed

1 file changed

+40
-46
lines changed

src/RobotLoader/RobotLoader.php

Lines changed: 40 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -32,13 +32,13 @@ class RobotLoader
3232
/** @var array */
3333
private $scanPaths = [];
3434

35-
/** @var array of lowered-class => [file, time, orig] or num-of-retry */
35+
/** @var array of lowered-class => [file, time, orig] */
3636
private $classes = [];
3737

3838
/** @var bool */
3939
private $refreshed = FALSE;
4040

41-
/** @var array of missing classes in this request */
41+
/** @var array of missing classes */
4242
private $missing = [];
4343

4444
/** @var string|NULL */
@@ -75,35 +75,35 @@ public function tryLoad($type)
7575
{
7676
$type = $orig = ltrim($type, '\\'); // PHP namespace bug #49143
7777
$type = strtolower($type);
78-
79-
$info = &$this->classes[$type];
80-
if (isset($this->missing[$type]) || (is_int($info) && $info >= self::RETRY_LIMIT)) {
81-
return;
82-
}
78+
$info = isset($this->classes[$type]) ? $this->classes[$type] : NULL;
8379

8480
if ($this->autoRebuild) {
85-
if (!is_array($info) || !is_file($info['file'])) {
86-
$info = is_int($info) ? $info + 1 : 0;
87-
if (!$this->refreshed) {
81+
if (!$info || !is_file($info['file'])) {
82+
$missing = & $this->missing[$type];
83+
$missing++;
84+
if (!$this->refreshed && $missing <= self::RETRY_LIMIT) {
8885
$this->refresh();
86+
$this->saveCache();
87+
} elseif ($info) {
88+
unset($this->classes[$type]);
89+
$this->saveCache();
8990
}
90-
$this->saveCache();
91+
9192
} elseif (!$this->refreshed && filemtime($info['file']) !== $info['time']) {
9293
$this->updateFile($info['file']);
93-
if (!isset($this->classes[$type])) {
94-
$this->classes[$type] = 0;
94+
if (empty($this->classes[$type])) {
95+
$this->missing[$type] = 0;
9596
}
9697
$this->saveCache();
9798
}
99+
$info = isset($this->classes[$type]) ? $this->classes[$type] : NULL;
98100
}
99101

100-
if (isset($this->classes[$type]['file'])) {
101-
if ($this->classes[$type]['orig'] !== $orig) {
102-
trigger_error("Case mismatch on class name '$orig', correct name is '{$this->classes[$type]['orig']}'.", E_USER_WARNING);
102+
if ($info) {
103+
if ($info['orig'] !== $orig) {
104+
trigger_error("Case mismatch on class name '$orig', correct name is '{$info['orig']}'.", E_USER_WARNING);
103105
}
104-
call_user_func(function ($file) { require $file; }, $this->classes[$type]['file']);
105-
} else {
106-
$this->missing[$type] = TRUE;
106+
call_user_func(function ($file) { require $file; }, $info['file']);
107107
}
108108
}
109109

@@ -127,9 +127,7 @@ public function getIndexedClasses()
127127
{
128128
$res = [];
129129
foreach ($this->classes as $info) {
130-
if (is_array($info)) {
131-
$res[$info['orig']] = $info['file'];
132-
}
130+
$res[$info['orig']] = $info['file'];
133131
}
134132
return $res;
135133
}
@@ -155,14 +153,10 @@ public function rebuild()
155153
private function refresh()
156154
{
157155
$this->refreshed = TRUE; // prevents calling refresh() or updateFile() in tryLoad()
158-
$files = $missing = [];
159-
foreach ($this->classes as $class => $info) {
160-
if (is_array($info)) {
161-
$files[$info['file']]['time'] = $info['time'];
162-
$files[$info['file']]['classes'][] = $info['orig'];
163-
} else {
164-
$missing[$class] = $info;
165-
}
156+
$files = [];
157+
foreach ($this->classes as $info) {
158+
$files[$info['file']]['time'] = $info['time'];
159+
$files[$info['file']]['classes'][] = $info['orig'];
166160
}
167161

168162
$this->classes = [];
@@ -177,15 +171,16 @@ private function refresh()
177171
$files[$file] = ['classes' => [], 'time' => filemtime($file)];
178172

179173
foreach ($classes as $class) {
180-
$info = &$this->classes[strtolower($class)];
174+
$lower = strtolower($class);
175+
$info = &$this->classes[$lower];
181176
if (isset($info['file'])) {
182177
throw new Nette\InvalidStateException("Ambiguous class $class resolution; defined in {$info['file']} and in $file.");
183178
}
184179
$info = ['file' => $file, 'time' => filemtime($file), 'orig' => $class];
180+
unset($this->missing[$lower]);
185181
}
186182
}
187183
}
188-
$this->classes += $missing;
189184
}
190185

191186

@@ -242,26 +237,25 @@ private function updateFile($file)
242237
}
243238
}
244239

245-
if (is_file($file)) {
246-
foreach ($this->scanPhp(file_get_contents($file)) as $class) {
240+
$classes = is_file($file) ? $this->scanPhp(file_get_contents($file)) : [];
241+
foreach ($classes as $class) {
242+
$info = &$this->classes[strtolower($class)];
243+
if (isset($info['file']) && @filemtime($info['file']) !== $info['time']) { // @ file may not exists
244+
$this->updateFile($info['file']);
247245
$info = &$this->classes[strtolower($class)];
248-
if (isset($info['file']) && @filemtime($info['file']) !== $info['time']) { // @ file may not exists
249-
$this->updateFile($info['file']);
250-
$info = &$this->classes[strtolower($class)];
251-
}
252-
if (isset($info['file'])) {
253-
throw new Nette\InvalidStateException("Ambiguous class $class resolution; defined in {$info['file']} and in $file.");
254-
}
255-
$info = ['file' => $file, 'time' => filemtime($file), 'orig' => $class];
256246
}
247+
if (isset($info['file'])) {
248+
throw new Nette\InvalidStateException("Ambiguous class $class resolution; defined in {$info['file']} and in $file.");
249+
}
250+
$info = ['file' => $file, 'time' => filemtime($file), 'orig' => $class];
257251
}
258252
}
259253

260254

261255
/**
262256
* Searches classes, interfaces and traits in PHP file.
263257
* @param string
264-
* @return array
258+
* @return string[]
265259
*/
266260
private function scanPhp($code)
267261
{
@@ -368,7 +362,7 @@ public function setTempDirectory($dir)
368362
private function loadCache()
369363
{
370364
$file = $this->getCacheFile();
371-
$this->classes = @include $file; // @ file may not exist
365+
list($this->classes, $this->missing) = @include $file; // @ file may not exist
372366
if (is_array($this->classes)) {
373367
return;
374368
}
@@ -378,7 +372,7 @@ private function loadCache()
378372
throw new \RuntimeException("Unable to create or acquire exclusive lock on file '$file.lock'.");
379373
}
380374

381-
$this->classes = @include $file; // @ file may not exist
375+
list($this->classes, $this->missing) = @include $file; // @ file may not exist
382376
if (!is_array($this->classes)) {
383377
$this->classes = [];
384378
$this->refresh();
@@ -398,7 +392,7 @@ private function loadCache()
398392
private function saveCache()
399393
{
400394
$file = $this->getCacheFile();
401-
$code = "<?php\nreturn " . var_export($this->classes, TRUE) . ";\n";
395+
$code = "<?php\nreturn " . var_export([$this->classes, $this->missing], TRUE) . ";\n";
402396
if (file_put_contents("$file.tmp", $code) !== strlen($code) || !rename("$file.tmp", $file)) {
403397
@unlink("$file.tmp"); // @ - file may not exist
404398
throw new \RuntimeException("Unable to create '$file'.");

0 commit comments

Comments
 (0)