├── .gitignore ├── .travis.yml ├── Autoload ├── CodeIgniterClassLoader.php ├── ComposerLoaderAwareInterface.php └── LegacyClassLoaderInterface.php ├── Command └── AssetsInstallCommand.php ├── DependencyInjection ├── Compiler │ ├── KernelConfigurationPass.php │ ├── LoaderInjectorPass.php │ └── ReplaceRouterPass.php ├── Configuration.php └── TheodoEvolutionLegacyWrapperExtension.php ├── EventListener ├── LegacyBooterListener.php └── RouterListener.php ├── Exception └── CodeIgniterException.php ├── HttpKernel └── EvolutionKernel.php ├── Kernel ├── CodeIgniterKernel.php ├── Event │ └── LegacyKernelBootEvent.php ├── LegacyKernel.php ├── LegacyKernelEvents.php ├── LegacyKernelInterface.php └── Symfony14Kernel.php ├── README.md ├── Resources ├── config │ └── services.xml └── doc │ ├── autoloading.rst │ ├── codeigniter.rst │ ├── codeignitertroubleshooting.md │ ├── customkernel.rst │ ├── index.rst │ └── symfony14.rst ├── Tests ├── DependencyInjection │ ├── Compiler │ │ └── KernelConfigurationPassTest.php │ └── ConfigurationTest.php ├── EventListener │ └── RouterListenerTest.php ├── Kernel │ ├── CodeIgniterKernelTest.php │ └── Symfony14KernelTest.php └── bootstrap.php ├── TheodoEvolutionLegacyWrapperBundle.php ├── composer.json └── phpunit.xml.dist /.gitignore: -------------------------------------------------------------------------------- 1 | composer.lock 2 | phpunit.xml 3 | vendor/* 4 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: php 2 | 3 | sudo: false 4 | 5 | php: 6 | - 5.5 7 | - 5.6 8 | 9 | env: 10 | global: 11 | - SYMFONY_VERSION=3.4.* 12 | 13 | matrix: 14 | include: 15 | - php: 5.6 16 | env: SYMFONY_VERSION=2.7.* 17 | - php: 5.6 18 | env: SYMFONY_VERSION=2.8.* 19 | - php: 5.6 20 | env: SYMFONY_VERSION=3.4.* 21 | - php: 7.0 22 | env: SYMFONY_VERSION=3.4.* 23 | - php: 7.1 24 | env: SYMFONY_VERSION=3.4.* 25 | - php: 5.6 26 | env: SYMFONY_VERSION=dev-master 27 | - php: hhvm-3.18 28 | sudo: required 29 | group: edge 30 | env: SYMFONY_VERSION=3.4.* 31 | fast_finish: true 32 | allow_failures: 33 | - env: SYMFONY_VERSION=dev-master 34 | 35 | before_script: 36 | - mkdir -p ~/.phpenv/versions/$(phpenv version-name)/etc/conf.d && echo "memory_limit=-1" >> ~/.phpenv/versions/$(phpenv version-name)/etc/conf.d/travis.ini 37 | - composer self-update 38 | - composer require symfony/symfony:${SYMFONY_VERSION} --no-update 39 | - composer update --dev 40 | 41 | script: ./vendor/bin/phpunit --coverage-text 42 | 43 | notifications: 44 | email: 45 | - open-source@theodo.fr 46 | -------------------------------------------------------------------------------- /Autoload/CodeIgniterClassLoader.php: -------------------------------------------------------------------------------- 1 | 12 | */ 13 | class CodeIgniterClassLoader implements LegacyClassLoaderInterface 14 | { 15 | /** 16 | * @var boolean 17 | */ 18 | private $isAutoloaded = false; 19 | 20 | /** 21 | * @var LegacyKernelInterface 22 | */ 23 | private $kernel; 24 | 25 | /** 26 | * Autoload the legacy code. 27 | * 28 | * @return void 29 | */ 30 | public function autoload() 31 | { 32 | // Load the global functions 33 | require_once(BASEPATH . 'core/Common.php'); 34 | 35 | // Load the framework constants 36 | if (defined('ENVIRONMENT') AND file_exists(APPPATH . 'config/' . ENVIRONMENT . '/constants.php')) { 37 | require_once(APPPATH . 'config/' . ENVIRONMENT . '/constants.php'); 38 | } else { 39 | require_once(APPPATH . 'config/constants.php'); 40 | } 41 | 42 | // Set the subclass_prefix 43 | if (isset($assign_to_config['subclass_prefix']) AND $assign_to_config['subclass_prefix'] != '') { 44 | get_config(array('subclass_prefix' => $assign_to_config['subclass_prefix'])); 45 | } 46 | 47 | // Set a liberal script execution time limit 48 | if (function_exists("set_time_limit") == true AND @ini_get("safe_mode") == 0) { 49 | @set_time_limit(300); 50 | } 51 | 52 | // Start the timer... tick tock tick tock... 53 | $BM = load_class('Benchmark', 'core'); 54 | $BM->mark('total_execution_time_start'); 55 | $BM->mark('loading_time:_base_classes_start'); 56 | $GLOBALS['BM'] = $BM; 57 | $this->kernel->getContainer()->set('BM', $BM); 58 | 59 | // Instantiate the hooks class 60 | $EXT = load_class('Hooks', 'core'); 61 | $GLOBALS['EXT'] = $EXT; 62 | $this->kernel->getContainer()->set('EXT', $EXT); 63 | 64 | // Is there a "pre_system" hook? 65 | $EXT->_call_hook('pre_system'); 66 | 67 | // Instantiate the config class 68 | $CFG = load_class('Config', 'core'); 69 | $GLOBALS['CFG'] = $CFG; 70 | $this->kernel->getContainer()->set('CFG', $CFG); 71 | 72 | // Do we have any manually set config items in the index.php file? 73 | if (isset($assign_to_config)) { 74 | $CFG->_assign_to_config($assign_to_config); 75 | } 76 | 77 | // Instantiate the UTF-8 class 78 | $UNI = load_class('Utf8', 'core'); 79 | $GLOBALS['UNI'] = $UNI; 80 | $this->kernel->getContainer()->set('UNI', $UNI); 81 | 82 | // Instantiate the URI class 83 | $URI = load_class('URI', 'core'); 84 | $GLOBALS['URI'] = $URI; 85 | $this->kernel->getContainer()->set('URI', $URI); 86 | 87 | // Instantiate the routing class and set the routing 88 | $RTR = load_class('Router', 'core'); 89 | $RTR->_set_routing(); 90 | $GLOBALS['RTR'] =$RTR; 91 | $this->kernel->getContainer()->set('RTR', $RTR); 92 | 93 | // Set any routing overrides that may exist in the main index file 94 | if (isset($routing)) { 95 | $RTR->_set_overrides($routing); 96 | } 97 | 98 | // Instantiate the output class 99 | $OUT = load_class('Output', 'core'); 100 | $GLOBALS['OUT'] = $OUT; 101 | $this->kernel->getContainer()->set('OUT', $OUT); 102 | 103 | // Is there a valid cache file? If so, we're done... 104 | if ($EXT->_call_hook('cache_override') === false) { 105 | if ($OUT->_display_cache($CFG, $URI) == true) { 106 | exit; 107 | } 108 | } 109 | 110 | // Load the security class for xss and csrf support 111 | $SEC = load_class('Security', 'core'); 112 | $GLOBALS['SEC'] = $SEC; 113 | $this->kernel->getContainer()->set('SEC', $SEC); 114 | 115 | // Load the Input class and sanitize globals 116 | $IN = load_class('Input', 'core'); 117 | $GLOBALS['IN'] = $IN; 118 | $this->kernel->getContainer()->set('IN', $IN); 119 | 120 | // Load the Language class 121 | $LANG = load_class('Lang', 'core'); 122 | $GLOBALS['LANG'] = $LANG; 123 | $this->kernel->getContainer()->set('LANG', $LANG); 124 | 125 | // Load the app controller and local controller 126 | require_once BASEPATH . 'core/Controller.php'; 127 | 128 | $this->isAutoloaded = true; 129 | } 130 | 131 | /** 132 | * Check whether the legacy is already autoloaded. 133 | * 134 | * @return bool 135 | */ 136 | public function isAutoloaded() 137 | { 138 | return $this->isAutoloaded; 139 | } 140 | 141 | /** 142 | * {@inheritdoc} 143 | * 144 | * @throws \InvalidArgumentException 145 | */ 146 | public function setKernel(LegacyKernelInterface $kernel) 147 | { 148 | if (!$kernel instanceof CodeIgniterKernel) { 149 | throw new \InvalidArgumentException(sprintf('The "%s" expects a CodeIgniterKernel, "%s" given', __CLASS__, get_class($kernel))); 150 | } 151 | 152 | $this->kernel = $kernel; 153 | } 154 | 155 | } 156 | -------------------------------------------------------------------------------- /Autoload/ComposerLoaderAwareInterface.php: -------------------------------------------------------------------------------- 1 | 11 | */ 12 | interface ComposerLoaderAwareInterface 13 | { 14 | /** 15 | * @param ClassLoader $loader 16 | * @return mixed 17 | */ 18 | public function setLoader(ClassLoader $loader); 19 | } 20 | -------------------------------------------------------------------------------- /Autoload/LegacyClassLoaderInterface.php: -------------------------------------------------------------------------------- 1 | 11 | */ 12 | interface LegacyClassLoaderInterface 13 | { 14 | /** 15 | * Autoload the legacy code. 16 | * 17 | * @return void 18 | */ 19 | public function autoload(); 20 | 21 | /** 22 | * Check whether the legacy is already autoloaded. 23 | * 24 | * @return bool 25 | */ 26 | public function isAutoloaded(); 27 | 28 | /** 29 | * Inject the kernel into the class looader. 30 | * 31 | * @param LegacyKernelInterface $kernel 32 | */ 33 | public function setKernel(LegacyKernelInterface $kernel); 34 | } 35 | -------------------------------------------------------------------------------- /Command/AssetsInstallCommand.php: -------------------------------------------------------------------------------- 1 | 17 | */ 18 | class AssetsInstallCommand extends ContainerAwareCommand 19 | { 20 | /** 21 | * {@inheritdoc} 22 | */ 23 | protected function configure() 24 | { 25 | $this 26 | ->setName('legacy:assets:install') 27 | ->setDescription('Installs legacy web assets under a public web directory') 28 | ->addArgument('target', InputArgument::OPTIONAL, 'The target directory', 'web') 29 | ->addOption('symlink', null, InputOption::VALUE_NONE, 'Symlinks the assets instead of copying it') 30 | ->addOption('relative', null, InputOption::VALUE_NONE, 'Make relative symlinks') 31 | ->setHelp(<<%command.name% command installs legacy assets into a given 33 | directory (e.g. the web directory). 34 | 35 | php %command.full_name% web 36 | 37 | A "bundles" directory will be created inside the target directory, and the 38 | listed directories from the configuration file will be copied into it. 39 | 40 | To create a symlink to each bundle instead of copying its assets, use the 41 | --symlink option: 42 | 43 | php %command.full_name% web --symlink 44 | 45 | To make symlink relative, add the --relative option: 46 | 47 | php %command.full_name% web --symlink --relative 48 | TEXT 49 | ) 50 | ; 51 | } 52 | 53 | /** 54 | * {@inheritdoc} 55 | */ 56 | protected function execute(InputInterface $input, OutputInterface $output) 57 | { 58 | $targetArg = rtrim($input->getArgument('target'), '/'); 59 | 60 | if (!is_dir($targetArg)) { 61 | throw new \InvalidArgumentException(sprintf('The target directory "%s" does not exist.', $input->getArgument('target'))); 62 | } 63 | 64 | if (!function_exists('symlink') && $input->getOption('symlink')) { 65 | throw new \InvalidArgumentException('The symlink() function is not available on your system. You need to install the assets without the --symlink option.'); 66 | } 67 | 68 | $output->writeln(sprintf('Installing legacy assets as %s', $input->getOption('symlink') ? 'symlinks' : 'hard copies')); 69 | 70 | /** @var LegacyKernelInterface $kernel */ 71 | $kernel = $this->getContainer()->get('theodo_evolution_legacy_wrapper.legacy_kernel'); 72 | 73 | foreach ($this->getContainer()->getParameter('theodo_evolution_legacy_wrapper.assets') as $group) { 74 | $this->installGroup($group, $kernel, $targetArg, $input, $output); 75 | } 76 | } 77 | 78 | private function installGroup($group, $kernel, $target, InputInterface $input, OutputInterface $output) 79 | { 80 | $filesystem = $this->getContainer()->get('filesystem'); 81 | 82 | if (false === strpos($group['base'], $kernel->getRootDir())) { 83 | $groupDir = $kernel->getRootDir().'/'.$group['base']; 84 | } else { 85 | $groupDir = $group['base']; 86 | } 87 | 88 | if (!is_dir($groupDir)) { 89 | throw new \InvalidArgumentException('The base directory does not exists.'); 90 | } 91 | 92 | foreach ($group['directories'] as $directory) { 93 | if (is_dir($originDir = $groupDir.'/'.$directory)) { 94 | $targetDir = $target.'/'.$directory; 95 | 96 | $output->writeln(sprintf('Installing assets for %s into %s', $originDir, $targetDir)); 97 | 98 | $filesystem->remove($targetDir); 99 | 100 | if ($input->getOption('symlink')) { 101 | if ($input->getOption('relative')) { 102 | $relativeOriginDir = $filesystem->makePathRelative($originDir, realpath($target)); 103 | } else { 104 | $relativeOriginDir = $originDir; 105 | } 106 | $filesystem->symlink($relativeOriginDir, $targetDir); 107 | } else { 108 | $filesystem->mkdir($targetDir, 0777); 109 | // We use a custom iterator to ignore VCS files 110 | $filesystem->mirror($originDir, $targetDir, Finder::create()->ignoreDotFiles(false)->in($originDir)); 111 | } 112 | } 113 | } 114 | } 115 | } 116 | -------------------------------------------------------------------------------- /DependencyInjection/Compiler/KernelConfigurationPass.php: -------------------------------------------------------------------------------- 1 | 13 | */ 14 | class KernelConfigurationPass implements CompilerPassInterface 15 | { 16 | /** 17 | * You can modify the container here before it is dumped to PHP code. 18 | * 19 | * @param ContainerBuilder $container 20 | * 21 | * @api 22 | */ 23 | public function process(ContainerBuilder $container) 24 | { 25 | $kernelId = $container->getParameter('theodo_evolution_legacy_wrapper.legacy_kernel.id'); 26 | $kernelOptions = $container->getParameter('theodo_evolution_legacy_wrapper.legacy_kernel.options'); 27 | $classLoaderId = $container->getParameter('theodo_evolution_legacy_wrapper.autoload.class_loader.id'); 28 | $container->setAlias('theodo_evolution_legacy_wrapper.legacy_kernel', $kernelId); 29 | 30 | if (!empty($kernelOptions)) { 31 | $definition = $container->findDefinition($kernelId); 32 | $definition->addMethodCall('setOptions', array($kernelOptions)); 33 | } 34 | 35 | if($classLoaderId) { 36 | $definition = $container->findDefinition($kernelId); 37 | $definition->addMethodCall('setClassLoader', array(new Reference($classLoaderId))); 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /DependencyInjection/Compiler/LoaderInjectorPass.php: -------------------------------------------------------------------------------- 1 | 13 | */ 14 | class LoaderInjectorPass implements CompilerPassInterface 15 | { 16 | /** 17 | * @var \Composer\Autoload\ClassLoader 18 | */ 19 | private $loader; 20 | 21 | /** 22 | * @param ClassLoader $loader 23 | */ 24 | public function __construct(ClassLoader $loader) 25 | { 26 | $this->loader = $loader; 27 | } 28 | 29 | /** 30 | * {@inheritdoc} 31 | */ 32 | public function process(ContainerBuilder $container) 33 | { 34 | // Inject composer.loader into tagged "loader_aware" services 35 | $taggedServices = $container->findTaggedServiceIds('loader_aware'); 36 | foreach ($taggedServices as $id => $attributes) { 37 | $container->getDefinition($id)->addMethodCall('setLoader', array(new Reference('composer.loader'))); 38 | } 39 | } 40 | 41 | } 42 | -------------------------------------------------------------------------------- /DependencyInjection/Compiler/ReplaceRouterPass.php: -------------------------------------------------------------------------------- 1 | 12 | */ 13 | class ReplaceRouterPass implements CompilerPassInterface 14 | { 15 | /** 16 | * You can modify the container here before it is dumped to PHP code. 17 | * 18 | * @param ContainerBuilder $container 19 | * 20 | * @api 21 | */ 22 | public function process(ContainerBuilder $container) 23 | { 24 | if (true === $container->hasDefinition('theodo_evolution_legacy_wrapper.router_listener')) { 25 | $routerListener = $container->getDefinition('router_listener'); 26 | 27 | $definition = $container->getDefinition('theodo_evolution_legacy_wrapper.router_listener'); 28 | $definition->replaceArgument(1, $routerListener); 29 | 30 | $container->setAlias('router_listener', 'theodo_evolution_legacy_wrapper.router_listener'); 31 | } 32 | } 33 | } -------------------------------------------------------------------------------- /DependencyInjection/Configuration.php: -------------------------------------------------------------------------------- 1 | root('theodo_evolution_legacy_wrapper'); 22 | 23 | $rootNode 24 | ->children() 25 | ->scalarNode('root_dir') 26 | ->info('The path where the legacy app lives') 27 | ->isRequired() 28 | ->end() 29 | ->append($this->addKernelNode()) 30 | ->scalarNode('class_loader_id')->end() 31 | ->arrayNode('assets') 32 | ->canBeUnset() 33 | ->useAttributeAsKey('name') 34 | ->prototype('array') 35 | ->children() 36 | ->scalarNode('base')->isRequired()->end() 37 | ->arrayNode('directories') 38 | ->example(array('css', 'js', 'images')) 39 | ->beforeNormalization() 40 | ->ifTrue(function ($v) { return !is_array($v); }) 41 | ->then(function ($v) { return array($v); }) 42 | ->end() 43 | ->prototype('scalar') 44 | ->end() 45 | ->end() 46 | ->end() 47 | ->end() 48 | ->end(); 49 | 50 | return $treeBuilder; 51 | } 52 | 53 | public function addKernelNode() 54 | { 55 | $builder = new TreeBuilder(); 56 | $node = $builder->root('kernel'); 57 | 58 | $node 59 | ->example('theodo_evolution_legacy_wrapper.legacy_kernel.symfony14') 60 | ->beforeNormalization() 61 | ->ifString() 62 | ->then(function($v) { return array('id'=> $v); }) 63 | ->end() 64 | ->children() 65 | ->scalarNode('id')->end() 66 | ->arrayNode('options') 67 | ->children() 68 | // Symfony 1.4 options 69 | ->scalarNode('application')->end() 70 | ->scalarNode('environment')->end() 71 | ->scalarNode('debug')->end() 72 | ->end() 73 | ->prototype('scalar')->end() 74 | ->end() 75 | ->end() 76 | ->validate() 77 | ->ifTrue(function($v) { 78 | // Validate symfony 1 configuration 79 | if (strpos($v['id'], 'symfony1')) { 80 | return !isset( 81 | $v['options']['application'], 82 | $v['options']['environment'], 83 | $v['options']['debug'] 84 | ); 85 | } 86 | }) 87 | ->thenInvalid('To use the symfony1 kernel you must set an application, environment and debug options.') 88 | ->end() 89 | ->validate() 90 | ->ifTrue(function($v) { 91 | // Validate CodeIgniter configuration 92 | if (strpos($v['id'], 'codeigniter')) { 93 | return !isset( 94 | $v['options']['environment'], 95 | $v['options']['version'], 96 | $v['options']['core'] 97 | ); 98 | } 99 | }) 100 | ->thenInvalid('To use the codeigniter kernel you must set an environment a version and a core options.') 101 | ->end() 102 | ; 103 | 104 | return $node; 105 | } 106 | } 107 | -------------------------------------------------------------------------------- /DependencyInjection/TheodoEvolutionLegacyWrapperExtension.php: -------------------------------------------------------------------------------- 1 | processConfiguration($configuration, $configs); 24 | 25 | $loader = new Loader\XmlFileLoader($container, new FileLocator(__DIR__.'/../Resources/config')); 26 | $loader->load('services.xml'); 27 | 28 | $container->register('composer.loader', 'Composer\Autoload\ClassLoader'); 29 | 30 | $container->setParameter('theodo_evolution_legacy_wrapper.root_dir', $config['root_dir']); 31 | $container->setParameter('theodo_evolution_legacy_wrapper.assets', $config['assets']); 32 | $container->setParameter('theodo_evolution_legacy_wrapper.legacy_kernel.id', $config['kernel']['id']); 33 | $container->setParameter('theodo_evolution_legacy_wrapper.legacy_kernel.options', isset($config['kernel']['options']) ? $config['kernel']['options'] : array()); 34 | $container->setParameter('theodo_evolution_legacy_wrapper.autoload.class_loader.id', isset($config['class_loader_id']) ? $config['class_loader_id'] : null); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /EventListener/LegacyBooterListener.php: -------------------------------------------------------------------------------- 1 | 15 | */ 16 | class LegacyBooterListener implements EventSubscriberInterface 17 | { 18 | /** 19 | * @var \Theodo\Evolution\Bundle\LegacyWrapperBundle\Kernel\LegacyKernelInterface 20 | */ 21 | private $kernel; 22 | 23 | /** 24 | * @var \Symfony\Component\DependencyInjection\ContainerInterface 25 | */ 26 | private $container; 27 | 28 | /** 29 | * @param LegacyKernelInterface $kernel 30 | * @param ContainerInterface $container 31 | */ 32 | public function __construct(LegacyKernelInterface $kernel, ContainerInterface $container) 33 | { 34 | $this->kernel = $kernel; 35 | $this->container = $container; 36 | } 37 | 38 | /** 39 | * @param GetResponseEvent $event 40 | */ 41 | public function onKernelRequest(GetResponseEvent $event) 42 | { 43 | if (!$this->kernel->isBooted()) { 44 | $this->kernel->boot($this->container); 45 | } 46 | } 47 | 48 | /** 49 | * Returns an array of event names this subscriber wants to listen to. 50 | * 51 | * The array keys are event names and the value can be: 52 | * 53 | * * The method name to call (priority defaults to 0) 54 | * * An array composed of the method name to call and the priority 55 | * * An array of arrays composed of the method names to call and respective 56 | * priorities, or 0 if unset 57 | * 58 | * For instance: 59 | * 60 | * * array('eventName' => 'methodName') 61 | * * array('eventName' => array('methodName', $priority)) 62 | * * array('eventName' => array(array('methodName1', $priority), array('methodName2')) 63 | * 64 | * @return array The event names to listen to 65 | * 66 | * @api 67 | */ 68 | public static function getSubscribedEvents() 69 | { 70 | return array( 71 | KernelEvents::REQUEST => array('onKernelRequest', '35') 72 | ); 73 | } 74 | 75 | } 76 | -------------------------------------------------------------------------------- /EventListener/RouterListener.php: -------------------------------------------------------------------------------- 1 | 21 | */ 22 | class RouterListener implements EventSubscriberInterface 23 | { 24 | /** 25 | * @var \Theodo\Evolution\Bundle\LegacyWrapperBundle\Kernel\LegacyKernelInterface 26 | */ 27 | protected $legacyKernel; 28 | 29 | /** 30 | * @var RouterListener 31 | */ 32 | protected $routerListener; 33 | 34 | /** 35 | * @var \Symfony\Component\HttpKernel\Log\LoggerInterface 36 | */ 37 | protected $logger; 38 | 39 | /** 40 | * @param LegacyKernelInterface $legacyKernel 41 | * @param SymfonyRouterListener $routerListener 42 | * @param LoggerInterface $logger 43 | */ 44 | public function __construct(LegacyKernelInterface $legacyKernel, SymfonyRouterListener $routerListener, LoggerInterface $logger = null) 45 | { 46 | $this->legacyKernel = $legacyKernel; 47 | $this->routerListener = $routerListener; 48 | $this->logger = $logger; 49 | } 50 | 51 | /** 52 | * @param GetResponseEvent $event 53 | * 54 | * @return GetResponseEvent 55 | */ 56 | public function onKernelRequest(GetResponseEvent $event) 57 | { 58 | try { 59 | $this->routerListener->onKernelRequest($event); 60 | } catch (NotFoundHttpException $e) { 61 | if (null !== $this->logger) { 62 | $this->logger->info('Request handled by the '.$this->legacyKernel->getName().' kernel.'); 63 | } 64 | 65 | $response = $this->legacyKernel->handle($event->getRequest(), $event->getRequestType(), true); 66 | if ($response->getStatusCode() !== 404) { 67 | $event->setResponse($response); 68 | 69 | return $event; 70 | } 71 | } 72 | } 73 | 74 | /** 75 | * @param FinishRequestEvent $event 76 | */ 77 | public function onKernelFinishRequest(FinishRequestEvent $event) 78 | { 79 | $this->routerListener->onKernelFinishRequest($event); 80 | } 81 | 82 | /** 83 | * @{inheritdoc} 84 | */ 85 | public static function getSubscribedEvents() 86 | { 87 | $listeners = array( 88 | KernelEvents::REQUEST => array(array('onKernelRequest', 31)), 89 | ); 90 | 91 | if (defined('\Symfony\Component\HttpKernel\KernelEvents::FINISH_REQUEST')) { 92 | $listeners[KernelEvents::FINISH_REQUEST] = array(array('onKernelFinishRequest', 0)); 93 | } 94 | 95 | return $listeners; 96 | } 97 | } 98 | -------------------------------------------------------------------------------- /Exception/CodeIgniterException.php: -------------------------------------------------------------------------------- 1 | 9 | */ 10 | class CodeIgniterException extends \RuntimeException 11 | { 12 | 13 | } 14 | -------------------------------------------------------------------------------- /HttpKernel/EvolutionKernel.php: -------------------------------------------------------------------------------- 1 | 12 | */ 13 | abstract class EvolutionKernel extends Kernel 14 | { 15 | /** 16 | * @var ClassLoader 17 | */ 18 | protected $loader; 19 | 20 | /** 21 | * Overrides the parent method to add the loader to the container. 22 | * 23 | * {@inheritdoc} 24 | */ 25 | protected function initializeContainer() 26 | { 27 | parent::initializeContainer(); 28 | 29 | $this->container->set('composer.loader', $this->loader); 30 | } 31 | 32 | /** 33 | * @param ClassLoader $loader 34 | */ 35 | public function setLoader(ClassLoader $loader) 36 | { 37 | $this->loader = $loader; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /Kernel/CodeIgniterKernel.php: -------------------------------------------------------------------------------- 1 | getSession(); 28 | if ($session->isStarted()) { 29 | $session->save(); 30 | } 31 | 32 | $response = new Response(); 33 | 34 | global $CFG, $RTR, $BM, $EXT, $CI, $URI, $OUT; 35 | 36 | ob_start(); 37 | 38 | // Set the error handler of CodeIgniter 39 | set_error_handler('_exception_handler'); 40 | 41 | // Load the app controller and local controller 42 | require_once BASEPATH . 'core/Controller.php'; 43 | 44 | if (file_exists(APPPATH . 'core/' . $CFG->config['subclass_prefix'] . 'Controller.php')) { 45 | require_once APPPATH . 'core/' . $CFG->config['subclass_prefix'] . 'Controller.php'; 46 | } 47 | 48 | // Load the local application controller 49 | // Note: The Router class automatically validates the controller path using the router->_validate_request(). 50 | // If this include fails it means that the default controller in the Routes.php file is not resolving to something valid. 51 | if (!file_exists(APPPATH . 'controllers/' . $RTR->fetch_directory() . $RTR->fetch_class() . '.php')) { 52 | throw new CodeIgniterException('Unable to load your default controller. Please make sure the controller specified in your Routes.php file is valid.'); 53 | } 54 | 55 | include(APPPATH . 'controllers/' . $RTR->fetch_directory() . $RTR->fetch_class() . '.php'); 56 | 57 | // Set a mark point for benchmarking 58 | $BM->mark('loading_time:_base_classes_end'); 59 | 60 | // Security check 61 | $class = $RTR->fetch_class(); 62 | $method = $RTR->fetch_method(); 63 | 64 | if (!class_exists($class) 65 | OR strncmp($method, '_', 1) == 0 66 | OR in_array(strtolower($method), array_map('strtolower', get_class_methods('CI_Controller'))) 67 | ) { 68 | if (!empty($RTR->routes['404_override'])) { 69 | $x = explode('/', $RTR->routes['404_override']); 70 | $class = $x[0]; 71 | $method = (isset($x[1]) ? $x[1] : 'index'); 72 | if (!class_exists($class)) { 73 | if (!file_exists(APPPATH . 'controllers/' . $class . '.php')) { 74 | $response->setStatusCode(404); 75 | $response->setContent("The {$class}/{$method} does not exist in CodeIgniter."); 76 | } 77 | 78 | include_once(APPPATH . 'controllers/' . $class . '.php'); 79 | } 80 | } else { 81 | $response->setStatusCode(404); 82 | $response->setContent("The {$class}/{$method} does not exist in CodeIgniter."); 83 | } 84 | } 85 | 86 | // Is there a "pre_controller" hook? 87 | $EXT->_call_hook('pre_controller'); 88 | 89 | // Instantiate the requested controller 90 | // Mark a start point so we can benchmark the controller 91 | $BM->mark('controller_execution_time_( ' . $class . ' / ' . $method . ' )_start'); 92 | 93 | $CI = new $class(); 94 | 95 | // Is there a "post_controller_constructor" hook? 96 | $EXT->_call_hook('post_controller_constructor'); 97 | 98 | // Call the requested method 99 | // Is there a "remap" function? If so, we call it instead 100 | if (method_exists($CI, '_remap')) { 101 | $CI->_remap($method, array_slice($URI->rsegments, 2)); 102 | } else { 103 | // is_callable() returns TRUE on some versions of PHP 5 for private and protected 104 | // methods, so we'll use this workaround for consistent behavior 105 | if (!in_array(strtolower($method), array_map('strtolower', get_class_methods($CI)))) { 106 | // Check and see if we are using a 404 override and use it. 107 | if (!empty($RTR->routes['404_override'])) { 108 | $x = explode('/', $RTR->routes['404_override']); 109 | $class = $x[0]; 110 | $method = (isset($x[1]) ? $x[1] : 'index'); 111 | if (!class_exists($class)) { 112 | if (!file_exists(APPPATH . 'controllers/' . $class . '.php')) { 113 | $response->setStatusCode(404); 114 | $response->setContent("The {$class}/{$method} does not exist in CodeIgniter."); 115 | } 116 | 117 | include_once(APPPATH . 'controllers/' . $class . '.php'); 118 | unset($CI); 119 | $CI = new $class(); 120 | } 121 | } else { 122 | $response->setStatusCode(404); 123 | $response->setContent("The {$class}/{$method} does not exist in CodeIgniter."); 124 | } 125 | } 126 | 127 | // Call the requested method. 128 | // Any URI segments present (besides the class/function) will be passed to the method for convenience 129 | call_user_func_array(array(&$CI, $method), array_slice($URI->rsegments, 2)); 130 | } 131 | 132 | // Mark a benchmark end point 133 | $BM->mark('controller_execution_time_( ' . $class . ' / ' . $method . ' )_end'); 134 | 135 | // Is there a "post_controller" hook? 136 | $EXT->_call_hook('post_controller'); 137 | 138 | // Send the final rendered output to the browser 139 | if ($EXT->_call_hook('display_override') === false) { 140 | $OUT->_display(); 141 | } 142 | 143 | // Is there a "post_system" hook? 144 | $EXT->_call_hook('post_system'); 145 | 146 | // Close the DB connection if one exists 147 | if (class_exists('CI_DB') AND isset($CI->db)) { 148 | $CI->db->close(); 149 | } 150 | 151 | ob_end_clean(); 152 | 153 | // Restore the Symfony2 error handler 154 | restore_error_handler(); 155 | 156 | // Restart the Symfony 2 session 157 | $session->migrate(); 158 | 159 | if (404 !== $response->getStatusCode()) { 160 | $response->setContent($OUT->get_output()); 161 | } 162 | 163 | return $response; 164 | } 165 | 166 | /** 167 | * {@inheritdoc} 168 | */ 169 | public function boot(ContainerInterface $container) 170 | { 171 | if (empty($this->options)) { 172 | throw new \RuntimeException('You must provide options for the CodeIgniter kernel.'); 173 | } 174 | 175 | $this->container = $container; 176 | 177 | // Defines constants as it is done in the index.php file of your CodeIgniter project. 178 | define('ENVIRONMENT', $this->options['environment']); 179 | define('CI_VERSION', $this->options['version']); 180 | define('CI_CORE', $this->options['core']); 181 | 182 | // The name of the front controller 183 | define('SELF', trim($container->get('request_stack')->getCurrentRequest()->getBaseUrl(), '/')); 184 | 185 | // The PHP file extension 186 | // this global constant is deprecated but used in some third party modules of CodeIgniter 187 | define('EXT', '.php'); 188 | 189 | // Path to the system folder 190 | $systemFolderPath = $this->getRootDir() . '/system/'; 191 | if (array_key_exists('system', $this->options)) { 192 | $systemFolderPath = $this->options['system']; 193 | } 194 | 195 | define('BASEPATH', str_replace("\\", "/", realpath($systemFolderPath) . '/')); 196 | 197 | // Path to the front controller (this file) 198 | define('FCPATH', $container->getParameter('kernel.root_dir') . '/../web'); 199 | 200 | // Name of the "system folder" 201 | define('SYSDIR', trim(strrchr(trim(BASEPATH, '/'), '/'), '/')); 202 | 203 | // The path to the "application" folder 204 | $applicationPath = $this->getRootDir() . '/application/'; 205 | if (array_key_exists('application', $this->options)) { 206 | $applicationPath = $this->options['application']; 207 | } 208 | 209 | define('APPPATH', realpath($applicationPath) . '/'); 210 | 211 | // The path to the "sparks" folder 212 | define('SPARKPATH', $this->getRootDir() . '/sparks/'); 213 | 214 | 215 | if (empty($this->classLoader)) { 216 | throw new \RuntimeException('You must provide a class loader to the CodeIgniter kernel.'); 217 | } 218 | 219 | if (!$this->classLoader->isAutoloaded()) { 220 | $this->classLoader->autoload(); 221 | } 222 | 223 | $this->isBooted = true; 224 | } 225 | 226 | /** 227 | * Return the name of the kernel. 228 | * 229 | * @return string 230 | */ 231 | public function getName() 232 | { 233 | return 'codeigniter'; 234 | } 235 | 236 | /** 237 | * @return \Symfony\Component\DependencyInjection\ContainerInterface 238 | */ 239 | public function getContainer() 240 | { 241 | return $this->container; 242 | } 243 | } 244 | } 245 | 246 | namespace { 247 | function &get_instance() 248 | { 249 | return \CI_Controller::get_instance(); 250 | } 251 | } -------------------------------------------------------------------------------- /Kernel/Event/LegacyKernelBootEvent.php: -------------------------------------------------------------------------------- 1 | request = $request; 27 | $this->options = $options; 28 | } 29 | 30 | /** 31 | * @return Request 32 | */ 33 | public function getRequest() 34 | { 35 | return $this->request; 36 | } 37 | 38 | /** 39 | * @return array 40 | */ 41 | public function getOptions() 42 | { 43 | return $this->options; 44 | } 45 | 46 | /** 47 | * @param array $options 48 | */ 49 | public function setOptions($options) 50 | { 51 | $this->options = $options; 52 | } 53 | 54 | /** 55 | * @param string $name 56 | * @param string $value 57 | */ 58 | public function setOption($name, $value) 59 | { 60 | $this->options[$name] = $value; 61 | } 62 | 63 | } 64 | -------------------------------------------------------------------------------- /Kernel/LegacyKernel.php: -------------------------------------------------------------------------------- 1 | 11 | */ 12 | abstract class LegacyKernel implements LegacyKernelInterface 13 | { 14 | /** 15 | * @var bool 16 | */ 17 | protected $isBooted = false; 18 | 19 | /** 20 | * @var string 21 | */ 22 | protected $rootDir; 23 | 24 | /** 25 | * @var LegacyClassLoaderInterface 26 | */ 27 | protected $classLoader; 28 | 29 | /** 30 | * @var array 31 | */ 32 | protected $options; 33 | 34 | /** 35 | * {@inheritdoc} 36 | */ 37 | public function isBooted() 38 | { 39 | return $this->isBooted; 40 | } 41 | 42 | /** 43 | * {@inheritdoc} 44 | */ 45 | public function getRootDir() 46 | { 47 | return $this->rootDir; 48 | } 49 | 50 | /** 51 | * {@inheritdoc} 52 | */ 53 | public function setRootDir($rootDir) 54 | { 55 | $this->rootDir = $rootDir; 56 | } 57 | 58 | /** 59 | * {@inheritdoc} 60 | */ 61 | public function setClassLoader(LegacyClassLoaderInterface $classLoader) 62 | { 63 | $classLoader->setKernel($this); 64 | $this->classLoader = $classLoader; 65 | } 66 | 67 | /** 68 | * {@inheritdoc} 69 | */ 70 | public function setOptions(array $options = array()) 71 | { 72 | $this->options = $options; 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /Kernel/LegacyKernelEvents.php: -------------------------------------------------------------------------------- 1 | 14 | */ 15 | interface LegacyKernelInterface extends HttpKernelInterface 16 | { 17 | /** 18 | * Boot the legacy kernel. 19 | * 20 | * @throws \RuntimeException 21 | * @param ContainerInterface $container 22 | * @return mixed 23 | */ 24 | public function boot(ContainerInterface $container); 25 | 26 | /** 27 | * Check whether the legacy kernel is already booted or not. 28 | * 29 | * @return boolean 30 | */ 31 | public function isBooted(); 32 | 33 | /** 34 | * Return the directory where the legacy app lives. 35 | * 36 | * @return string 37 | */ 38 | public function getRootDir(); 39 | 40 | /** 41 | * Set the directory where the legacy app lives. 42 | * 43 | * @param string $rootDir 44 | */ 45 | public function setRootDir($rootDir); 46 | 47 | /** 48 | * Set the class loader to use to load the legacy project. 49 | * 50 | * @param LegacyClassLoaderInterface $classLoader 51 | */ 52 | public function setClassLoader(LegacyClassLoaderInterface $classLoader); 53 | 54 | /** 55 | * Return the name of the kernel. 56 | * 57 | * @return string 58 | */ 59 | public function getName(); 60 | 61 | /** 62 | * Set kernel options 63 | * 64 | * @param array $options 65 | */ 66 | public function setOptions(array $options = array()); 67 | } 68 | -------------------------------------------------------------------------------- /Kernel/Symfony14Kernel.php: -------------------------------------------------------------------------------- 1 | 14 | */ 15 | class Symfony14Kernel extends LegacyKernel 16 | { 17 | /** 18 | * @var \sfApplicationConfiguration 19 | */ 20 | private $configuration; 21 | 22 | /** 23 | * {@inheritdoc} 24 | */ 25 | public function boot(ContainerInterface $container) 26 | { 27 | if (empty($this->options)) { 28 | throw new \RuntimeException('You must provide options for the Symfony 1.4 kernel.'); 29 | } 30 | 31 | if ($this->isBooted()) { 32 | return; 33 | } 34 | 35 | if ($this->classLoader && !$this->classLoader->isAutoloaded()) { 36 | $this->classLoader->autoload(); 37 | } 38 | 39 | if ($container->has('request_stack')) { 40 | $request = $container->get('request_stack')->getCurrentRequest(); 41 | } else { 42 | $request = $container->get('request'); 43 | } 44 | 45 | $dispatcher = $container->get('event_dispatcher'); 46 | $event = new LegacyKernelBootEvent($request, $this->options); 47 | $dispatcher->dispatch(LegacyKernelEvents::BOOT, $event); 48 | $this->options = $event->getOptions(); 49 | 50 | require_once $this->rootDir.'/config/ProjectConfiguration.class.php'; 51 | 52 | $application = $this->options['application']; 53 | $environment = $this->options['environment']; 54 | $debug = $this->options['debug']; 55 | 56 | $this->configuration = \ProjectConfiguration::getApplicationConfiguration( 57 | $application, 58 | $environment, 59 | $debug, 60 | $this->getRootDir() 61 | ); 62 | $this->configuration->loadHelpers(array('Url')); 63 | 64 | // Create a context to use with some helpers like Url. 65 | if (!\sfContext::hasInstance()) { 66 | $session = $container->get('session'); 67 | if ($session->isStarted()) { 68 | $session->save(); 69 | } 70 | 71 | ob_start(); 72 | \sfContext::createInstance($this->configuration); 73 | ob_end_flush(); 74 | } 75 | 76 | $this->isBooted = true; 77 | } 78 | 79 | /** 80 | * {@inheritdoc} 81 | */ 82 | public function handle(Request $request, $type = self::MASTER_REQUEST, $catch = true) 83 | { 84 | $session = $request->getSession(); 85 | if ($session->isStarted()) { 86 | $session->save(); 87 | } 88 | 89 | ob_start(); 90 | $context = \sfContext::getInstance(); 91 | $context->dispatch(); 92 | $context->shutdown(); 93 | ob_end_clean(); 94 | 95 | // @todo: the debug toolbar is not displayed 96 | return $this->convertResponse($context->getResponse()); 97 | } 98 | 99 | /** 100 | * Check whether the legacy kernel is already booted or not. 101 | * 102 | * @return boolean 103 | */ 104 | public function isBooted() 105 | { 106 | return $this->isBooted; 107 | } 108 | 109 | /** 110 | * {@inheritdoc} 111 | */ 112 | public function getName() 113 | { 114 | return 'symfony14'; 115 | } 116 | 117 | /** 118 | * Convert the symfony 1.4 response to a Response. 119 | * @param \sfWebResponse $legacyResponse 120 | * @return Response 121 | */ 122 | private function convertResponse($legacyResponse) 123 | { 124 | $response = new Response($legacyResponse->getContent(), $legacyResponse->getStatusCode()); 125 | $response->setCharset($legacyResponse->getCharset()); 126 | $response->setStatusCode($legacyResponse->getStatusCode()); 127 | 128 | foreach($legacyResponse->getHttpHeaders() as $headerName => $headerValue) { 129 | $response->headers->set($headerName, $headerValue); 130 | } 131 | 132 | return $response; 133 | } 134 | } 135 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Theodo Evolution LegacyWrapperBundle 2 | ==================================== 3 | 4 | [![Build Status](https://travis-ci.org/theodo/TheodoEvolutionLegacyWrapperBundle.svg?branch=master)](https://travis-ci.org/theodo/TheodoEvolutionLegacyWrapperBundle) [![Latest Stable Version](https://poser.pugx.org/theodo-evolution/legacy-wrapper-bundle/version.svg)](https://packagist.org/packages/theodo-evolution/legacy-wrapper-bundle) [![Latest Unstable Version](https://poser.pugx.org/theodo-evolution/legacy-wrapper-bundle/v/unstable.svg)](//packagist.org/packages/theodo-evolution/legacy-wrapper-bundle) [![Total Downloads](https://poser.pugx.org/theodo-evolution/legacy-wrapper-bundle/downloads.svg)](https://packagist.org/packages/theodo-evolution/legacy-wrapper-bundle) 5 | 6 | 7 | What is Theodo Evolution? 8 | ------------------------- 9 | 10 | Theodo Evolution is a set of tools, methodologies and software components, making the code of a legacy php application 11 | more maintainable, easily scalable, secure and fast. 12 | 13 | Theodo Evolution's LegacyWrapperBundle 14 | -------------------------------------- 15 | 16 | This bundle allows you to call the legacy framework from Symfony2. 17 | Tested and works for legacy app made with: 18 | 19 | * [symfony 1.4](https://github.com/symfony/symfony1) 20 | * [symfony 1.5](https://github.com/lexpress/symfony1) 21 | * [CodeIgniter >=2.1.2](https://github.com/EllisLab/CodeIgniter/tree/2.1-stable) 22 | 23 | Prerequisites 24 | ------------- 25 | 26 | This version requires at least Symfony 2.4. It has been tested with Symfony 3.4. 27 | 28 | Documentation 29 | ------------- 30 | 31 | The bulk of the documentation is stored in the `Resources/doc/index.md` 32 | file in this bundle: 33 | 34 | [Read the Documentation for master](Resources/doc/index.rst) 35 | 36 | License 37 | ------- 38 | 39 | This bundle is under the MIT license. See the complete license in the bundle: 40 | 41 | Resources/meta/LICENSE 42 | -------------------------------------------------------------------------------- /Resources/config/services.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 7 | 8 | Theodo\Evolution\Bundle\LegacyWrapperBundle\Kernel\Symfony14Kernel 9 | Theodo\Evolution\Bundle\LegacyWrapperBundle\Kernel\CodeIgniterKernel 10 | Theodo\Evolution\Bundle\LegacyWrapperBundle\Autoload\CodeIgniterClassLoader 11 | Theodo\Evolution\Bundle\LegacyWrapperBundle\EventListener\RouterListener 12 | Theodo\Evolution\Bundle\LegacyWrapperBundle\EventListener\LegacyBooterListener 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | %theodo_evolution_legacy_wrapper.root_dir% 33 | 34 | 35 | 36 | 42 | 43 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | -------------------------------------------------------------------------------- /Resources/doc/autoloading.rst: -------------------------------------------------------------------------------- 1 | Autoloading 2 | =========== 3 | 4 | The autoloading of the legacy application is done from the ``boot`` method of the legacy 5 | kernel, called by the ``LegacyBooterListener``. 6 | 7 | There are many ways to autoload a PHP project. The legacy project can be autoloaded: 8 | * requiring a PHP file 9 | * instantiating the main class of the framework 10 | * using composer 11 | * ... 12 | 13 | Regardless the way the legacy code is autoloaded, you will have to do it by yourself. 14 | To do so you will have to create a ``class loader`` which must implement the 15 | ``LegacyClassLoaderInterface``: 16 | 17 | :: 18 | 19 | namespace Acme\MyLegacyBundle\Autoload; 20 | 21 | use Theodo\Evolution\Bundle\LegacyWrapperBundle\Autoload\LegacyKernelInterface; 22 | 23 | class MyLegacyClassLoader implements LegacyClassLoaderInterface 24 | { 25 | /** 26 | * @var LegacyKernelInterface 27 | */ 28 | private $kernel; 29 | 30 | /** 31 | * {@inheritdoc} 32 | */ 33 | public function autoload() 34 | { 35 | // require the legacy autoload php file. 36 | require_once $this->kernel->getRootDir().'/autoload.php'; 37 | 38 | $this->isAutoloaded = true; 39 | } 40 | 41 | /** 42 | * {@inheritdoc} 43 | */ 44 | public function isAutoloaded() 45 | { 46 | return $this->isAutoloaded; 47 | } 48 | 49 | /** 50 | * {@inheritdoc} 51 | */ 52 | public function setKernel(LegacyKernelInterface $kernel) 53 | { 54 | $this->kernel = $kernel; 55 | } 56 | } 57 | 58 | Declare this class as a service: 59 | 60 | :: 61 | 62 | 63 | Acme\MyLegacyBundle\Autoload\MyLegacyClassLoader 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | Then you will have to configure the bundle to use your class loader service: 72 | 73 | :: 74 | 75 | theodo_evolution_legacy_wrapper: 76 | # ... 77 | class_loader_id: my_legacy.autoload.my_legacy_class_loader 78 | 79 | Legacy with Composer 80 | ==================== 81 | 82 | If you are lucky, the legacy project could use Composer. This will ease your work a lot. 83 | The bundle provides you a way to use Composer from the legacy kernel. 84 | 85 | First your AppKernel must extends the ``EvolutionKernel``: 86 | 87 | :: 88 | 89 | use Theodo\Evolution\Bundle\LegacyWrapperBundle\HttpKernel\EvolutionKernel; 90 | 91 | class AppKernel extends EvolutionKernel 92 | { 93 | // ... 94 | } 95 | 96 | Then make sure to set the ``loader`` to the kernel from the front controller ``web/app.php``, 97 | ``web/app_dev.php`` and ``app/console``: 98 | 99 | :: 100 | 101 | // ... 102 | $loader = require_once __DIR__.'/../app/bootstrap.php.cache'; 103 | 104 | // ... 105 | 106 | $kernel = new AppKernel('dev', true); 107 | $kernel->setLoader($loader); 108 | 109 | Your class loader service must implement the ``ComposerLoaderAwareInterface`` 110 | to inject the autoloader provided by Composer in it. 111 | 112 | :: 113 | 114 | class MyLegacyClassLoader implements LegacyClassLoaderInterface, ComposerLoaderAwareInterface 115 | { 116 | // ... other properties 117 | 118 | /** 119 | * @var ClassLoader 120 | */ 121 | private $loader; 122 | 123 | // ... other methods 124 | 125 | /** 126 | * @param ClassLoader $loader 127 | * @return mixed 128 | */ 129 | public function setLoader(ClassLoader $loader) 130 | { 131 | $this->loader = $loader; 132 | } 133 | } 134 | 135 | Don't forget to change the service definition and add the ``loader_aware`` tag: 136 | 137 | :: 138 | 139 | 140 | Acme\MyLegacyBundle\Autoload\MyLegacyClassLoader 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | Finally, you can use the ``autoload`` generated by Composer from the legacy application and remove, add some classes or library: 150 | 151 | :: 152 | 153 | /** 154 | * {@inheritdoc} 155 | */ 156 | public function autoload() 157 | { 158 | $composerDir = realpath($this->legacyPath.'/lib/vendor/composer'); 159 | 160 | $map = require $composerDir . '/autoload_namespaces.php'; 161 | $prefixes = $this->loader->getPrefixes(); 162 | foreach ($map as $namespace => $path) { 163 | if (!array_key_exists($namespace, $prefixes)) { 164 | $this->loader->set($namespace, $path); 165 | } 166 | } 167 | 168 | $classMap = require $composerDir . '/autoload_classmap.php'; 169 | if ($classMap) { 170 | $this->loader->addClassMap($classMap); 171 | } 172 | 173 | $includeFiles = require $composerDir . '/autoload_files.php'; 174 | foreach ($includeFiles as $file) { 175 | // Don't autoload the legacy SwiftMailer as it is autoloaded with the SwiftMailerBundle 176 | if (false === strpos($file, 'swiftmailer')) { 177 | require $file; 178 | } 179 | } 180 | } 181 | -------------------------------------------------------------------------------- /Resources/doc/codeigniter.rst: -------------------------------------------------------------------------------- 1 | Wrap CodeIgniter 2 | ================ 3 | 4 | Here is the basic configuration for a CodeIgniter application: 5 | :: 6 | 7 | theodo_evolution_legacy_wrapper: 8 | root_dir: %kernel.root_dir%/../legacy 9 | class_loader_id: theodo_evolution_legacy_wrapper.autoload.codeigniter_class_loader 10 | kernel: 11 | id: theodo_evolution_legacy_wrapper.legacy_kernel.codeigniter 12 | options: 13 | environment: %kernel.environment% 14 | version: '2.1.2' 15 | core: false 16 | 17 | Slightly advanced configuration for CodeIgniter application: 18 | * where the system folder and application folder reside in locations other than the `%root_dir%/system` and 19 | `%root_dir%/application paths`. If these are not set, they default to looking under the `%root_dir%` for the 20 | appropriate folders 21 | 22 | :: 23 | 24 | theodo_evolution_legacy_wrapper: 25 | root_dir: %kernel.root_dir%/../legacy 26 | class_loader_id: theodo_evolution_legacy_wrapper.autoload.codeigniter_class_loader 27 | kernel: 28 | id: theodo_evolution_legacy_wrapper.legacy_kernel.codeigniter 29 | options: 30 | environment: %kernel.environment% 31 | version: '2.1.2' 32 | core: false 33 | system: %kernel.root_dir%/../library/CodeIgniter_2.1.4/system 34 | application: %kernel.root_dir%/../application 35 | 36 | -------------------------------------------------------------------------------- /Resources/doc/codeignitertroubleshooting.md: -------------------------------------------------------------------------------- 1 | #CodeIgniter Troubleshooting 2 | 3 | - Symfony Debug Toolbar 404|500 4 | - add the following to your CodeIgniter `routes.php` config file: 5 | 6 | 7 | if (is_bool(strpos(ENVIRONMENT, 'prod'))) 8 | { 9 | $route['404_override'] = 'nomEmptyStringValue'; 10 | } 11 | -------------------------------------------------------------------------------- /Resources/doc/customkernel.rst: -------------------------------------------------------------------------------- 1 | Create your own kernel 2 | ====================== 3 | 4 | First create a class that implements the ``LegacyKernelInterface`` or extends the ``LegacyKernel``: 5 | 6 | :: 7 | 8 | namespace Acme\MyLegacyBundle\Kernel; 9 | 10 | use Symfony\Component\HttpFoundation\Response; 11 | use Theodo\Evolution\Bundle\LegacyWrapperBundle\Kernel\LegacyKernel; 12 | 13 | class MyKernel extends LegacyKernel 14 | { 15 | // ... implementation of abstract methods 16 | 17 | /** 18 | * {@inheritdoc} 19 | */ 20 | public function getName() 21 | { 22 | return 'mykernel'; 23 | } 24 | } 25 | 26 | Then you must implement the ``boot`` method. It must load the legacy application either by calling 27 | an injected ``LegacyClassLoaderInterface`` implementation instance, or doing it directly from 28 | the method. The way you should boot your legacy app depends on it, so this example is a really simple 29 | one... 30 | 31 | :: 32 | 33 | /** 34 | * {@inheritdoc} 35 | */ 36 | public function boot(ContainerInterface $container) 37 | { 38 | $this->classLoader->autoload(); 39 | } 40 | 41 | The next step is to implement the request handling. This is done implementing the ``handle`` method, 42 | provided by the ``HttpKernelInterface``. 43 | The first step is to save the eventually opened session to let the legacy application write data in it. 44 | Then start a buffer and let the legacy handle the request as it normally does... Once this is done, 45 | store the content and close the buffer. Then, if the legacy application does not, write close the 46 | session and restart the Symfony 2 session. Finally, create a Symfony response populated with the content 47 | that the legacy returned: 48 | 49 | :: 50 | 51 | /** 52 | * {@inheritdoc} 53 | */ 54 | public function handle(Request $request, $type = self::MASTER_REQUEST, $catch = true) 55 | { 56 | // Save the Symfony 2 session 57 | $session = $request->getSession(); 58 | if ($session->isStarted()) { 59 | $session->save(); 60 | } 61 | 62 | ob_start(); 63 | require_once $this->getRootDir().'/index.php'; 64 | $response = ob_get_clean(); 65 | 66 | // Save the session updated by the legacy app and restart the Symfony 2 one. 67 | $session->migrate(); 68 | 69 | return new Response($response); 70 | } 71 | 72 | You might set different status code to the response, set http cache headers, change the content type... You can 73 | do this from this point. -------------------------------------------------------------------------------- /Resources/doc/index.rst: -------------------------------------------------------------------------------- 1 | How it works 2 | ============ 3 | 4 | The aim of the bundle is to allow a legacy project to handle HTTP requests instead of Symfony 2, 5 | in a simple way: 6 | 7 | * let Symfony try to find a controller that matches the request 8 | * if it can't, it let the legacy project try to return a response 9 | * otherwise return a 404 response 10 | 11 | To do so, the LegacyWrapperBundle provides a ```RouterLister``` which will delegates the request 12 | handling to the ```RouterListener``` of Symfony 2 and if a ```HttpNotFoundException``` is thrown 13 | it will call the legacy kernel, which is an implementation of the ``HttpKernelInterface`` of the 14 | legacy project. 15 | 16 | Installation 17 | ============ 18 | 19 | This bundle requires Symfony 2.4 or higher. 20 | 21 | Add the following lines to your composer.json: 22 | 23 | :: 24 | 25 | "require": { 26 | ... 27 | "composer/composer": "~1.0@dev", 28 | "theodo-evolution/legacy-wrapper-bundle": "~1.0" 29 | ... 30 | }, 31 | 32 | And run Composer: 33 | 34 | :: 35 | 36 | php composer.phar update theodo-evolution/legacy-wrapper-bundle 37 | 38 | Configuration 39 | ============= 40 | 41 | Add the bundles in your app/AppKernel.php: 42 | 43 | :: 44 | 45 | public function registerBundles() 46 | { 47 | $bundles = array( 48 | //vendors, other bundles... 49 | new Theodo\Evolution\Bundle\LegacyWrapperBundle\TheodoEvolutionLegacyWrapperBundle(), 50 | ); 51 | } 52 | 53 | Configure the bundle in your app/config/config.yml: 54 | 55 | * `Symfony >=1.4 configuration`_ 56 | * `Code Igniter ~2.1 configuration`_ 57 | * `Custom kernel configuration`_ 58 | 59 | .. _Symfony >=1.4 configuration: symfony14.rst 60 | .. _Code Igniter ~2.1 configuration: codeigniter.rst 61 | .. _Custom kernel configuration: customkernel.rst 62 | 63 | Autoloading 64 | =========== 65 | 66 | To make the legacy application handle the request or to use the legacy code from Symfony 2 67 | (in a controller for example) you must autoload it. 68 | 69 | See the `autoloading`_ guide. 70 | 71 | .. _autoloading: autoloading.rst 72 | -------------------------------------------------------------------------------- /Resources/doc/symfony14.rst: -------------------------------------------------------------------------------- 1 | Wrap symfony >=1.4 2 | =================== 3 | 4 | Here is the basic configuration for a symfony >=1.4 application: 5 | :: 6 | 7 | theodo_evolution_legacy_wrapper: 8 | root_dir: %kernel.root_dir%/../legacy 9 | kernel: 10 | id: theodo_evolution_legacy_wrapper.legacy_kernel.symfony14 11 | options: 12 | application: frontend 13 | environment: '%kernel.environment%' 14 | debug: '%kernel.debug%' 15 | 16 | 17 | Update options in runtime 18 | ------------------------- 19 | There is an event ``LegacyKernelEvents::BOOT`` being dispatched in from ``Symfony14Kernel::boot`` before legacy project is actually started. 20 | Handling this event allows to update ``options`` (``application``, ``environment`` and ``debug``) in runtime. 21 | For example to launch application(in terms of symfony 1) based on request: 22 | 23 | :: 24 | 25 | namespace My\LegacyWrapperBundle\EventListener; 26 | 27 | use Symfony\Component\EventDispatcher\EventSubscriberInterface; 28 | use Theodo\Evolution\Bundle\LegacyWrapperBundle\Kernel\Event\LegacyKernelBootEvent; 29 | use Theodo\Evolution\Bundle\LegacyWrapperBundle\Kernel\LegacyKernelEvents; 30 | 31 | class MyListener implements EventSubscriberInterface 32 | { 33 | /** 34 | * @param LegacyKernelBootEvent $event 35 | */ 36 | public function onLegacyKernelBoot(LegacyKernelBootEvent $event) 37 | { 38 | $request = $event->getRequest(); 39 | if($this->isBackendApplication()) { 40 | $event->setOption('application', 'backend'); 41 | } else { 42 | $event->setOption('application', 'frontend'); 43 | } 44 | } 45 | 46 | /** 47 | * {@inheritdoc} 48 | */ 49 | public static function getSubscribedEvents() 50 | { 51 | return [ 52 | LegacyKernelEvents::BOOT => 'onLegacyKernelBoot' 53 | ]; 54 | } 55 | 56 | 57 | /** 58 | * @param Request $request 59 | * 60 | * @return bool 61 | */ 62 | protected function isBackendApplication(Request $request) 63 | { 64 | // .... some logic there 65 | } 66 | } 67 | 68 | 69 | -------------------------------------------------------------------------------- /Tests/DependencyInjection/Compiler/KernelConfigurationPassTest.php: -------------------------------------------------------------------------------- 1 | setDefinition('legacy_kernel_id', new Definition()); 16 | 17 | $container->setParameter('theodo_evolution_legacy_wrapper.legacy_kernel.id', $kernel = 'legacy_kernel_id'); 18 | $container->setParameter('theodo_evolution_legacy_wrapper.legacy_kernel.options', $options = array('key' => 'value')); 19 | $container->setParameter('theodo_evolution_legacy_wrapper.autoload.class_loader.id', $loader = 'class_loader'); 20 | 21 | $compiler = new KernelConfigurationPass(); 22 | $compiler->process($container); 23 | 24 | $kernelDefinition = $container->findDefinition('theodo_evolution_legacy_wrapper.legacy_kernel'); 25 | 26 | $this->assertSame($container->findDefinition('legacy_kernel_id'), $kernelDefinition, 'Legacy kernel alias has not been set correctly'); 27 | $this->assertAttributeContains(array('setOptions', array($options)), 'calls', $kernelDefinition, 'Method setOptions has not been set to call'); 28 | $this->assertAttributeContains(array('setClassLoader', array(new Reference('class_loader'))), 'calls', $kernelDefinition, 'Method setClassLoader has not been set to call'); 29 | } 30 | 31 | public function testShouldNotCallSetOptionsIfEmpty() 32 | { 33 | $container = new ContainerBuilder(); 34 | 35 | $container->setDefinition('legacy_kernel_id', new Definition()); 36 | 37 | $container->setParameter('theodo_evolution_legacy_wrapper.legacy_kernel.id', $kernel = 'legacy_kernel_id'); 38 | $container->setParameter('theodo_evolution_legacy_wrapper.legacy_kernel.options', $options = array()); 39 | $container->setParameter('theodo_evolution_legacy_wrapper.autoload.class_loader.id', $loader = 'class_loader'); 40 | 41 | $compiler = new KernelConfigurationPass(); 42 | $compiler->process($container); 43 | 44 | $kernelDefinition = $container->findDefinition('theodo_evolution_legacy_wrapper.legacy_kernel'); 45 | 46 | $this->assertSame($container->findDefinition('legacy_kernel_id'), $kernelDefinition, 'Legacy kernel alias has not been set correctly'); 47 | $this->assertAttributeNotContains(array('setOptions', array($options)), 'calls', $kernelDefinition, 'Method setOptions should not be set to call'); 48 | } 49 | 50 | public function testShouldNotCallSetClassLoaderIfNull() 51 | { 52 | $container = new ContainerBuilder(); 53 | 54 | $container->setDefinition('legacy_kernel_id', new Definition()); 55 | 56 | $container->setParameter('theodo_evolution_legacy_wrapper.legacy_kernel.id', $kernel = 'legacy_kernel_id'); 57 | $container->setParameter('theodo_evolution_legacy_wrapper.legacy_kernel.options', $options = array('key' => 'value')); 58 | $container->setParameter('theodo_evolution_legacy_wrapper.autoload.class_loader.id', $loader = null); 59 | 60 | $compiler = new KernelConfigurationPass(); 61 | $compiler->process($container); 62 | 63 | $kernelDefinition = $container->findDefinition('theodo_evolution_legacy_wrapper.legacy_kernel'); 64 | 65 | $this->assertSame($container->findDefinition('legacy_kernel_id'), $kernelDefinition, 'Legacy kernel alias has not been set correctly'); 66 | $this->assertAttributeNotContains(array('setClassLoader', array(new Reference('class_loader'))), 'calls', $kernelDefinition, 'Method setClassLoader should not be set to call'); 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /Tests/DependencyInjection/ConfigurationTest.php: -------------------------------------------------------------------------------- 1 | getBasicConfiguration(); 19 | 20 | $config = $this->process($configs); 21 | 22 | $this->assertEquals('/foo/bar', $config['root_dir']); 23 | $this->assertEquals('foo', $config['kernel']['id']); 24 | $this->assertArrayNotHasKey('class_loader_id', $config); 25 | $this->assertEmpty($config['assets']); 26 | } 27 | 28 | public function testProcessSymfony14KernelConfiguration() 29 | { 30 | $configs = array( 31 | array( 32 | 'root_dir' => '/foo', 33 | 'kernel' => array( 34 | 'id' => 'legacy_kernel.symfony14', 35 | 'options' => array( 36 | 'application' => 'bar', 37 | 'environment' => '%kernel.environment%', 38 | 'debug' => '%kernel.debug%', 39 | ) 40 | ) 41 | ) 42 | ); 43 | 44 | $config = $this->process($configs); 45 | 46 | $this->assertEquals('legacy_kernel.symfony14', $config['kernel']['id']); 47 | $this->assertArrayHasKey('application', $config['kernel']['options']); 48 | $this->assertArrayHasKey('environment', $config['kernel']['options']); 49 | $this->assertArrayHasKey('debug', $config['kernel']['options']); 50 | } 51 | 52 | /** 53 | * @expectedException \Symfony\Component\Config\Definition\Exception\InvalidConfigurationException 54 | */ 55 | public function testProcessInvalidSymfony14KernelConfiguration() 56 | { 57 | $configs = array( 58 | array( 59 | 'root_dir' => '/foo', 60 | 'kernel' => array( 61 | 'id' => 'legacy_kernel.symfony14', 62 | 'options' => array( 63 | 'application' => 'bar', 64 | ) 65 | ) 66 | ) 67 | ); 68 | 69 | $this->process($configs); 70 | } 71 | 72 | public function testProcessCodeIgniterKernelConfiguration() 73 | { 74 | $configs = array( 75 | array( 76 | 'root_dir' => '/foo', 77 | 'kernel' => array( 78 | 'id' => 'legacy_kernel.codeigniter', 79 | 'options' => array( 80 | 'environment' => '%kernel.environment%', 81 | 'version' => '2.1.2', 82 | 'core' => false, 83 | ) 84 | ) 85 | ) 86 | ); 87 | 88 | $config = $this->process($configs); 89 | 90 | $this->assertEquals('legacy_kernel.codeigniter', $config['kernel']['id']); 91 | $this->assertArrayHasKey('environment', $config['kernel']['options']); 92 | $this->assertArrayHasKey('version', $config['kernel']['options']); 93 | $this->assertArrayHasKey('core', $config['kernel']['options']); 94 | $this->assertArrayNotHasKey('application', $config['kernel']['options']); 95 | } 96 | 97 | /** 98 | * @expectedException \Symfony\Component\Config\Definition\Exception\InvalidConfigurationException 99 | */ 100 | public function testProcessInvalidaCodeIgniterKernelConfiguration() 101 | { 102 | $configs = array( 103 | array( 104 | 'root_dir' => '/foo', 105 | 'kernel' => array( 106 | 'id' => 'legacy_kernel.codeigniter', 107 | 'options' => array( 108 | 'environment' => '%kernel.environment%', 109 | ) 110 | ) 111 | ) 112 | ); 113 | 114 | $this->process($configs); 115 | } 116 | 117 | public function testProcessCustomKernelConfiguration() 118 | { 119 | $configs = array( 120 | array( 121 | 'root_dir' => '/foo', 122 | 'kernel' => array( 123 | 'id' => 'my_kernel', 124 | 'options' => array( 125 | 'foo' => 'bar', 126 | ) 127 | ) 128 | ) 129 | ); 130 | 131 | $config = $this->process($configs); 132 | 133 | $this->assertArrayHasKey('foo', $config['kernel']['options']); 134 | } 135 | 136 | public function testProcessBasicAssetsConfiguration() 137 | { 138 | $configs = $this->getBasicConfiguration(); 139 | $configs[0] += array( 140 | 'assets' => array( 141 | 'web' => array( 142 | 'base' => '/web', 143 | 'directories' => array('css', 'js') 144 | ) 145 | ) 146 | ); 147 | 148 | $config = $this->process($configs); 149 | 150 | $this->assertArrayHasKey('web', $config['assets']); 151 | $this->assertEquals('/web', $config['assets']['web']['base']); 152 | $this->assertCount(2, $config['assets']['web']['directories']); 153 | } 154 | 155 | public function testProcessMultipleAssetsConfiguration() 156 | { 157 | $configs = $this->getBasicConfiguration(); 158 | $configs[0] += array( 159 | 'assets' => array( 160 | 'foo' => array( 161 | 'base' => '/foo', 162 | 'directories' => array('css', 'js') 163 | ), 164 | 'bar' => array( 165 | 'base' => '/bar', 166 | 'directories' => array('css', 'js') 167 | ) 168 | ) 169 | ); 170 | 171 | $config = $this->process($configs); 172 | 173 | $this->assertCount(2, $config['assets']); 174 | } 175 | 176 | /** 177 | * Processes an array of configurations and returns a compiled version. 178 | * 179 | * @param array $configs An array of raw configurations 180 | * 181 | * @return array A normalized array 182 | */ 183 | protected function process($configs) 184 | { 185 | $processor = new Processor(); 186 | 187 | return $processor->processConfiguration(new Configuration(), $configs); 188 | } 189 | 190 | /** 191 | * @return array 192 | */ 193 | private function getBasicConfiguration() 194 | { 195 | return array( 196 | array( 197 | 'root_dir' => '/foo/bar', 198 | 'kernel' => 'foo' 199 | ) 200 | ); 201 | } 202 | } 203 | -------------------------------------------------------------------------------- /Tests/EventListener/RouterListenerTest.php: -------------------------------------------------------------------------------- 1 | 16 | */ 17 | class RouterListenerTest extends ProphecyTestCase 18 | { 19 | public function testLegacyKernelShouldHandleTheRequest() 20 | { 21 | $request = new Request(); 22 | $response = new Response(); 23 | 24 | $httpKernel = $this->prophesize('Symfony\Component\HttpKernel\HttpKernelInterface'); 25 | $event = new GetResponseEvent($httpKernel->reveal(), $request, HttpKernel::MASTER_REQUEST); 26 | 27 | $baseRouterListener = $this->prophesize('Symfony\Component\HttpKernel\EventListener\RouterListener'); 28 | $baseRouterListener->onKernelRequest($event)->willThrow('Symfony\Component\HttpKernel\Exception\NotFoundHttpException'); 29 | 30 | $kernel = $this->prophesize('Theodo\Evolution\Bundle\LegacyWrapperBundle\Kernel\LegacyKernelInterface'); 31 | $kernel->handle($request, HttpKernel::MASTER_REQUEST, true)->willReturn($response); 32 | 33 | $routerListener = new \Theodo\Evolution\Bundle\LegacyWrapperBundle\EventListener\RouterListener($kernel->reveal(), $baseRouterListener->reveal()); 34 | $routerListener->onKernelRequest($event); 35 | 36 | $this->assertEquals($response, $event->getResponse()); 37 | } 38 | 39 | public function testLegacyKernelShouldNotHandleTheRequest() 40 | { 41 | $request = new Request(); 42 | 43 | $httpKernel = $this->prophesize('Symfony\Component\HttpKernel\HttpKernelInterface'); 44 | $event = new GetResponseEvent($httpKernel->reveal(), $request, HttpKernel::MASTER_REQUEST); 45 | 46 | $baseRouterListener = $this->prophesize('Symfony\Component\HttpKernel\EventListener\RouterListener'); 47 | $baseRouterListener->onKernelRequest($event); 48 | 49 | $kernel = $this->prophesize('Theodo\Evolution\Bundle\LegacyWrapperBundle\Kernel\LegacyKernelInterface'); 50 | $kernel->handle()->shouldNotBeCalled(); 51 | 52 | $routerListener = new RouterListener($kernel->reveal(), $baseRouterListener->reveal()); 53 | $routerListener->onKernelRequest($event); 54 | } 55 | 56 | public function testNotFoundHttp() 57 | { 58 | $request = new Request(); 59 | $response = new Response(); 60 | $response->setStatusCode(404); 61 | 62 | $httpKernel = $this->prophesize('Symfony\Component\HttpKernel\HttpKernelInterface'); 63 | $event = new GetResponseEvent($httpKernel->reveal(), $request, HttpKernel::MASTER_REQUEST); 64 | 65 | $baseRouterListener = $this->prophesize('Symfony\Component\HttpKernel\EventListener\RouterListener'); 66 | $baseRouterListener->onKernelRequest($event)->willThrow('Symfony\Component\HttpKernel\Exception\NotFoundHttpException'); 67 | 68 | $kernel = $this->prophesize('Theodo\Evolution\Bundle\LegacyWrapperBundle\Kernel\LegacyKernelInterface'); 69 | $kernel->handle($request, HttpKernel::MASTER_REQUEST, true)->willReturn($response); 70 | 71 | $routerListener = new RouterListener($kernel->reveal(), $baseRouterListener->reveal()); 72 | $routerListener->onKernelRequest($event); 73 | 74 | $this->assertNull($event->getResponse()); 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /Tests/Kernel/CodeIgniterKernelTest.php: -------------------------------------------------------------------------------- 1 | =')) { 18 | $this->markTestSkipped('CodeIgniter v2.1 is not compatible with PHP >= 5.6'); 19 | } 20 | 21 | $session = new Session(new MockArraySessionStorage()); 22 | $request = Request::create('/welcome/'); 23 | $request->setSession($session); 24 | 25 | $requestStack = $this->prophesize('Symfony\Component\HttpFoundation\RequestStack'); 26 | $requestStack->getCurrentRequest()->willReturn($request); 27 | 28 | $container = $this->prophesize('Symfony\Component\DependencyInjection\ContainerInterface'); 29 | $container->get('request_stack')->willReturn($requestStack->reveal()); 30 | $container->getParameter(Argument::any())->willReturn('foo'); 31 | $container->set(Argument::type('string'), Argument::any())->shouldBeCalled(); 32 | 33 | $classLoader = new CodeIgniterClassLoader(); 34 | 35 | $kernel = new CodeIgniterKernel(); 36 | $kernel->setRootDir($_ENV['THEODO_EVOLUTION_FAKE_PROJECTS'].'/codeigniter21'); 37 | $kernel->setOptions(array('environment' => 'prod', 'version' => '2.1.4', 'core' => false)); 38 | $kernel->setClassLoader($classLoader); 39 | 40 | $kernel->boot($container->reveal()); 41 | 42 | $this->assertTrue($kernel->isBooted()); 43 | $this->assertTrue($classLoader->isAutoloaded()); 44 | // CodeIgniter creates a global variables 45 | $this->assertArrayHasKey('BM', $GLOBALS); 46 | $this->assertArrayHasKey('EXT', $GLOBALS); 47 | $this->assertArrayHasKey('CFG', $GLOBALS); 48 | $this->assertArrayHasKey('UNI', $GLOBALS); 49 | $this->assertArrayHasKey('URI', $GLOBALS); 50 | $this->assertArrayHasKey('RTR', $GLOBALS); 51 | $this->assertArrayHasKey('OUT', $GLOBALS); 52 | $this->assertArrayHasKey('SEC', $GLOBALS); 53 | 54 | $response = $kernel->handle($request, 1, true); 55 | 56 | $this->assertInstanceOf('Symfony\Component\HttpFoundation\Response', $response); 57 | $this->assertEquals(200, $response->getStatusCode()); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /Tests/Kernel/Symfony14KernelTest.php: -------------------------------------------------------------------------------- 1 | 20 | */ 21 | class Symfony14KernelTest extends ProphecyTestCase 22 | { 23 | public function testShouldBootAndHandleRequest() 24 | { 25 | $kernelOptions = array( 26 | 'application' => 'frontend', 27 | 'environment' => 'prod', 28 | 'debug' => true, 29 | ); 30 | 31 | $classLoader = $this->prophesize('Theodo\Evolution\Bundle\LegacyWrapperBundle\Autoload\LegacyClassLoaderInterface'); 32 | 33 | $session = new Session(new MockArraySessionStorage()); 34 | $request = Request::create('/'); 35 | $request->setSession($session); 36 | 37 | $eventDispatcher = $this->prophesize('Symfony\Component\EventDispatcher\EventDispatcherInterface'); 38 | $eventDispatcher->dispatch('legacy_kernel.boot', new LegacyKernelBootEvent($request, $kernelOptions))->shouldBeCalled(); 39 | 40 | $container = $this->createProphesizedContainer($request); 41 | $container->get('session')->willReturn($session); 42 | $container->get('event_dispatcher')->willReturn($eventDispatcher); 43 | 44 | $classLoader->setKernel(Argument::type('Theodo\Evolution\Bundle\LegacyWrapperBundle\Kernel\Symfony14Kernel'))->shouldBeCalled(); 45 | $classLoader->isAutoloaded()->willReturn(false); 46 | $classLoader->autoload()->shouldBeCalled(); 47 | 48 | $kernel = new Symfony14Kernel(); 49 | $kernel->setRootDir($_ENV['THEODO_EVOLUTION_FAKE_PROJECTS'].'/symfony14'); 50 | $kernel->setClassLoader($classLoader->reveal()); 51 | $kernel->setOptions($kernelOptions); 52 | 53 | $kernel->boot($container->reveal()); 54 | $this->assertTrue($kernel->isBooted()); 55 | 56 | $response = $kernel->handle($request, 1, true); 57 | 58 | $this->assertInstanceOf('Symfony\Component\HttpFoundation\Response', $response); 59 | $this->assertEquals(200, $response->getStatusCode()); 60 | } 61 | 62 | public function testShouldBootAndHandleRequestIfClassLoaderIsNotProvided() 63 | { 64 | $kernelOptions = array( 65 | 'application' => 'frontend', 66 | 'environment' => 'prod', 67 | 'debug' => true, 68 | ); 69 | 70 | $session = new Session(new MockArraySessionStorage()); 71 | $request = Request::create('/'); 72 | $request->setSession($session); 73 | 74 | $eventDispatcher = $this->prophesize('Symfony\Component\EventDispatcher\EventDispatcherInterface'); 75 | $eventDispatcher->dispatch('legacy_kernel.boot', new LegacyKernelBootEvent($request, $kernelOptions))->shouldBeCalled(); 76 | 77 | $container = $this->createProphesizedContainer($request); 78 | $container->get('event_dispatcher')->willReturn($eventDispatcher); 79 | 80 | $kernel = new Symfony14Kernel(); 81 | $kernel->setRootDir($_ENV['THEODO_EVOLUTION_FAKE_PROJECTS'].'/symfony14'); 82 | $kernel->setOptions($kernelOptions); 83 | 84 | $kernel->boot($container->reveal()); 85 | $this->assertTrue($kernel->isBooted()); 86 | $this->assertAttributeEmpty('classLoader', $kernel); 87 | 88 | $response = $kernel->handle($request, 1, true); 89 | 90 | $this->assertInstanceOf('Symfony\Component\HttpFoundation\Response', $response); 91 | $this->assertEquals(200, $response->getStatusCode()); 92 | } 93 | 94 | public function testShouldCopyLegacyResponseData() 95 | { 96 | $kernel = new Symfony14Kernel(); 97 | $rm = new \ReflectionMethod($kernel, 'convertResponse'); 98 | $rm->setAccessible(true); 99 | 100 | $legacyResponse = $this->prophesize('sfWebResponse'); 101 | $legacyResponse->getHttpHeaders()->willReturn($headers = array( 102 | 'Content-Type' => 'text/html', 103 | 'Location' => 'http://localhost', 104 | 'X-Custom-Header' => 'value', 105 | )); 106 | $legacyResponse->getContent()->willReturn($content = 'content'); 107 | $legacyResponse->getCharset()->willReturn($charset = 'charset'); 108 | $legacyResponse->getStatusCode()->willReturn($status = 200); 109 | 110 | /** @var Response $response */ 111 | $response = $rm->invoke($kernel, $legacyResponse->reveal()); 112 | 113 | $this->assertEquals($status, $response->getStatusCode()); 114 | $this->assertEquals($charset, $response->getCharset()); 115 | $this->assertEquals($content, $response->getContent()); 116 | $this->assertEquals($headers['Content-Type'], $response->headers->get('Content-Type')); 117 | $this->assertEquals($headers['Location'], $response->headers->get('Location')); 118 | $this->assertEquals($headers['X-Custom-Header'], $response->headers->get('X-Custom-Header')); 119 | } 120 | 121 | protected function createProphesizedContainer($request) 122 | { 123 | $container = $this->prophesize('Symfony\Component\DependencyInjection\ContainerInterface'); 124 | 125 | if (Kernel::MAJOR_VERSION === 3) { 126 | $request_stack = new RequestStack(); 127 | $request_stack->push($request); 128 | $container->has('request_stack')->willReturn(true); 129 | $container->get('request_stack')->willReturn($request_stack); 130 | } else { 131 | $container->has('request_stack')->willReturn(false); 132 | $container->get('request')->willReturn($request); 133 | } 134 | 135 | return $container; 136 | } 137 | } 138 | -------------------------------------------------------------------------------- /Tests/bootstrap.php: -------------------------------------------------------------------------------- 1 | loader = $loader; 25 | } 26 | 27 | /** 28 | * {@inheritdoc} 29 | */ 30 | public function build(ContainerBuilder $container) 31 | { 32 | // The loader can be null when clearing the cache. 33 | if (null !== $this->loader) { 34 | $container->addCompilerPass(new LoaderInjectorPass($this->loader)); 35 | } 36 | 37 | $container->addCompilerPass(new KernelConfigurationPass()); 38 | $container->addCompilerPass(new ReplaceRouterPass()); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "theodo-evolution/legacy-wrapper-bundle", 3 | "type": "symfony-bundle", 4 | "keywords": ["legacy", "symfony1", "symfony2"], 5 | "homepage": "http://www.theodo.fr", 6 | "license": "MIT", 7 | "authors": [ 8 | { 9 | "name": "Theodo", 10 | "homepage": "http://www.theodo.fr" 11 | } 12 | ], 13 | "minimum-stability": "dev", 14 | "autoload": { 15 | "psr-4": { 16 | "Theodo\\Evolution\\Bundle\\LegacyWrapperBundle\\": "" 17 | } 18 | }, 19 | "require": { 20 | "php": ">=5.3.3|>=7.1.3", 21 | "composer/composer": "~1.0@dev", 22 | "symfony/framework-bundle": "~2.1|~3.0|~4.0" 23 | }, 24 | "require-dev": { 25 | "phpunit/phpunit": "~4.1", 26 | "phpspec/prophecy": "~1.1", 27 | "phpspec/prophecy-phpunit": "~1.0", 28 | "theodo-evolution/fake-projects": "dev-master" 29 | }, 30 | "repositories": [ 31 | { 32 | "type": "git", 33 | "url": "https://github.com/theodo/theodo-evolution-fake-projects" 34 | } 35 | ], 36 | "extra": { 37 | "branch-alias": { 38 | "dev-master": "1.1.x-dev" 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /phpunit.xml.dist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 15 | 16 | 17 | 18 | ./Tests 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | ./ 29 | 30 | ./Resources 31 | ./Tests 32 | ./vendor 33 | 34 | 35 | 36 | 37 | --------------------------------------------------------------------------------