We launched new forums in March 2019—join us there. In a hurry for help with your website? Get Help Now!
    • 25663 MODX Staff
    • 12,272 Posts
    Victor and I had a really interesting discussion about how the manager/document parser works, for which I was almost totally useless in describing what was really going on under the hood and in the event loop inside the parser. Since he has considerable experience with some other CMSes like ATG Dynamo and Vignette, and he has actually waded a bit through the code, I figured his insight might prove useful as to optimal ways to do things. I’ll leave it at that and let him take over from here... Victor, if you’re out there reading this in RSS feed land, please come on in and post away!

      Ryan Thrash, MODX Co-Founder
      Follow me on Twitter at @rthrash or catch my occasional unofficial thoughts at thrash.me
      • 31337
      • 258 Posts
      I think someone who knows that architecture better than can comment on this. But I’ve been trying to wrap my brain around how the existing event model works.

      The way I see it is that for every page request received, an event loop starts with several steps in it. At each step, a global flag is set up for that step. A plugin is then loaded and eval()’ed during that cycle, and the plugin contains logic to catch that particular flag. So you end up with code like:

      if ($flagA) { do something }
      if ($flagB) { do something else}

      And that’s how a plugin deals with events during a request.

      So before I go any futher....is this description correct? Am I missing anything important here?
        • 32963
        • 1,732 Posts
        Hi Victor,

        The design used for plugins is a branch of what is being used for snippets. I first started out with Snippets that could listen to events. Then we latter on decided that they should be separate to avoid confusion. Now we are saying let’s merge them.

        The way you have explained it is the way it now works. the current design triggers the plugin by passing the event name to the plugin. The plugin then handles the event.

        Future versions will use a class/function structure to process event calls.



          xWisdom
          www.xwisdomhtml.com
          The fear of the Lord is the beginning of wisdom:
          MODx Co-Founder - Create and do more with less.
          • 31337
          • 258 Posts
          Raymond,

          Thanks for the reply and the good info.

          The reason I started looking at the event model is that it appears to be a one way communication -- i.e., the plugin just listens for an event and blindly recieves it. There’s no context of the event and more importantly, there’s no communication between the plugin back to the event, nor to any other plugin that’s interested in the event. This is also a pretty ineffecient design since it requres every event to iterate through a list of plugins regardless of whether they want that event or not. There’s also an additional problem in that once the event is passed to the plug-in there’s no further communication --- which means the plugin must potentially deal with error conditions outside of its scope, etc.

          My suggestion is to move to a design where you have a central dispatcher for events. All events are sent directly to the dispatcher. Every plugin at load time can register with the dispatcher for certain events, and when the event is received, the dispatcher can then call the proper method on the plug-in that wants that event.

          This presents a much more modular structure and also allows things like proper ordering of event handling. And in fact allows a plug-in to handle an event more than once depending on who else has handled it. I think it’d also make the writing of plugins much simpler for coders since there’s less things they have to do. And it’d also allow for creation of error handler plugins that can register for events like the database going down, and dealing with it gracefully.

          I’ve attached a PDF that gives a pretty technical discussion of how this type of design work. The PDF is targetted at embedded system design, but much of the content is relevant here.


            • 25663 MODX Staff
            • 12,272 Posts
            Thanks Victor. Very cool advice and I’m sure an onslaught of questions to ensue...
              Ryan Thrash, MODX Co-Founder
              Follow me on Twitter at @rthrash or catch my occasional unofficial thoughts at thrash.me
              • 32963
              • 1,732 Posts
              Hmmm,

              As is now plugins have to be registered before they can listen to events, right?

              The registration is handled by the system and once an event is triggered (see $modx->invokeEvent() method) the list of registered plugins are invoked. There is also an event object that the plugins can use to pass values you the event output (see $e->output).

              The plugins can also send alert message via $e->alert(). And there is also a stopPropagation() function which a plugin can use to prevent it’s fellow plugins from been invoked.

              The model does not support priority at this time.

              I’ll have a look at the PDF but did you get a chance to look at the Event object and invokeEvent functions?
                xWisdom
                www.xwisdomhtml.com
                The fear of the Lord is the beginning of wisdom:
                MODx Co-Founder - Create and do more with less.
                • 31337
                • 258 Posts
                Quote from: xwisdom at Nov 10, 2005, 10:09 PM

                Hmmm,

                As is now plugins have to be registered before they can listen to events, right?

                The registration is handled by the system and once an event is triggered (see $modx->invokeEvent() method) the list of registered plugins are invoked. There is also an event object that the plugins can use to pass values you the event output (see $e->output).

                The plugins can also send alert message via $e->alert(). And there is also a stopPropagation() function which a plugin can use to prevent it’s fellow plugins from been invoked.

                The model does not support priority at this time.

                I’ll have a look at the PDF but did you get a chance to look at the Event object and invokeEvent functions?


                I did look at the Event object and associated functions. In essence, I am looking at the flow going different from how it is now. So in other words, instead of the plug-in doing a switch stamement on an event type, the event dispatcher calls the method on the plu-in itself.

                Anyway, take a look at the PDF and let me know your thoughts. In no way am I claiming that the current system is bad, just voicing an opinion that we should take a look at different architectures to see if anything in them makes sense for us to use.
                  • 32963
                  • 1,732 Posts
                  Quote from: vbrilon at Nov 10, 2005, 10:16 PM

                  I did look at the Event object and associated functions. In essence, I am looking at the flow going different from how it is now. So in other words, instead of the plug-in doing a switch stamement on an event type, the event dispatcher calls the method on the plu-in itself.

                  You’re right on target Victor. That’s on of the things that should have been addressed with tp4.

                  The new design will treat Widgets like objects. Each widget will expose it’s event in the form:

                  widget.OnEventName($event, $args)

                  So you don’t have to use the switch case any more. Will continue to read the events whitepattern




                    xWisdom
                    www.xwisdomhtml.com
                    The fear of the Lord is the beginning of wisdom:
                    MODx Co-Founder - Create and do more with less.
                    • 31337
                    • 258 Posts
                    The other piece I forgot to mention in my original post is that the proposed architecture makes it easier to allow plugins to register for a "class" of an event. I.E., any page-rendering event or any error event, without having to iterate through all the different event types.
                      • 25663 MODX Staff
                      • 12,272 Posts
                      Since the events and parser are inextricably linked for the most part, I’m moving this discussion here:

                      Implementing it all
                      The above is not definitive. We hope be able to make the parser consist of one recursive preg_match (or whatever) on nestable [[ tags with a separate pass for non-cached objects. The revsised syntax follows, which would allow for things like [[widget? &color=`[[*colors]]` &foo=`[[blah? &bar=`[[blahblah]]` ]]` ]] to work.

                      This would all be done in hopes of optimizing the performance and flexibility of the document parser via fewer loops to go through, and using function callbacks vs. case/switch statements. It would also hopefully provide for:

                      • all objects being cachable or non-cachable
                      • all objects being nestable

                      Here’s how to translate the current methods into the proposed new way:


                      • [[widget]] = [[snippet]] or {{chunk}} with a static/dynamic flag, plus a caching flag, eliminating the requirement to configure caching parameters via [!snippet!]
                      • [[~linkID]] = [~linkID~]
                      • [[+placehoder]] = [+placeholder+]
                      • [[++system_setting]] = a system placeholder with namespace uniqueness [(site_setting)]
                      • [[*contentField]] = Template Variable [*tv*]
                      • [[*#contentField]] = QuickEdit enabled content field [*#tv-or-content*]
                      • [[^parse_time]] = also time, date, size for current date/time and bytes of code (HTML text only... no includes or linked files/images) sent to the browser [[^timing^]]

                      • Here’s some completely new/majorly enhanced constructs:

                      • [[$template]] = insesrts a template or sub-template in the page (n/a previously)
                      • [[%language]] = way to handle multi-lingual sites, to be addressed eventually (n/a previously)
                      • [[@onEventName]] = used to raise an event from within the page and allows for calling / invoking custom or system events. For example: [[@OnRenderRichText? &editor=`FCKEditor` &elements=`mytextarea`]] will invoke the RTE plugins and render the RTE on the page, replacing the textarea of ID=mytextarea with the FCKEditor instance, or [[@OnBackupInit]] could be used to trigger a backup whenever a page is viewed
                      • [!anything!] = for developers who want to maintain/override caching on any of the above items [!snippet!] (and previously limited only to snippets)

                      The following modifiers are what makes fair game sense to use:
                      ~ ! @ $ % ^ *#  _ - + = { } . 
                      


                      The following don’t to me due to logic/code/html associations/implications:
                      \ / ( ) ? & : ; ,
                      


                      The # is obviously used by QuickEdit, which needs to be considered in the switch handling, obviously. The ! could also be used to denote inline cache disabling as needed: [[!non-cachable-snipet-call]], but more discussion is needed on this as to how it would affect execution times and overall architecture.
                        Ryan Thrash, MODX Co-Founder
                        Follow me on Twitter at @rthrash or catch my occasional unofficial thoughts at thrash.me