Verzeichnisstruktur phpBB-3.1.0


Veröffentlicht
27.10.2014

So funktioniert es


Auf das letzte Element klicken. Dies geht jeweils ein Schritt zurück

Auf das Icon klicken, dies öffnet das Verzeichnis. Nochmal klicken schließt das Verzeichnis.
Auf den Verzeichnisnamen klicken, dies zeigt nur das Verzeichnis mit Inhalt an

      (Beispiel Datei-Icons)

Auf das Icon klicken um den Quellcode anzuzeigen

Kernel.php

Zuletzt modifiziert: 09.10.2024, 12:58 - Dateigröße: 23.23 KiB


 001  <?php
 002   
 003  /*
 004   * This file is part of the Symfony package.
 005   *
 006   * (c) Fabien Potencier <fabien@symfony.com>
 007   *
 008   * For the full copyright and license information, please view the LICENSE
 009   * file that was distributed with this source code.
 010   */
 011   
 012  namespace Symfony\Component\HttpKernel;
 013   
 014  use Symfony\Bridge\ProxyManager\LazyProxy\Instantiator\RuntimeInstantiator;
 015  use Symfony\Bridge\ProxyManager\LazyProxy\PhpDumper\ProxyDumper;
 016  use Symfony\Component\DependencyInjection\ContainerInterface;
 017  use Symfony\Component\DependencyInjection\ContainerBuilder;
 018  use Symfony\Component\DependencyInjection\Dumper\PhpDumper;
 019  use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag;
 020  use Symfony\Component\DependencyInjection\Loader\XmlFileLoader;
 021  use Symfony\Component\DependencyInjection\Loader\YamlFileLoader;
 022  use Symfony\Component\DependencyInjection\Loader\IniFileLoader;
 023  use Symfony\Component\DependencyInjection\Loader\PhpFileLoader;
 024  use Symfony\Component\DependencyInjection\Loader\ClosureLoader;
 025  use Symfony\Component\HttpFoundation\Request;
 026  use Symfony\Component\HttpFoundation\Response;
 027  use Symfony\Component\HttpKernel\Bundle\BundleInterface;
 028  use Symfony\Component\HttpKernel\Config\FileLocator;
 029  use Symfony\Component\HttpKernel\DependencyInjection\MergeExtensionConfigurationPass;
 030  use Symfony\Component\HttpKernel\DependencyInjection\AddClassesToCachePass;
 031  use Symfony\Component\Config\Loader\LoaderResolver;
 032  use Symfony\Component\Config\Loader\DelegatingLoader;
 033  use Symfony\Component\Config\ConfigCache;
 034  use Symfony\Component\ClassLoader\ClassCollectionLoader;
 035   
 036  /**
 037   * The Kernel is the heart of the Symfony system.
 038   *
 039   * It manages an environment made of bundles.
 040   *
 041   * @author Fabien Potencier <fabien@symfony.com>
 042   *
 043   * @api
 044   */
 045  abstract class Kernel implements KernelInterface, TerminableInterface
 046  {
 047      /**
 048       * @var BundleInterface[]
 049       */
 050      protected $bundles;
 051   
 052      protected $bundleMap;
 053      protected $container;
 054      protected $rootDir;
 055      protected $environment;
 056      protected $debug;
 057      protected $booted;
 058      protected $name;
 059      protected $startTime;
 060      protected $loadClassCache;
 061   
 062      const VERSION         = '2.3.21';
 063      const VERSION_ID      = '20321';
 064      const MAJOR_VERSION   = '2';
 065      const MINOR_VERSION   = '3';
 066      const RELEASE_VERSION = '21';
 067      const EXTRA_VERSION   = '';
 068   
 069      /**
 070       * Constructor.
 071       *
 072       * @param string  $environment The environment
 073       * @param bool    $debug       Whether to enable debugging or not
 074       *
 075       * @api
 076       */
 077      public function __construct($environment, $debug)
 078      {
 079          $this->environment = $environment;
 080          $this->debug = (bool) $debug;
 081          $this->booted = false;
 082          $this->rootDir = $this->getRootDir();
 083          $this->name = $this->getName();
 084          $this->bundles = array();
 085   
 086          if ($this->debug) {
 087              $this->startTime = microtime(true);
 088          }
 089   
 090          $this->init();
 091      }
 092   
 093      /**
 094       * @deprecated Deprecated since version 2.3, to be removed in 3.0. Move your logic in the constructor instead.
 095       */
 096      public function init()
 097      {
 098      }
 099   
 100      public function __clone()
 101      {
 102          if ($this->debug) {
 103              $this->startTime = microtime(true);
 104          }
 105   
 106          $this->booted = false;
 107          $this->container = null;
 108      }
 109   
 110      /**
 111       * Boots the current kernel.
 112       *
 113       * @api
 114       */
 115      public function boot()
 116      {
 117          if (true === $this->booted) {
 118              return;
 119          }
 120   
 121          if ($this->loadClassCache) {
 122              $this->doLoadClassCache($this->loadClassCache[0], $this->loadClassCache[1]);
 123          }
 124   
 125          // init bundles
 126          $this->initializeBundles();
 127   
 128          // init container
 129          $this->initializeContainer();
 130   
 131          foreach ($this->getBundles() as $bundle) {
 132              $bundle->setContainer($this->container);
 133              $bundle->boot();
 134          }
 135   
 136          $this->booted = true;
 137      }
 138   
 139      /**
 140       * {@inheritdoc}
 141       *
 142       * @api
 143       */
 144      public function terminate(Request $request, Response $response)
 145      {
 146          if (false === $this->booted) {
 147              return;
 148          }
 149   
 150          if ($this->getHttpKernel() instanceof TerminableInterface) {
 151              $this->getHttpKernel()->terminate($request, $response);
 152          }
 153      }
 154   
 155      /**
 156       * {@inheritdoc}
 157       *
 158       * @api
 159       */
 160      public function shutdown()
 161      {
 162          if (false === $this->booted) {
 163              return;
 164          }
 165   
 166          $this->booted = false;
 167   
 168          foreach ($this->getBundles() as $bundle) {
 169              $bundle->shutdown();
 170              $bundle->setContainer(null);
 171          }
 172   
 173          $this->container = null;
 174      }
 175   
 176      /**
 177       * {@inheritdoc}
 178       *
 179       * @api
 180       */
 181      public function handle(Request $request, $type = HttpKernelInterface::MASTER_REQUEST, $catch = true)
 182      {
 183          if (false === $this->booted) {
 184              $this->boot();
 185          }
 186   
 187          return $this->getHttpKernel()->handle($request, $type, $catch);
 188      }
 189   
 190      /**
 191       * Gets a HTTP kernel from the container
 192       *
 193       * @return HttpKernel
 194       */
 195      protected function getHttpKernel()
 196      {
 197          return $this->container->get('http_kernel');
 198      }
 199   
 200      /**
 201       * {@inheritdoc}
 202       *
 203       * @api
 204       */
 205      public function getBundles()
 206      {
 207          return $this->bundles;
 208      }
 209   
 210      /**
 211       * {@inheritdoc}
 212       *
 213       * @api
 214       */
 215      public function isClassInActiveBundle($class)
 216      {
 217          foreach ($this->getBundles() as $bundle) {
 218              if (0 === strpos($class, $bundle->getNamespace())) {
 219                  return true;
 220              }
 221          }
 222   
 223          return false;
 224      }
 225   
 226      /**
 227       * {@inheritdoc}
 228       *
 229       * @api
 230       */
 231      public function getBundle($name, $first = true)
 232      {
 233          if (!isset($this->bundleMap[$name])) {
 234              throw new \InvalidArgumentException(sprintf('Bundle "%s" does not exist or it is not enabled. Maybe you forgot to add it in the registerBundles() method of your %s.php file?', $name, get_class($this)));
 235          }
 236   
 237          if (true === $first) {
 238              return $this->bundleMap[$name][0];
 239          }
 240   
 241          return $this->bundleMap[$name];
 242      }
 243   
 244      /**
 245       * Returns the file path for a given resource.
 246       *
 247       * A Resource can be a file or a directory.
 248       *
 249       * The resource name must follow the following pattern:
 250       *
 251       *     @<BundleName>/path/to/a/file.something
 252       *
 253       * where BundleName is the name of the bundle
 254       * and the remaining part is the relative path in the bundle.
 255       *
 256       * If $dir is passed, and the first segment of the path is "Resources",
 257       * this method will look for a file named:
 258       *
 259       *     $dir/<BundleName>/path/without/Resources
 260       *
 261       * before looking in the bundle resource folder.
 262       *
 263       * @param string  $name  A resource name to locate
 264       * @param string  $dir   A directory where to look for the resource first
 265       * @param bool    $first Whether to return the first path or paths for all matching bundles
 266       *
 267       * @return string|array The absolute path of the resource or an array if $first is false
 268       *
 269       * @throws \InvalidArgumentException if the file cannot be found or the name is not valid
 270       * @throws \RuntimeException         if the name contains invalid/unsafe
 271       * @throws \RuntimeException         if a custom resource is hidden by a resource in a derived bundle
 272       *
 273       * @api
 274       */
 275      public function locateResource($name, $dir = null, $first = true)
 276      {
 277          if ('@' !== $name[0]) {
 278              throw new \InvalidArgumentException(sprintf('A resource name must start with @ ("%s" given).', $name));
 279          }
 280   
 281          if (false !== strpos($name, '..')) {
 282              throw new \RuntimeException(sprintf('File name "%s" contains invalid characters (..).', $name));
 283          }
 284   
 285          $bundleName = substr($name, 1);
 286          $path = '';
 287          if (false !== strpos($bundleName, '/')) {
 288              list($bundleName, $path) = explode('/', $bundleName, 2);
 289          }
 290   
 291          $isResource = 0 === strpos($path, 'Resources') && null !== $dir;
 292          $overridePath = substr($path, 9);
 293          $resourceBundle = null;
 294          $bundles = $this->getBundle($bundleName, false);
 295          $files = array();
 296   
 297          foreach ($bundles as $bundle) {
 298              if ($isResource && file_exists($file = $dir.'/'.$bundle->getName().$overridePath)) {
 299                  if (null !== $resourceBundle) {
 300                      throw new \RuntimeException(sprintf('"%s" resource is hidden by a resource from the "%s" derived bundle. Create a "%s" file to override the bundle resource.',
 301                          $file,
 302                          $resourceBundle,
 303                          $dir.'/'.$bundles[0]->getName().$overridePath
 304                      ));
 305                  }
 306   
 307                  if ($first) {
 308                      return $file;
 309                  }
 310                  $files[] = $file;
 311              }
 312   
 313              if (file_exists($file = $bundle->getPath().'/'.$path)) {
 314                  if ($first && !$isResource) {
 315                      return $file;
 316                  }
 317                  $files[] = $file;
 318                  $resourceBundle = $bundle->getName();
 319              }
 320          }
 321   
 322          if (count($files) > 0) {
 323              return $first && $isResource ? $files[0] : $files;
 324          }
 325   
 326          throw new \InvalidArgumentException(sprintf('Unable to find file "%s".', $name));
 327      }
 328   
 329      /**
 330       * {@inheritdoc}
 331       *
 332       * @api
 333       */
 334      public function getName()
 335      {
 336          if (null === $this->name) {
 337              $this->name = preg_replace('/[^a-zA-Z0-9_]+/', '', basename($this->rootDir));
 338          }
 339   
 340          return $this->name;
 341      }
 342   
 343      /**
 344       * {@inheritdoc}
 345       *
 346       * @api
 347       */
 348      public function getEnvironment()
 349      {
 350          return $this->environment;
 351      }
 352   
 353      /**
 354       * {@inheritdoc}
 355       *
 356       * @api
 357       */
 358      public function isDebug()
 359      {
 360          return $this->debug;
 361      }
 362   
 363      /**
 364       * {@inheritdoc}
 365       *
 366       * @api
 367       */
 368      public function getRootDir()
 369      {
 370          if (null === $this->rootDir) {
 371              $r = new \ReflectionObject($this);
 372              $this->rootDir = str_replace('\\', '/', dirname($r->getFileName()));
 373          }
 374   
 375          return $this->rootDir;
 376      }
 377   
 378      /**
 379       * {@inheritdoc}
 380       *
 381       * @api
 382       */
 383      public function getContainer()
 384      {
 385          return $this->container;
 386      }
 387   
 388      /**
 389       * Loads the PHP class cache.
 390       *
 391       * This methods only registers the fact that you want to load the cache classes.
 392       * The cache will actually only be loaded when the Kernel is booted.
 393       *
 394       * That optimization is mainly useful when using the HttpCache class in which
 395       * case the class cache is not loaded if the Response is in the cache.
 396       *
 397       * @param string $name      The cache name prefix
 398       * @param string $extension File extension of the resulting file
 399       */
 400      public function loadClassCache($name = 'classes', $extension = '.php')
 401      {
 402          $this->loadClassCache = array($name, $extension);
 403      }
 404   
 405      /**
 406       * Used internally.
 407       */
 408      public function setClassCache(array $classes)
 409      {
 410          file_put_contents($this->getCacheDir().'/classes.map', sprintf('<?php return %s;', var_export($classes, true)));
 411      }
 412   
 413      /**
 414       * {@inheritdoc}
 415       *
 416       * @api
 417       */
 418      public function getStartTime()
 419      {
 420          return $this->debug ? $this->startTime : -INF;
 421      }
 422   
 423      /**
 424       * {@inheritdoc}
 425       *
 426       * @api
 427       */
 428      public function getCacheDir()
 429      {
 430          return $this->rootDir.'/cache/'.$this->environment;
 431      }
 432   
 433      /**
 434       * {@inheritdoc}
 435       *
 436       * @api
 437       */
 438      public function getLogDir()
 439      {
 440          return $this->rootDir.'/logs';
 441      }
 442   
 443      /**
 444       * {@inheritdoc}
 445       *
 446       * @api
 447       */
 448      public function getCharset()
 449      {
 450          return 'UTF-8';
 451      }
 452   
 453      protected function doLoadClassCache($name, $extension)
 454      {
 455          if (!$this->booted && is_file($this->getCacheDir().'/classes.map')) {
 456              ClassCollectionLoader::load(include($this->getCacheDir().'/classes.map'), $this->getCacheDir(), $name, $this->debug, false, $extension);
 457          }
 458      }
 459   
 460      /**
 461       * Initializes the data structures related to the bundle management.
 462       *
 463       *  - the bundles property maps a bundle name to the bundle instance,
 464       *  - the bundleMap property maps a bundle name to the bundle inheritance hierarchy (most derived bundle first).
 465       *
 466       * @throws \LogicException if two bundles share a common name
 467       * @throws \LogicException if a bundle tries to extend a non-registered bundle
 468       * @throws \LogicException if a bundle tries to extend itself
 469       * @throws \LogicException if two bundles extend the same ancestor
 470       */
 471      protected function initializeBundles()
 472      {
 473          // init bundles
 474          $this->bundles = array();
 475          $topMostBundles = array();
 476          $directChildren = array();
 477   
 478          foreach ($this->registerBundles() as $bundle) {
 479              $name = $bundle->getName();
 480              if (isset($this->bundles[$name])) {
 481                  throw new \LogicException(sprintf('Trying to register two bundles with the same name "%s"', $name));
 482              }
 483              $this->bundles[$name] = $bundle;
 484   
 485              if ($parentName = $bundle->getParent()) {
 486                  if (isset($directChildren[$parentName])) {
 487                      throw new \LogicException(sprintf('Bundle "%s" is directly extended by two bundles "%s" and "%s".', $parentName, $name, $directChildren[$parentName]));
 488                  }
 489                  if ($parentName == $name) {
 490                      throw new \LogicException(sprintf('Bundle "%s" can not extend itself.', $name));
 491                  }
 492                  $directChildren[$parentName] = $name;
 493              } else {
 494                  $topMostBundles[$name] = $bundle;
 495              }
 496          }
 497   
 498          // look for orphans
 499          if (!empty($directChildren) && count($diff = array_diff_key($directChildren, $this->bundles))) {
 500              $diff = array_keys($diff);
 501   
 502              throw new \LogicException(sprintf('Bundle "%s" extends bundle "%s", which is not registered.', $directChildren[$diff[0]], $diff[0]));
 503          }
 504   
 505          // inheritance
 506          $this->bundleMap = array();
 507          foreach ($topMostBundles as $name => $bundle) {
 508              $bundleMap = array($bundle);
 509              $hierarchy = array($name);
 510   
 511              while (isset($directChildren[$name])) {
 512                  $name = $directChildren[$name];
 513                  array_unshift($bundleMap, $this->bundles[$name]);
 514                  $hierarchy[] = $name;
 515              }
 516   
 517              foreach ($hierarchy as $bundle) {
 518                  $this->bundleMap[$bundle] = $bundleMap;
 519                  array_pop($bundleMap);
 520              }
 521          }
 522      }
 523   
 524      /**
 525       * Gets the container class.
 526       *
 527       * @return string The container class
 528       */
 529      protected function getContainerClass()
 530      {
 531          return $this->name.ucfirst($this->environment).($this->debug ? 'Debug' : '').'ProjectContainer';
 532      }
 533   
 534      /**
 535       * Gets the container's base class.
 536       *
 537       * All names except Container must be fully qualified.
 538       *
 539       * @return string
 540       */
 541      protected function getContainerBaseClass()
 542      {
 543          return 'Container';
 544      }
 545   
 546      /**
 547       * Initializes the service container.
 548       *
 549       * The cached version of the service container is used when fresh, otherwise the
 550       * container is built.
 551       */
 552      protected function initializeContainer()
 553      {
 554          $class = $this->getContainerClass();
 555          $cache = new ConfigCache($this->getCacheDir().'/'.$class.'.php', $this->debug);
 556          $fresh = true;
 557          if (!$cache->isFresh()) {
 558              $container = $this->buildContainer();
 559              $container->compile();
 560              $this->dumpContainer($cache, $container, $class, $this->getContainerBaseClass());
 561   
 562              $fresh = false;
 563          }
 564   
 565          require_once $cache;
 566   
 567          $this->container = new $class();
 568          $this->container->set('kernel', $this);
 569   
 570          if (!$fresh && $this->container->has('cache_warmer')) {
 571              $this->container->get('cache_warmer')->warmUp($this->container->getParameter('kernel.cache_dir'));
 572          }
 573      }
 574   
 575      /**
 576       * Returns the kernel parameters.
 577       *
 578       * @return array An array of kernel parameters
 579       */
 580      protected function getKernelParameters()
 581      {
 582          $bundles = array();
 583          foreach ($this->bundles as $name => $bundle) {
 584              $bundles[$name] = get_class($bundle);
 585          }
 586   
 587          return array_merge(
 588              array(
 589                  'kernel.root_dir'        => $this->rootDir,
 590                  'kernel.environment'     => $this->environment,
 591                  'kernel.debug'           => $this->debug,
 592                  'kernel.name'            => $this->name,
 593                  'kernel.cache_dir'       => $this->getCacheDir(),
 594                  'kernel.logs_dir'        => $this->getLogDir(),
 595                  'kernel.bundles'         => $bundles,
 596                  'kernel.charset'         => $this->getCharset(),
 597                  'kernel.container_class' => $this->getContainerClass(),
 598              ),
 599              $this->getEnvParameters()
 600          );
 601      }
 602   
 603      /**
 604       * Gets the environment parameters.
 605       *
 606       * Only the parameters starting with "SYMFONY__" are considered.
 607       *
 608       * @return array An array of parameters
 609       */
 610      protected function getEnvParameters()
 611      {
 612          $parameters = array();
 613          foreach ($_SERVER as $key => $value) {
 614              if (0 === strpos($key, 'SYMFONY__')) {
 615                  $parameters[strtolower(str_replace('__', '.', substr($key, 9)))] = $value;
 616              }
 617          }
 618   
 619          return $parameters;
 620      }
 621   
 622      /**
 623       * Builds the service container.
 624       *
 625       * @return ContainerBuilder The compiled service container
 626       *
 627       * @throws \RuntimeException
 628       */
 629      protected function buildContainer()
 630      {
 631          foreach (array('cache' => $this->getCacheDir(), 'logs' => $this->getLogDir()) as $name => $dir) {
 632              if (!is_dir($dir)) {
 633                  if (false === @mkdir($dir, 0777, true)) {
 634                      throw new \RuntimeException(sprintf("Unable to create the %s directory (%s)\n", $name, $dir));
 635                  }
 636              } elseif (!is_writable($dir)) {
 637                  throw new \RuntimeException(sprintf("Unable to write in the %s directory (%s)\n", $name, $dir));
 638              }
 639          }
 640   
 641          $container = $this->getContainerBuilder();
 642          $container->addObjectResource($this);
 643          $this->prepareContainer($container);
 644   
 645          if (null !== $cont = $this->registerContainerConfiguration($this->getContainerLoader($container))) {
 646              $container->merge($cont);
 647          }
 648   
 649          $container->addCompilerPass(new AddClassesToCachePass($this));
 650   
 651          return $container;
 652      }
 653   
 654      /**
 655       * Prepares the ContainerBuilder before it is compiled.
 656       *
 657       * @param ContainerBuilder $container A ContainerBuilder instance
 658       */
 659      protected function prepareContainer(ContainerBuilder $container)
 660      {
 661          $extensions = array();
 662          foreach ($this->bundles as $bundle) {
 663              if ($extension = $bundle->getContainerExtension()) {
 664                  $container->registerExtension($extension);
 665                  $extensions[] = $extension->getAlias();
 666              }
 667   
 668              if ($this->debug) {
 669                  $container->addObjectResource($bundle);
 670              }
 671          }
 672          foreach ($this->bundles as $bundle) {
 673              $bundle->build($container);
 674          }
 675   
 676          // ensure these extensions are implicitly loaded
 677          $container->getCompilerPassConfig()->setMergePass(new MergeExtensionConfigurationPass($extensions));
 678      }
 679   
 680      /**
 681       * Gets a new ContainerBuilder instance used to build the service container.
 682       *
 683       * @return ContainerBuilder
 684       */
 685      protected function getContainerBuilder()
 686      {
 687          $container = new ContainerBuilder(new ParameterBag($this->getKernelParameters()));
 688   
 689          if (class_exists('ProxyManager\Configuration')) {
 690              $container->setProxyInstantiator(new RuntimeInstantiator());
 691          }
 692   
 693          return $container;
 694      }
 695   
 696      /**
 697       * Dumps the service container to PHP code in the cache.
 698       *
 699       * @param ConfigCache      $cache     The config cache
 700       * @param ContainerBuilder $container The service container
 701       * @param string           $class     The name of the class to generate
 702       * @param string           $baseClass The name of the container's base class
 703       */
 704      protected function dumpContainer(ConfigCache $cache, ContainerBuilder $container, $class, $baseClass)
 705      {
 706          // cache the container
 707          $dumper = new PhpDumper($container);
 708   
 709          if (class_exists('ProxyManager\Configuration')) {
 710              $dumper->setProxyDumper(new ProxyDumper());
 711          }
 712   
 713          $content = $dumper->dump(array('class' => $class, 'base_class' => $baseClass));
 714          if (!$this->debug) {
 715              $content = static::stripComments($content);
 716          }
 717   
 718          $cache->write($content, $container->getResources());
 719      }
 720   
 721      /**
 722       * Returns a loader for the container.
 723       *
 724       * @param ContainerInterface $container The service container
 725       *
 726       * @return DelegatingLoader The loader
 727       */
 728      protected function getContainerLoader(ContainerInterface $container)
 729      {
 730          $locator = new FileLocator($this);
 731          $resolver = new LoaderResolver(array(
 732              new XmlFileLoader($container, $locator),
 733              new YamlFileLoader($container, $locator),
 734              new IniFileLoader($container, $locator),
 735              new PhpFileLoader($container, $locator),
 736              new ClosureLoader($container),
 737          ));
 738   
 739          return new DelegatingLoader($resolver);
 740      }
 741   
 742      /**
 743       * Removes comments from a PHP source string.
 744       *
 745       * We don't use the PHP php_strip_whitespace() function
 746       * as we want the content to be readable and well-formatted.
 747       *
 748       * @param string $source A PHP string
 749       *
 750       * @return string The PHP string with the comments removed
 751       */
 752      public static function stripComments($source)
 753      {
 754          if (!function_exists('token_get_all')) {
 755              return $source;
 756          }
 757   
 758          $rawChunk = '';
 759          $output = '';
 760          $tokens = token_get_all($source);
 761          $ignoreSpace = false;
 762          for (reset($tokens); false !== $token = current($tokens); next($tokens)) {
 763              if (is_string($token)) {
 764                  $rawChunk .= $token;
 765              } elseif (T_START_HEREDOC === $token[0]) {
 766                  $output .= $rawChunk.$token[1];
 767                  do {
 768                      $token = next($tokens);
 769                      $output .= $token[1];
 770                  } while ($token[0] !== T_END_HEREDOC);
 771                  $rawChunk = '';
 772              } elseif (T_WHITESPACE === $token[0]) {
 773                  if ($ignoreSpace) {
 774                      $ignoreSpace = false;
 775   
 776                      continue;
 777                  }
 778   
 779                  // replace multiple new lines with a single newline
 780                  $rawChunk .= preg_replace(array('/\n{2,}/S'), "\n", $token[1]);
 781              } elseif (in_array($token[0], array(T_COMMENT, T_DOC_COMMENT))) {
 782                  $ignoreSpace = true;
 783              } else {
 784                  $rawChunk .= $token[1];
 785   
 786                  // The PHP-open tag already has a new-line
 787                  if (T_OPEN_TAG === $token[0]) {
 788                      $ignoreSpace = true;
 789                  }
 790              }
 791          }
 792   
 793          $output .= $rawChunk;
 794   
 795          return $output;
 796      }
 797   
 798      public function serialize()
 799      {
 800          return serialize(array($this->environment, $this->debug));
 801      }
 802   
 803      public function unserialize($data)
 804      {
 805          list($environment, $debug) = unserialize($data);
 806   
 807          $this->__construct($environment, $debug);
 808      }
 809  }
 810