Skip to content

Commit

Permalink
[HttpKernel] added the possibility to add non-namespaced classes to t…
Browse files Browse the repository at this point in the history
…he compiled class cache
  • Loading branch information
fabpot committed Jan 16, 2011
1 parent 612dce8 commit be35aa1
Show file tree
Hide file tree
Showing 3 changed files with 195 additions and 12 deletions.
57 changes: 56 additions & 1 deletion src/Symfony/Component/HttpKernel/ClassCollectionLoader.php
Expand Up @@ -92,7 +92,17 @@ static public function load($classes, $cacheDir, $name, $autoReload, $adaptive =
$r = new \ReflectionClass($class);
$files[] = $r->getFileName();

$content .= preg_replace(array('/^\s*<\?php/', '/\?>\s*$/'), '', file_get_contents($r->getFileName()));
$c = preg_replace(array('/^\s*<\?php/', '/\?>\s*$/'), '', file_get_contents($r->getFileName()));

// add namespace declaration for global code
if (!$r->inNamespace()) {
$c = "\nnamespace\n{\n$c\n}\n";
} else {
$c = self::fixNamespaceDeclarations('<?php '.$c);
$c = preg_replace('/^\s*<\?php/', '', $c);
}

$content .= $c;
}

// cache the core classes
Expand All @@ -107,6 +117,51 @@ static public function load($classes, $cacheDir, $name, $autoReload, $adaptive =
}
}

/**
* Adds brackets around each namespace if it's not already the case.
*/
static public function fixNamespaceDeclarations($source)
{
if (!function_exists('token_get_all')) {
return $source;
}

$output = '';
$inNamespace = false;
$tokens = token_get_all($source);

while ($token = array_shift($tokens)) {
if (is_string($token)) {
$output .= $token;
} elseif (T_NAMESPACE === $token[0]) {
if ($inNamespace) {
$output .= "}\n";
}
$output .= $token[1];

// namespace name and whitespaces
while (($t = array_shift($tokens)) && is_array($t) && in_array($t[0], array(T_WHITESPACE, T_NS_SEPARATOR, T_STRING))) {
$output .= $t[1];
}
if (is_string($t) && '{' === $t) {
$inNamespace = false;
array_unshift($tokens, $t);
} else {
$output .= "\n{";
$inNamespace = true;
}
} else {
$output .= $token[1];
}
}

if ($inNamespace) {
$output .= "}\n";
}

return $output;
}

static protected function writeCacheFile($file, $content)
{
$tmpFile = tempnam(dirname($file), basename($file));
Expand Down
84 changes: 73 additions & 11 deletions src/Symfony/Component/HttpKernel/bootstrap.php
@@ -1,5 +1,6 @@
<?php
namespace Symfony\Component\HttpKernel\Bundle;
namespace Symfony\Component\HttpKernel\Bundle
{
use Symfony\Component\DependencyInjection\ContainerAware;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;
Expand Down Expand Up @@ -81,13 +82,17 @@ protected function initReflection()
$this->path = str_replace('\\', '/', dirname($this->reflection->getFilename()));
}
}
namespace Symfony\Component\HttpKernel\Bundle;
}
namespace Symfony\Component\HttpKernel\Bundle
{
interface BundleInterface
{
function boot();
function shutdown();
}
namespace Symfony\Component\HttpKernel\Debug;
}
namespace Symfony\Component\HttpKernel\Debug
{
class ErrorHandler
{
protected $levels = array(
Expand Down Expand Up @@ -119,7 +124,9 @@ public function handle($level, $message, $file, $line, $context)
return false;
}
}
namespace Symfony\Component\HttpKernel;
}
namespace Symfony\Component\HttpKernel
{
class ClassCollectionLoader
{
static protected $loaded;
Expand Down Expand Up @@ -167,7 +174,14 @@ static public function load($classes, $cacheDir, $name, $autoReload, $adaptive =
}
$r = new \ReflectionClass($class);
$files[] = $r->getFileName();
$content .= preg_replace(array('/^\s*<\?php/', '/\?>\s*$/'), '', file_get_contents($r->getFileName()));
$c = preg_replace(array('/^\s*<\?php/', '/\?>\s*$/'), '', file_get_contents($r->getFileName()));
if (!$r->inNamespace()) {
$c = "\nnamespace\n{\n$c\n}\n";
} else {
$c = self::fixNamespaceDeclarations('<?php '.$c);
$c = preg_replace('/^\s*<\?php/', '', $c);
}
$content .= $c;
}
if (!is_dir(dirname($cache))) {
mkdir(dirname($cache), 0777, true);
Expand All @@ -177,6 +191,41 @@ static public function load($classes, $cacheDir, $name, $autoReload, $adaptive =
self::writeCacheFile($metadata, serialize(array($files, $classes)));
}
}
static public function fixNamespaceDeclarations($source)
{
if (!function_exists('token_get_all')) {
return $source;
}
$output = '';
$inNamespace = false;
$tokens = token_get_all($source);
while ($token = array_shift($tokens)) {
if (is_string($token)) {
$output .= $token;
} elseif (T_NAMESPACE === $token[0]) {
if ($inNamespace) {
$output .= "}\n";
}
$output .= $token[1];
while (($t = array_shift($tokens)) && is_array($t) && in_array($t[0], array(T_WHITESPACE, T_NS_SEPARATOR, T_STRING))) {
$output .= $t[1];
}
if (is_string($t) && '{' === $t) {
$inNamespace = false;
array_unshift($tokens, $t);
} else {
$output .= "\n{";
$inNamespace = true;
}
} else {
$output .= $token[1];
}
}
if ($inNamespace) {
$output .= "}\n";
}
return $output;
}
static protected function writeCacheFile($file, $content)
{
$tmpFile = tempnam(dirname($file), basename($file));
Expand All @@ -187,7 +236,9 @@ static protected function writeCacheFile($file, $content)
throw new \RuntimeException(sprintf('Failed to write cache file "%s".', $file));
}
}
namespace Symfony\Component\DependencyInjection;
}
namespace Symfony\Component\DependencyInjection
{
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag;
use Symfony\Component\DependencyInjection\ParameterBag\FrozenParameterBag;
Expand Down Expand Up @@ -275,12 +326,16 @@ static public function underscore($id)
return strtolower(preg_replace(array('/([A-Z]+)([A-Z][a-z])/', '/([a-z\d])([A-Z])/'), array('\\1_\\2', '\\1_\\2'), strtr($id, '_', '.')));
}
}
namespace Symfony\Component\DependencyInjection;
}
namespace Symfony\Component\DependencyInjection
{
interface ContainerAwareInterface
{
function setContainer(ContainerInterface $container = null);
}
namespace Symfony\Component\DependencyInjection;
}
namespace Symfony\Component\DependencyInjection
{
interface ContainerInterface
{
const EXCEPTION_ON_INVALID_REFERENCE = 1;
Expand All @@ -290,7 +345,9 @@ function set($id, $service);
function get($id, $invalidBehavior = self::EXCEPTION_ON_INVALID_REFERENCE);
function has($id);
}
namespace Symfony\Component\DependencyInjection\ParameterBag;
}
namespace Symfony\Component\DependencyInjection\ParameterBag
{
class FrozenParameterBag extends ParameterBag
{
public function __construct(array $parameters = array())
Expand All @@ -312,7 +369,9 @@ public function set($name, $value)
throw new \LogicException('Impossible to call set() on a frozen ParameterBag.');
}
}
namespace Symfony\Component\DependencyInjection\ParameterBag;
}
namespace Symfony\Component\DependencyInjection\ParameterBag
{
interface ParameterBagInterface
{
function clear();
Expand All @@ -322,8 +381,11 @@ function get($name);
function set($name, $value);
function has($name);
}
namespace Symfony\Component\DependencyInjection;
}
namespace Symfony\Component\DependencyInjection
{
interface TaggedContainerInterface extends ContainerInterface
{
function findTaggedServiceIds($name);
}
}
@@ -0,0 +1,66 @@
<?php

/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien.potencier@symfony-project.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace Symfony\Tests\Component\HttpKernel;

use Symfony\Component\HttpKernel\ClassCollectionLoader;

class ClassCollectionLoaderTest extends \PHPUnit_Framework_TestCase
{
public function testFixNamespaceDeclarations()
{
$source = <<<EOF
<?php
namespace Foo;
class Foo {}
namespace Bar ;
class Foo {}
namespace Foo\Bar;
class Foo {}
namespace Foo\Bar\Bar
{
class Foo {}
}
namespace
{
class Foo {}
}
EOF;

$expected = <<<EOF
<?php
namespace Foo
{
class Foo {}
}
namespace Bar
{
class Foo {}
}
namespace Foo\Bar
{
class Foo {}
}
namespace Foo\Bar\Bar
{
class Foo {}
}
namespace
{
class Foo {}
}
EOF;

$this->assertEquals($expected, ClassCollectionLoader::fixNamespaceDeclarations($source));
}
}

0 comments on commit be35aa1

Please sign in to comment.