try it now

Encoding of Symfony 2

Home / Encoding of Symfony 2

Do you need to encode a Symfony 2 project?

 
Symfony 2 is intensively using annotations. Also it detects custom classes by doing source code parsing. While Reflection API is used for getting annotations and that part works perfectly with encoded files, tokenizing of source files and searching for 'namespace' and 'class' keywords is also used. It's obvious that neither of the keywords can be found in the scripts after encoding. That's why running encoded Symfony 2 php scripts do not work out of the box. 
 
We used the latest Symfony2 default project and encoded the src directory for a test
(available for downloading as zip archive or by using composer from http://symfony.com/download)
 
After running the tests with the latest Symfony2 we found that it does not work out of the box with encoded files but we have done a thorough investigation and can give you a recipe. We are not experts in Symfony and do not use it in our work, so what we suggest may not fully correspond with the concept of Symfony engine. However, we sure this gives an idea of what happens and give ideas of how this can be fixed.
 
A general problem with Symfony is that it parses source files. I was surprised when found that they do use Reflection API for reading annotations but they also still parse source code for detecting classes. Frankly, this looks as a weird combination.  We also found that Symfony uses token_get_all() in some other parts of the code, which means the solution below may not be enough and require further updates.
 
We developed two possible ways of fixing the issue and running protected files with Symfony. The first is a quick but ugly solution that needs a small modification to the Symfony engine and also some modifications of annotations in custom controllers.
 
1) We need to change how Symfony detects that a file contains a class. If you find the findClass() method in AnnotationFileLoader class, you'll see that they tokenize source code and search for 'namespace' and 'class' keywords. Obviously, it does not work for encoded files. So the idea is to change that to a direct filename-to-classname mapping. This will work as Symfony insists on using coding standards for file names, class names and how files are allocated in directories. 
 
Edit AnnotationFileLoader.php and add a new private function:
 
private function findClassInPath($path) {
if ($path[0] == DIRECTORY_SEPARATOR) $path = substr($path, 1);
$className = str_replace(DIRECTORY_SEPARATOR, '\\', str_replace('.php', '', $path));
while(true) {
if (class_exists($className)) return $className;
if (($p = strpos($className, '\\')) === false) return false;
$className = substr($className, $p+1);
}
}
 
Then edit the findClass() method and add the following line at the top of the method's code:
 
protected function findClass($file)
{
    if ($className = $this->findClassInPath($file)) return $className;
......
 
The change lets Symfony detect encoded class file without parsing it:
src/Acme/DemoBundle/Controller/DemoController.php -> \Acme\DemoBundle\Controller\DemoController
 
It should be possible to write the above code into a subclass and setting it in configurations files instead of standard parser. This will look better from Symfony's concept but produce the same result. 
 
 
2) You also need to change short annotations in your controllers to full ones. We did this change in Acme/DemoBundle/Controller/DemoController.php
 
// import the "@Route" and "@Template" annotations
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;
 
Change this:
 
/**
  * @Route("/", name="_demo")
  * @Template()
  */
 
 
To that:
 
/**
  * @Sensio\Bundle\FrameworkExtraBundle\Configuration\Route("/", name="_demo")
  * @Sensio\Bundle\FrameworkExtraBundle\Configuration\Template()
  */
 
 
Please note, there may be other annotations in your code and they should be also changed to the full version, e.g. @Security in SecuredController.php demo file.
 
After that you may encode updated controller files as usual and run the application. (Make sure you have a SourceGuardian loader installed in php.ini) Please note, that the above changes do not break compatibility with unencoded code. The unencoded code may still be run.
 
It's no need to encode any standard Symfony files.
 
We fully understand that the above is not a good way to fix things as it requires both changing the engine and changing custom files. But that was a quick solution we found. We also have an idea of making a smarter fix that should allow encoding of Symfony (or other engines) files without any manual modifications of the code. Please bear with us as it will take some time to develop and test it. We are going to make it available on our website soon. 
 
Kind Regards
 
Alexander Belonosov
Senior Developer
SourceGuardian

Support Area

If you have any questions, please fill out our support form. Also, keep an eye out for our new instructional videos which are coming soon.
View Support Area

SourceGuardian

UK Office
 
Office S14
Tanfield Lea Business Centre
Stanley
County Durham
DH9 9DB
United Kingdom
 
USA Office
 
2880 Zanker Road
San Jose, California 95134
United States
 

 





"You give the best support and assistence I ever found around. Really a big Thanks."
Gianluca Baldo, http://www.phpauction.org
TRY SOURCEGUARDIAN FREE FOR 14 DAYS
Account Login:

login Forgotten Password?
Connect with us
Bookmark
facebook linkedin twitter rss
© Copyright 2002 - 2017 SourceGuardian Limited
Privacy Policy l Terms & Conditions l Company Info l Contact us l Sitemap l PHP Weekly News