Skip to content

Commit f4258f7

Browse files
committed
added classloader and console symfony components.
1 parent 2aac28e commit f4258f7

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

42 files changed

+6667
-0
lines changed
Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\ClassLoader;
13+
14+
/**
15+
* ApcUniversalClassLoader implements a "universal" autoloader cached in APC for PHP 5.3.
16+
*
17+
* It is able to load classes that use either:
18+
*
19+
* * The technical interoperability standards for PHP 5.3 namespaces and
20+
* class names (https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-0.md);
21+
*
22+
* * The PEAR naming convention for classes (http://pear.php.net/).
23+
*
24+
* Classes from a sub-namespace or a sub-hierarchy of PEAR classes can be
25+
* looked for in a list of locations to ease the vendoring of a sub-set of
26+
* classes for large projects.
27+
*
28+
* Example usage:
29+
*
30+
* require 'vendor/symfony/src/Symfony/Component/ClassLoader/UniversalClassLoader.php';
31+
* require 'vendor/symfony/src/Symfony/Component/ClassLoader/ApcUniversalClassLoader.php';
32+
*
33+
* use Symfony\Component\ClassLoader\ApcUniversalClassLoader;
34+
*
35+
* $loader = new ApcUniversalClassLoader('apc.prefix.');
36+
*
37+
* // register classes with namespaces
38+
* $loader->registerNamespaces(array(
39+
* 'Symfony\Component' => __DIR__.'/component',
40+
* 'Symfony' => __DIR__.'/framework',
41+
* 'Sensio' => array(__DIR__.'/src', __DIR__.'/vendor'),
42+
* ));
43+
*
44+
* // register a library using the PEAR naming convention
45+
* $loader->registerPrefixes(array(
46+
* 'Swift_' => __DIR__.'/Swift',
47+
* ));
48+
*
49+
* // activate the autoloader
50+
* $loader->register();
51+
*
52+
* In this example, if you try to use a class in the Symfony\Component
53+
* namespace or one of its children (Symfony\Component\Console for instance),
54+
* the autoloader will first look for the class under the component/
55+
* directory, and it will then fallback to the framework/ directory if not
56+
* found before giving up.
57+
*
58+
* @author Fabien Potencier <fabien@symfony.com>
59+
* @author Kris Wallsmith <kris@symfony.com>
60+
*
61+
* @api
62+
*/
63+
class ApcUniversalClassLoader extends UniversalClassLoader
64+
{
65+
private $prefix;
66+
67+
/**
68+
* Constructor.
69+
*
70+
* @param string $prefix A prefix to create a namespace in APC
71+
*
72+
* @api
73+
*/
74+
public function __construct($prefix)
75+
{
76+
if (!extension_loaded('apc')) {
77+
throw new \RuntimeException('Unable to use ApcUniversalClassLoader as APC is not enabled.');
78+
}
79+
80+
$this->prefix = $prefix;
81+
}
82+
83+
/**
84+
* Finds a file by class name while caching lookups to APC.
85+
*
86+
* @param string $class A class name to resolve to file
87+
*/
88+
public function findFile($class)
89+
{
90+
if (false === $file = apc_fetch($this->prefix.$class)) {
91+
apc_store($this->prefix.$class, $file = parent::findFile($class));
92+
}
93+
94+
return $file;
95+
}
96+
}
Lines changed: 222 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,222 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\ClassLoader;
13+
14+
/**
15+
* ClassCollectionLoader.
16+
*
17+
* @author Fabien Potencier <fabien@symfony.com>
18+
*/
19+
class ClassCollectionLoader
20+
{
21+
static private $loaded;
22+
23+
/**
24+
* Loads a list of classes and caches them in one big file.
25+
*
26+
* @param array $classes An array of classes to load
27+
* @param string $cacheDir A cache directory
28+
* @param string $name The cache name prefix
29+
* @param Boolean $autoReload Whether to flush the cache when the cache is stale or not
30+
* @param Boolean $adaptive Whether to remove already declared classes or not
31+
* @param string $extension File extension of the resulting file
32+
*
33+
* @throws \InvalidArgumentException When class can't be loaded
34+
*/
35+
static public function load($classes, $cacheDir, $name, $autoReload, $adaptive = false, $extension = '.php')
36+
{
37+
// each $name can only be loaded once per PHP process
38+
if (isset(self::$loaded[$name])) {
39+
return;
40+
}
41+
42+
self::$loaded[$name] = true;
43+
44+
if ($adaptive) {
45+
// don't include already declared classes
46+
$classes = array_diff($classes, get_declared_classes(), get_declared_interfaces());
47+
48+
// the cache is different depending on which classes are already declared
49+
$name = $name.'-'.substr(md5(implode('|', $classes)), 0, 5);
50+
}
51+
52+
$cache = $cacheDir.'/'.$name.$extension;
53+
54+
// auto-reload
55+
$reload = false;
56+
if ($autoReload) {
57+
$metadata = $cacheDir.'/'.$name.$extension.'.meta';
58+
if (!is_file($metadata) || !is_file($cache)) {
59+
$reload = true;
60+
} else {
61+
$time = filemtime($cache);
62+
$meta = unserialize(file_get_contents($metadata));
63+
64+
if ($meta[1] != $classes) {
65+
$reload = true;
66+
} else {
67+
foreach ($meta[0] as $resource) {
68+
if (!is_file($resource) || filemtime($resource) > $time) {
69+
$reload = true;
70+
71+
break;
72+
}
73+
}
74+
}
75+
}
76+
}
77+
78+
if (!$reload && is_file($cache)) {
79+
require_once $cache;
80+
81+
return;
82+
}
83+
84+
$files = array();
85+
$content = '';
86+
foreach ($classes as $class) {
87+
if (!class_exists($class) && !interface_exists($class) && (!function_exists('trait_exists') || !trait_exists($class))) {
88+
throw new \InvalidArgumentException(sprintf('Unable to load class "%s"', $class));
89+
}
90+
91+
$r = new \ReflectionClass($class);
92+
$files[] = $r->getFileName();
93+
94+
$c = preg_replace(array('/^\s*<\?php/', '/\?>\s*$/'), '', file_get_contents($r->getFileName()));
95+
96+
// add namespace declaration for global code
97+
if (!$r->inNamespace()) {
98+
$c = "\nnamespace\n{\n".self::stripComments($c)."\n}\n";
99+
} else {
100+
$c = self::fixNamespaceDeclarations('<?php '.$c);
101+
$c = preg_replace('/^\s*<\?php/', '', $c);
102+
}
103+
104+
$content .= $c;
105+
}
106+
107+
// cache the core classes
108+
if (!is_dir(dirname($cache))) {
109+
mkdir(dirname($cache), 0777, true);
110+
}
111+
self::writeCacheFile($cache, '<?php '.$content);
112+
113+
if ($autoReload) {
114+
// save the resources
115+
self::writeCacheFile($metadata, serialize(array($files, $classes)));
116+
}
117+
}
118+
119+
/**
120+
* Adds brackets around each namespace if it's not already the case.
121+
*
122+
* @param string $source Namespace string
123+
*
124+
* @return string Namespaces with brackets
125+
*/
126+
static public function fixNamespaceDeclarations($source)
127+
{
128+
if (!function_exists('token_get_all')) {
129+
return $source;
130+
}
131+
132+
$output = '';
133+
$inNamespace = false;
134+
$tokens = token_get_all($source);
135+
136+
for ($i = 0, $max = count($tokens); $i < $max; $i++) {
137+
$token = $tokens[$i];
138+
if (is_string($token)) {
139+
$output .= $token;
140+
} elseif (in_array($token[0], array(T_COMMENT, T_DOC_COMMENT))) {
141+
// strip comments
142+
continue;
143+
} elseif (T_NAMESPACE === $token[0]) {
144+
if ($inNamespace) {
145+
$output .= "}\n";
146+
}
147+
$output .= $token[1];
148+
149+
// namespace name and whitespaces
150+
while (($t = $tokens[++$i]) && is_array($t) && in_array($t[0], array(T_WHITESPACE, T_NS_SEPARATOR, T_STRING))) {
151+
$output .= $t[1];
152+
}
153+
if (is_string($t) && '{' === $t) {
154+
$inNamespace = false;
155+
--$i;
156+
} else {
157+
$output .= "\n{";
158+
$inNamespace = true;
159+
}
160+
} else {
161+
$output .= $token[1];
162+
}
163+
}
164+
165+
if ($inNamespace) {
166+
$output .= "}\n";
167+
}
168+
169+
return $output;
170+
}
171+
172+
/**
173+
* Writes a cache file.
174+
*
175+
* @param string $file Filename
176+
* @param string $content Temporary file content
177+
*
178+
* @throws \RuntimeException when a cache file cannot be written
179+
*/
180+
static private function writeCacheFile($file, $content)
181+
{
182+
$tmpFile = tempnam(dirname($file), basename($file));
183+
if (false !== @file_put_contents($tmpFile, $content) && @rename($tmpFile, $file)) {
184+
chmod($file, 0644);
185+
186+
return;
187+
}
188+
189+
throw new \RuntimeException(sprintf('Failed to write cache file "%s".', $file));
190+
}
191+
192+
/**
193+
* Removes comments from a PHP source string.
194+
*
195+
* We don't use the PHP php_strip_whitespace() function
196+
* as we want the content to be readable and well-formatted.
197+
*
198+
* @param string $source A PHP string
199+
*
200+
* @return string The PHP string with the comments removed
201+
*/
202+
static private function stripComments($source)
203+
{
204+
if (!function_exists('token_get_all')) {
205+
return $source;
206+
}
207+
208+
$output = '';
209+
foreach (token_get_all($source) as $token) {
210+
if (is_string($token)) {
211+
$output .= $token;
212+
} elseif (!in_array($token[0], array(T_COMMENT, T_DOC_COMMENT))) {
213+
$output .= $token[1];
214+
}
215+
}
216+
217+
// replace multiple new lines with a single newline
218+
$output = preg_replace(array('/\s+$/Sm', '/\n+/S'), "\n", $output);
219+
220+
return $output;
221+
}
222+
}

0 commit comments

Comments
 (0)