We launched new forums in March 2019—join us there. In a hurry for help with your website? Get Help Now!
    • 34162
    • 1 Posts
    I’d like to chime in with two cents here, if everyone doesn’t mind.

    The current way that plugins are stored in the DB and then eval() has been bothering me, as has another aspect that we’ll get to in the moment.  This morning during my two hour cat nap it struck me why (other than the obvious performance hit for repeatedly eval()’ing code):

    We are setting ourselves up to have problems as we move more and more things into the plugins due to the fact there is no namespace.  Looking at the FCKEditor plugin, for instance, we see:

    if (!function_exists('getFCKEditorSettings')) {
    	function getFCKEditorSettings() {
            ...
            };
    };
    


    That’s fine, but what happens if a plugin author tried to define a function with the same name as another plugin author?  Or if someone accidently defined a plugin with the name of a core function and/or existing PHP function?  At the moment one of two things happens:  either the person didn’t call function_exists() and things just break horribly-- potentially even making it so if the person doesn’t have phpMyAdmin or similiar they can’t even access the backend to fix the problem-- OR the plugin doesn’t declare its functions and ends up calling the previously defined funcs, which would have completely unpredictable behavior.

    So, in a nutshell, this is my suggestion:  every plugin should be enclosed in its own class in the form of:

    class plugin_fckeditor extends plugin {
         function plugin_fckeditor() {
                   ....
         };
         function getFCKEditorSettings() {
            ...
         };
    };
    


      Several nice things result:
      [list]
    • Every plugin now has its own namespace.
    • Who doesn’t like OO design?
    • [li]Plugins automatically have an init function, if needed
    • By extending the plugin base class, we can easily add/expand functionality of plugins in the future, if needed.
    • A biggie:  filesystem based plugins become very, very practical, allowing us to abstract out parts of the core (*)
    • And much, much more!

    (*)  As an example:  Imagine that frontend editing, capsules/containers, placeholders, custom fields, etc. were all created as distinct plugins, located on the filesystem.  Now the $modx->parseDocumentSource() function just has to see which plugins have been activated on the backend for the onParseDocument event and load those particular classes.  As part of their startup, they pass in the token(s) that they work with.  As parseDocumentSource examines the source, it only calls those plugins that are needed:  so, for instance, if there are no [[]] tags, the capsules/containers plugin doesn’t even get called.  The end result:  the document parser is considerably more efficient than it is now, an admin can completely deactivate features he doesn’t use, AND we don’t take the repeated performance hits for repeatedly calling eval() on the plugin code.

    Of course, DB based plugins would continue to operate exactly as they do now and current plugins would still work, but I would make a case that for perfomance reasons all plugins we distribute with the core should be filesystem based to minimize the eval() overhead (and to demonstrate the most efficient method for creating plugins).

    So...  what are everyone’s thoughts?  I don’t mind putting this together and, in fact, already have a very solid start on another little project, if everyone sees the value that I do.

    [/list]
      • 25663 MODX Staff
      • 12,272 Posts
      It sounds awesome and like a great way to continue to make our solution better/faster and in line with my mantra of "less is more". laugh

      Would this give us the control of plugin execution order?
        Ryan Thrash, MODX Co-Founder
        Follow me on Twitter at @rthrash or catch my occasional unofficial thoughts at thrash.me
        • 34162
        • 1 Posts
        Quote from: rthrash at Aug 11, 2005, 12:01 PM

        Would this give us the control of plugin execution order?

        Yes, by using something similiar to:

        $modx->registerPlugin("plugin_fckeditor", <PRIORITY>);
        


        This would be done after the class definition. The registerPlugin would be responsible for creating the instance of the plugin and the optional priority would control execution order; all plugins set to the same level would be done FIFO. I see this on a scale of 0 - 100, with default priority being something like "50", so that there is space before and after it; lower numbered priorities would execute first.

        $modx->plugins[EVENTNAME][PRIORITY][] would store the plugins and the events they’ve attached to.

        Make sense?
          • 25663 MODX Staff
          • 12,272 Posts
          Yep. Perfect!
            Ryan Thrash, MODX Co-Founder
            Follow me on Twitter at @rthrash or catch my occasional unofficial thoughts at thrash.me
            • 32963
            • 1,732 Posts

            The name space solution is very nice indeed. smiley

            Here’s what came to mind...

            Rather than having the user create a class file why not let the system handle all of that? In other words, the user simply create his/her functions and plugin codes as they normally would with the exception that their startup code is wrapped inside a function called init or main:

            function init(){
               // my startup code there
            }
            
            function MyFunction(){
              // my code here
            }


            The manager will then take the above and wrap it into a class file or object.

            manager generated class object:

            class plugin-name {
            	function init(){
            	   // my startup code there
            	}
            
            	function MyFunction(){
            	  // my code here
            	}
            }


            In addition to the above the user could then wrap his/her event calls inside an function name:


            function OnWebPageInit(event) {
            	// some code here
            }



            The class files can then be grouped into a single event file. For exmaple, onwebpageinit.inc.php. When the OnWebPageInit event is called this file would be included once. Checks could be added to the event files to ensure that the class objects are not loaded twice.

            This class method could also be applied to snippets. This would then give us the ability to only evaluate the snippet class once per parse pass.

            Note: On the issue of storage... File-based storage has it’s advantage and disadvantage. One of the disadvantage is speed. It’s normally takes a longer time to include a class file from the file system rather than to pull it from memory. It’s not noticeable when using one or two plugins but it’s a problem when you start doing it for quite a few plugins.

            Execution Order
            On the issue of execution order. I don’t think the execution order of the snippet should be hard coded inside the class file. This should be an option that the user can change from via the plugin’s event interface.

              xWisdom
              www.xwisdomhtml.com
              The fear of the Lord is the beginning of wisdom:
              MODx Co-Founder - Create and do more with less.
              • 34162
              • 1 Posts
              Two thoughts on my initial reading (keeping in mind I have been up for three straight days now working on the new manager w/ no sleep):

              1. Classes are built into PHP, so why reinvent the wheel and add additional overhead by creating something in PHP to do what the language already does?
              2. If you have two plugins with a function named init(), which is what it looks like you are suggesting, the entire system breaks. Hence the classes: six plugins can use the same function names and no one cares. In fact, this is actually DESIRED since you can create a common API. $plugin->getEvents(), for instance, can return the events the plugin wants to listen to regardless of the type of plugin. Or $plugin->doInstall(); can always run the install for the plugin, creating any needed tables, etc. Standardization and predictability is key.

              As for filesystem: actually, it would be exceedingly more difficult to be more inefficient than the system currently is, from memory storage to caching to a lot of the DB structure.

              And execution order *definitely* needs to be controllable by the programmer. Just look in the source code to see this: there are at least a half dozen comments in the sourcecode that says things like "snippets must be processed before chunks" or some such. No system of any complexity should remove that control from the ones writing the code. I have at least a dozen ideas for plugins that execution order is a necessity; it’s not even possible to write them without that control. Heck, even the most simplistic blogging software has these controls built into the API; no way we are going to ever be taken seriously while stripping such control from the programmers-- execution order is even the first thing they teach in freshman level programming courses!

              I’m sure I had other thoughts, but I’m too tired to continue trying to think about it at the moment. Need to get back to work.
                • 32963
                • 1,732 Posts
                Classes are built into PHP, so why reinvent the wheel and add additional overhead by creating something in PHP to do what the language already does?

                We are not trying to reinvent the wheel. What I’m suggesting is that the parser should wrap the functions written by the user inside a class object. This would mean that each two plugins can use the same funcion names without causing conflicts.

                As it releates to the execution priority I believe that MODx should be flexible enough for everyone to use. The idea of allowing the user to change the execution priority does not take anything away from the programer. I believe there will be cases where a user might want a specific plugin to run at priority #1 while another to run at priority #2.This I believe should be done from within the Manager interface not by editing the plugin files.
                  xWisdom
                  www.xwisdomhtml.com
                  The fear of the Lord is the beginning of wisdom:
                  MODx Co-Founder - Create and do more with less.
                  • 25663 MODX Staff
                  • 12,272 Posts
                  Why don’t we just enable both models: one for end users with the manager interfae as is now and one via the auto-loading-drop-in-a-directory model?

                  We could get the kinks worked out in the filesystem model then port the load/execution order into the DB/manager method.
                    Ryan Thrash, MODX Co-Founder
                    Follow me on Twitter at @rthrash or catch my occasional unofficial thoughts at thrash.me
                    • 1764
                    • 680 Posts
                    I’ve been thinking about this a bit. I like the idea of storing snippets and such as files but I’d miss the ease of making quick changes to DB snippets. But why can’t we have the best of both worlds? Why not be able to edit FS snippets the same way you can edit DB snippets? The end user wouldn’t even be able to tell the difference.

                    Maybe this is what you guys were thinking all along but it case it wasn’t I thought I’d mention it.
                      • 28042 ☆ A M B ☆
                      • 24,524 Posts
                      I have a system for editing language files that is much the same as editing snippets or chunks; I even plugged it into the Manager. Of course, this does mean that the /assets/lang folder has to be world-writeable, which doesn’t make me too happy. I’ve been considering moving the whole system into the database just for the security.
                        Studying MODX in the desert - http://sottwell.com
                        Tips and Tricks from the MODX Forums and Slack Channels - http://modxcookbook.com
                        Join the Slack Community - http://modx.org