SitePoint Sponsor

User Tag List

Results 1 to 6 of 6
  1. #1
    SitePoint Member
    Join Date
    May 2009
    Posts
    4
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    Extending objects through plugins

    I'm currently looking into a way to implement extensibility through a plugin mechanism. As an illustration, this is what I've come up with so far.

    PHP Code:
    /**
     * Page class
     */
    class Page {
        private 
    $id;
        private static 
    $plugins = array();
        
        static function 
    registerPlugin($plugin) {
            
    self::$plugins[] = $plugin;
        }
        
        function 
    __construct($id) {
            
    $this->id $id;
        }
        
        protected function 
    getPlugins() {
            return 
    self::$plugins;
        }
        
        function 
    getId() {
            return 
    $this->id;
        }
        
        function 
    checkAccess($user) {
            foreach (
    $this->getPlugins() as $plugin) {
                if (
    $plugin instanceof AccessControlPlugin &&
                    
    $plugin->checkAccess($this$user) === TRUE) {
                    return 
    TRUE;
                }
            }
            
            return 
    FALSE;
        }
    }

    /**
     * Access control plugin interface
     */
    interface AccessControlPlugin {
        function 
    checkAccess($node$user);
    }

    /**
     * Simple plugins
     */
    class Plugin1 implements AccessControlPlugin {
        function 
    checkAccess($node$user) {
            echo 
    'Page '$node->getId() .': Checking access for '.
                
    $user .' in Plugin1<br />';
        }
    }

    class 
    Plugin2 implements AccessControlPlugin {
        function 
    checkAccess($node$user) {
            echo 
    'Page '$node->getId() .': Checking access for '.
                
    $user .' in Plugin2<br />';
        }
    }

    class 
    Plugin3 implements AccessControlPlugin {
        function 
    checkAccess($node$user) {
            echo 
    'Page '$node->getId() .': Checking access for '.
                
    $user .' in Plugin3<br />';
        }

    In this example the page object would represent an individual page and each plugin would implement some kind of access control mechanism to allow or deny a user access to the page.

    The plugins would be registered through the static method registerPlugin, but from what I've been reading here static methods seem to be frowned upon. It seems sensible to me to use static data as otherwise every time a page is created the plugins would need to be passed to the instance.

    Is there a better way that avoids the static calls and data?

  2. #2
    SitePoint Addict Mastodont's Avatar
    Join Date
    Mar 2007
    Location
    Czech Republic
    Posts
    375
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Do you plan to create instance of Page class? If yes, then do not use static methods (except shared methods for more instances).

  3. #3
    SitePoint Member
    Join Date
    May 2009
    Posts
    4
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Yes, the there may be more than one instance of Page. Can you explain more what you mean by don't use except for shared methods? What I need is for the plugins to be shared across instances, isn't this the purpose of static?

  4. #4
    . shoooo... silver trophy logic_earth's Avatar
    Join Date
    Oct 2005
    Location
    CA
    Posts
    9,013
    Mentioned
    8 Post(s)
    Tagged
    0 Thread(s)
    You want to look at the Decorator Pattern, and the Observer Pattern.
    Logic without the fatal effects.
    All code snippets are licensed under WTFPL.


  5. #5
    SitePoint Member
    Join Date
    May 2009
    Posts
    4
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I have looked at these patterns, the decorator seems to wrap the class up in a new class, which is no good for what I need (correct me if I am wrong). The observer pattern is sort of what I need, but I need all instances to have the same observers.

    In my example I could have a number of different access rules and these would only need to be set up in one place in the application's initialisation and they would be available to all instances. How could the observer pattern be implemented to fit my requirements?

  6. #6
    SitePoint Member
    Join Date
    May 2009
    Posts
    4
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Been doing some reading and thinking. Is this a better approach? Does it make sense?

    PHP Code:
    /**
     * Page factory
     * Responsible for making sure pages get same plugins
     */
    class PageFactory {
        private 
    $plugins;
        
        function 
    __construct($plugins) {
            
    $this->plugins $plugins;
        }
        
        function 
    getPage($id) {
            
    $page = new Page($id$this->plugins);
            return 
    $page;
        }
    }

    /**
     * Simple page class which is plugable
     */
    class Page {
        private 
    $id;
        private 
    $plugins;
        
        function 
    __construct($id$plugins) {
            
    $this->id $id;
            
    $this->plugins $plugins;
        }
        
        function 
    checkAccess($user) {
            foreach (
    $this->plugins->getPlugins() as $plugin) {
                if (
    $plugin instanceof AccessControlPlugin &&
                    
    $plugin->checkAccess($this->id$user)) {
                    return 
    TRUE;
                }
            }
        }
    }

    /**
     * Simple plugin collection
     */
    class PluginCollection {
        private 
    $plugins;
        
        function 
    registerPlugin($plugin) {
            
    $this->plugins[] = $plugin;
        }
        
        function 
    getPlugins() {
            return 
    $this->plugins;
        }
    }

    /**
     * Access control plugin interface
     */
    interface AccessControlPlugin {
        function 
    checkAccess($id$user);
    }

    /**
     * Example plugins
     */
    class Plugin1 implements AccessControlPlugin {
        function 
    checkAccess($id$user) {
            
    // Do access checking here
        
    }
    }

    class 
    Plugin2 implements AccessControlPlugin {
        function 
    checkAccess($id$user) {
            
    // Do access checking here
        
    }
    }

    /**
     * Example implementation
     */
    $pluginCollection = new PluginCollection();
    $pluginCollection->registerPlugin(new Plugin1());
    $pluginCollection->registerPlugin(new Plugin2());
    $pageFactory = new PageFactory($pluginCollection);
    $p1 $pageFactory->getPage(100);
    $p1->checkAccess('jsmith');
    $p2 $pageFactory->getPage(200);
    $p2->checkAccess('jsmith'); 


Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •