Skip to content

Commit 993b405

Browse files
committed
bug symfony#19859 [ClassLoader] Fix ClassCollectionLoader inlining with declare(strict_types=1) (nicolas-grekas)
This PR was merged into the 2.7 branch. Discussion ---------- [ClassLoader] Fix ClassCollectionLoader inlining with declare(strict_types=1) | Q | A | ------------- | --- | Branch? | 2.7 | Bug fix? | yes | Tests pass? | yes | Fixed tickets | symfony#19845 | License | MIT See diff as https://github.com/symfony/symfony/pull/19859/files?w=1 Commits ------- 647b3d2 [ClassLoader] Fix ClassCollectionLoader inlining with declare(strict_types=1)
2 parents c7d129e + 647b3d2 commit 993b405

File tree

4 files changed

+61
-19
lines changed

4 files changed

+61
-19
lines changed

src/Symfony/Component/ClassLoader/ClassCollectionLoader.php

Lines changed: 38 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,12 @@ public static function load($classes, $cacheDir, $name, $autoReload, $adaptive =
5858

5959
$classes = array_unique($classes);
6060

61-
$cache = $cacheDir.'/'.$name.$extension;
61+
// cache the core classes
62+
if (!is_dir($cacheDir) && !@mkdir($cacheDir, 0777, true) && !is_dir($cacheDir)) {
63+
throw new \RuntimeException(sprintf('Class Collection Loader was not able to create directory "%s"', $cacheDir));
64+
}
65+
$cacheDir = rtrim(realpath($cacheDir), '/'.DIRECTORY_SEPARATOR);
66+
$cache = $cacheDir.DIRECTORY_SEPARATOR.$name.$extension;
6267

6368
// auto-reload
6469
$reload = false;
@@ -99,31 +104,50 @@ public static function load($classes, $cacheDir, $name, $autoReload, $adaptive =
99104
}
100105
}
101106

107+
$c = '(?:\s*+(?:(?:#|//)[^\n]*+\n|/\*(?:(?<!\*/).)++)?+)*+';
108+
$strictTypesRegex = str_replace('.', $c, "'^<\?php\s.declare.\(.strict_types.=.1.\).;'is");
109+
110+
$cacheDir = explode(DIRECTORY_SEPARATOR, $cacheDir);
102111
$files = array();
103112
$content = '';
104113
foreach (self::getOrderedClasses($classes) as $class) {
105114
if (in_array($class->getName(), $declared)) {
106115
continue;
107116
}
108117

109-
$files[] = $class->getFileName();
118+
$files[] = $file = $class->getFileName();
119+
$c = file_get_contents($file);
110120

111-
$c = preg_replace(array('/^\s*<\?php/', '/\?>\s*$/'), '', file_get_contents($class->getFileName()));
121+
if (preg_match($strictTypesRegex, $c)) {
122+
$file = explode(DIRECTORY_SEPARATOR, $file);
112123

113-
// fakes namespace declaration for global code
114-
if (!$class->inNamespace()) {
115-
$c = "\nnamespace\n{\n".$c."\n}\n";
116-
}
124+
for ($i = 0; isset($file[$i], $cacheDir[$i]); ++$i) {
125+
if ($file[$i] !== $cacheDir[$i]) {
126+
break;
127+
}
128+
}
129+
if (1 >= $i) {
130+
$file = var_export(implode(DIRECTORY_SEPARATOR, $file), true);
131+
} else {
132+
$file = array_slice($file, $i);
133+
$file = str_repeat('..'.DIRECTORY_SEPARATOR, count($cacheDir) - $i).implode(DIRECTORY_SEPARATOR, $file);
134+
$file = '__DIR__.'.var_export(DIRECTORY_SEPARATOR.$file, true);
135+
}
117136

118-
$c = self::fixNamespaceDeclarations('<?php '.$c);
119-
$c = preg_replace('/^\s*<\?php/', '', $c);
137+
$c = "\nnamespace {require $file;}";
138+
} else {
139+
$c = preg_replace(array('/^\s*<\?php/', '/\?>\s*$/'), '', $c);
120140

121-
$content .= $c;
122-
}
141+
// fakes namespace declaration for global code
142+
if (!$class->inNamespace()) {
143+
$c = "\nnamespace\n{\n".$c."\n}\n";
144+
}
123145

124-
// cache the core classes
125-
if (!is_dir($cacheDir) && !@mkdir($cacheDir, 0777, true) && !is_dir($cacheDir)) {
126-
throw new \RuntimeException(sprintf('Class Collection Loader was not able to create directory "%s"', $cacheDir));
146+
$c = self::fixNamespaceDeclarations('<?php '.$c);
147+
$c = preg_replace('/^\s*<\?php/', '', $c);
148+
}
149+
150+
$content .= $c;
127151
}
128152
self::writeCacheFile($cache, '<?php '.$content);
129153

src/Symfony/Component/ClassLoader/Tests/ClassCollectionLoaderTest.php

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -223,18 +223,20 @@ public function testUnableToLoadClassException()
223223

224224
public function testCommentStripping()
225225
{
226-
if (is_file($file = sys_get_temp_dir().'/bar.php')) {
226+
if (is_file($file = __DIR__.'/bar.php')) {
227227
unlink($file);
228228
}
229229
spl_autoload_register($r = function ($class) {
230230
if (0 === strpos($class, 'Namespaced') || 0 === strpos($class, 'Pearlike_')) {
231-
require_once __DIR__.'/Fixtures/'.str_replace(array('\\', '_'), '/', $class).'.php';
231+
@require_once __DIR__.'/Fixtures/'.str_replace(array('\\', '_'), '/', $class).'.php';
232232
}
233233
});
234234

235+
$strictTypes = defined('HHVM_VERSION') ? '' : "\nnamespace {require __DIR__.'/Fixtures/Namespaced/WithStrictTypes.php';}";
236+
235237
ClassCollectionLoader::load(
236-
array('Namespaced\\WithComments', 'Pearlike_WithComments'),
237-
sys_get_temp_dir(),
238+
array('Namespaced\\WithComments', 'Pearlike_WithComments', $strictTypes ? 'Namespaced\\WithStrictTypes' : 'Namespaced\\WithComments'),
239+
__DIR__,
238240
'bar',
239241
false
240242
);
@@ -274,7 +276,9 @@ class Pearlike_WithComments
274276
}
275277
}
276278
EOF
277-
, str_replace("<?php \n", '', file_get_contents($file)));
279+
.$strictTypes,
280+
str_replace(array("<?php \n", '\\\\'), array('', '/'), file_get_contents($file))
281+
);
278282

279283
unlink($file);
280284
}

src/Symfony/Component/ClassLoader/Tests/ClassMapGeneratorTest.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@ public function getTestCreateMapTests()
7676
'Namespaced\\Foo' => realpath(__DIR__).'/Fixtures/Namespaced/Foo.php',
7777
'Namespaced\\Baz' => realpath(__DIR__).'/Fixtures/Namespaced/Baz.php',
7878
'Namespaced\\WithComments' => realpath(__DIR__).'/Fixtures/Namespaced/WithComments.php',
79+
'Namespaced\WithStrictTypes' => realpath(__DIR__).'/Fixtures/Namespaced/WithStrictTypes.php',
7980
),
8081
),
8182
array(__DIR__.'/Fixtures/beta/NamespaceCollision', array(
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
<?php
2+
3+
/*
4+
* foo
5+
*/
6+
7+
declare (strict_types = 1);
8+
9+
namespace Namespaced;
10+
11+
class WithStrictTypes
12+
{
13+
}

0 commit comments

Comments
 (0)