Development

#1245 (symfony incorrectly autoloading BasesfGuardAuthActions (and maybe other plugin classes))

You must first sign up to be able to contribute.

Ticket #1245 (closed defect: invalid)

Opened 2 years ago

Last modified 1 year ago

symfony incorrectly autoloading BasesfGuardAuthActions (and maybe other plugin classes)

Reported by: Mark.Quezada Assigned to:
Priority: major Milestone: plugins
Component: cache Version: 1.0.0-beta1
Keywords: Cc:
Qualification:

Description

It seems like the config_autoload.yml.php file is trying to autoload BasesfGuardAuthActions? like this:

'sfGuardAuth/BasesfGuardAuthActions' => '/path/to/BasesfGuardAuthActions.class.php'

instead of like this:

'BasesfGuardAuthActions' => '/path/to/BasesfGuardAuthActions.class.php'

This happens when trying to extend sfGuardAuth in your own project and creating an actions.class.php file that inherits from BasesfGuardAuthActions?. When trying to access the actions for your extended actions.class.php file, symfony will complain that it cannot find BasesfGuardAuthActions?.class.php unless you add a manual require in that file.

Some more info in this forum post:

http://www.symfony-project.com/forum/index.php/m/17851/#msg_17851

Change History

12/27/06 03:42:55 changed by subzero2000

  • status changed from new to closed.
  • resolution set to invalid.

At first I thought that this was a legitimate bug, but after reviewing the symfony source, I now believe that this bug can safely be marked as invalid. There are three files that are relevant to the symfony autoload behavior being reported as faulty:

trunk/data/config/autoload.yml trunk/lib/config/sfAutoloadConfigHandler.class.php trunk/lib/util/sfCore.class.php

First the relevant parts of trunk/data/config/autoload.yml

1  autoload:
...
31   plugins_module_lib:
32     name:           plugins module lib
33     path:           %SF_PLUGINS_DIR%/*/modules/*/lib
34     prefix:         2
35     recursive:      on
...
55   modules:
56     name:           module
57     path:           %SF_APP_DIR%/modules/*/lib
58     prefix:         1
59     recursive:      on

Note, these are the only directories in symfony's default autoload.yml with the prefix parameter set.

Next, the relevant parts from trunk/lib/config/sfAutoloadConfigHandler.class.php:

99 	        $regex = '~^\s*(?:abstract\s+|final\s+)?(?:class|interface)\s+(\w+)~mi';
100 	        foreach ($files as $file)
101 	        {
102 	          preg_match_all($regex, file_get_contents($file), $classes);
103 	          foreach ($classes[1] as $class)
104 	          {
105 	            $prefix = '';
106 	            if (isset($entry['prefix']))
107 	            {
108 	              // FIXME: does not work for plugins installed with a symlink
109 	              preg_match('~^'.str_replace('\*', '(.+?)', preg_quote(str_replace('/', DIRECTORY_SEPARATOR, $path), '~')).'~', $file, $match);
110 	              $prefix = $match[$entry['prefix']].'/';
111 	            }
112 	
113 	            $data[] = sprintf("'%s%s' => '%s',", $prefix, $class, $file);
114 	          }
115 	        }

The code inside the if (isset($entryprefix?)) is the portion of the autoload file generation code that prepends the name of the module followed by a slash.

Lastly, the relevant code from trunk/lib/util/sfCore.class.php:

166 	    // see if the file exists in the current module lib directory
167 	    // must be in a module context
168 	    if (sfContext::hasInstance() && ($module = sfContext::getInstance()->getModuleName()) && isset(self::$classes[$module.'/'.$class]))
169 	    {
170 	      require(self::$classes[$module.'/'.$class]);
171 	
172 	      return true;
173 	    }
174 	
175 	    return false;

The if block that starts on line 168 verifies that you are in a module context before trying to prepend module name with a trailing slash to the class name. If that condition is met, then the appropriate file containing the class is included via a require statement.

Based on this, if you try to include code from anywhere in the lib directory of a module in either your code or from within a plugin and the code doing the including is not in that module, then autoload will not include that file because the autoload array has that entry prepended with the module name and a trailing slash. A trailing slash is a good choice, as it is not legal in a class name and therefore cannot be matched by trying to create a class with that name.

The reporter is trying to include a file that lives in plugins/sfGuardPlugin/modules/sfGuardAuth/lib/BasesfGuardAuthActions.class.php, which is in the lib directory of the sfGuardAuth module of the sfGuardPlugin. The default symfony autoload.yml will prevent that from being included from anywhere outside of the sfGuardAuth module of the sfGuardPlugin.

I suspect that the reason why some are not seeing that bug is that they may have overridden the autoload.yml on the application level perhaps from an application written under 0.6.3 or earlier. It does not appear that "symfony upgrade 1.0" removes an application's custom autoload.yml if it exists (based on a cursory review of trunk/data/tasks/sfPakeUpgrade.php). A custom autoload.yml without any prefix parameters will allow this to work as the reporter desires.

03/27/07 01:20:41 changed by subzero2000

  • status changed from closed to reopened.
  • resolution deleted.
  • component set to cache.

Re-opening ticket.

Upon further inspection, the if statement in util/sfCore.class.php at line 168 will not work if you declare a class in the lib directory in a module, then attempt to autoload that class by extending it in the actions.class.php of either the module or another module of the same name in the case of overriding plugins. The issue is that the namespace is taken from the action's instance on the action stack, which means the action has to exist to be on the action stack. Since the action is attempting to be created at this point, you will not be able to obtain the namespace for the module, and the autoload of the module-specific class will fail. autoloading once the action actually exists should work properly, in my opinion, although I have had the time to verify this.

09/07/07 23:49:12 changed by davedash

  • status changed from reopened to closed.
  • resolution set to invalid.

Okay looking at this using 1.0.6 this is no longer in the autoload files at all, which is good. this means this is not a bug per se.

It's arguable whether the framework should include the autload magic all the way to the point of adding autoloading into deep plugin/module/lib folders. I'm closing this for now, as it seems autoloading is a bit overdone especially in cases like this where you will probably only do one require statement in a given symfony app. Unlike Model classes which might be used all over your project and therefore have more of a reason to be auto-indexed.

That was a mouthful.