CodeIgniter Forums
Plugin Handling Class - Extends the CI_Hooks Class - Printable Version

+- CodeIgniter Forums (https://forum.codeigniter.com)
+-- Forum: Archived Discussions (https://forum.codeigniter.com/forumdisplay.php?fid=20)
+--- Forum: Archived Libraries & Helpers (https://forum.codeigniter.com/forumdisplay.php?fid=22)
+--- Thread: Plugin Handling Class - Extends the CI_Hooks Class (/showthread.php?tid=10594)

Pages: 1 2 3


Plugin Handling Class - Extends the CI_Hooks Class - El Forum - 08-05-2008

[eluser]Xeoncross[/eluser]
Based on disccustions Here and here I built a way to handle plugins without breaking/changing the CI core - or even your system design pattern.

Just drop this class into your application/lib/{prefix}_hooks.php folder and you are set to use the power of hooks throughout the whole of your site.

Background: all systems built by more than 3 people need to think about building flexible systems that 3rd parties and end users can change/update/add-to without messing with your classes/models/etc. Plugins are the answer to this - if you need more info please read the two topics above.


Download: ExtraHooks on Google Code

I would love to have feed back on why I am so stupid for making this, what I could have done, etc... :cheese:

Here is an example controller using Hooks:
Code:
class Hooks extends Controller {

    function Hooks()
    {
        parent::Controller();    
        $this->output->enable_profiler(TRUE);
        
                //Instantiate the hooks class
        $this->hooks =& load_class('Hooks');
    }
    
    function index()
    {
        print $this->hooks->call('custom_hook', 'call');

        var_dump($this->hooks->remove('custom_hook', 'custom_hook2'));

        print $this->hooks->filter('custom_hook', 'filter');

        $this->hooks->_call_hook('custom_hook_class');
    }
}



Plugin Handling Class - Extends the CI_Hooks Class - El Forum - 08-05-2008

[eluser]Colin Williams[/eluser]
So, how does a plugin implement a hook. I don't think I've seen the whole process here. I see your controller invoking hooks, but what's the convention for implementing them?

I think a good usage example is needed here. Like, show something performing its core functionality, then show how a hook extends that functionality.


Plugin Handling Class - Extends the CI_Hooks Class - El Forum - 08-05-2008

[eluser]Xeoncross[/eluser]
[quote author="Colin Williams" date="1218002434"]So, how does a plugin implement a hook. I don't think I've seen the whole process here. I see your controller invoking hooks, but what's the convention for implementing them?

I think a good usage example is needed here. Like, show something performing its core functionality, then show how a hook extends that functionality.[/quote]

Look at the SVN on the google code :lol:

Your config/hooks.php registers all the hooks just like they do now.

Code:
$hook['custom_hook_class'][] = array(
    'function' => 'print_hello',
    'filename' => 'custom_hook_class.php',
    'filepath' => 'hooks',
    'class'    => 'custom_hook_class'
);

Your Controller (above) Calls them.

Then each hook is placed inside the app/hooks/ directory:
Code:
<?php
class custom_hook_class {
    function custom_hook_class() {
        print '<h1>This is '.  __CLASS__. ':'. __FUNCTION__. '</h1>';
    }
    
    function print_hello() {
        print '<h1>This is '.  __CLASS__. ':'. __FUNCTION__. '</h1>';
    }
}
?&gt;

A hook can be a simple file containing functions (like CI plugins) or a class. Plus, everything is auto-loaded and saved so you don't need to worry about the extrahooks class creating multible objects just to run different functions or including files twice.

This system works EXACTLY like the default hooks setup. Only now:
1) Hooks can be passed data
2) Hooks can return data
3) Hooks can filter data (several hooks running after each other)
3) Hooks can be called/created everywhere in your system (Not just the 8 default places)


Plugin Handling Class - Extends the CI_Hooks Class - El Forum - 08-05-2008

[eluser]Colin Williams[/eluser]
Very well. I see. What I have in mind takes a different approach with less configuration needed, but what you've done certainly achieves some of the same ends. Defining the exact file, class, and function for each implementation of a hook is massive overkill IMO. But that is how CI core hooks work already. My approach is just different


Plugin Handling Class - Extends the CI_Hooks Class - El Forum - 08-05-2008

[eluser]Xeoncross[/eluser]
[quote author="Colin Williams" date="1218003865"]Defining the exact file, class, and function for each implementation of a hook is massive overkill IMO. But that is how CI core hooks work already. My approach is just different[/quote]

Yes, with 50 hook calls things can add up fast! But most systems just embed those calls into the plugins themselves so I don't see any loss in keeping them all together in one file.

However, I wish you would share you logic because I might be missing something...


Plugin Handling Class - Extends the CI_Hooks Class - El Forum - 08-05-2008

[eluser]Colin Williams[/eluser]
Quote:However, I wish you would share you logic because I might be missing something

When I feel it's robust enough, I'll certainly be sharing it. It's effective now but there are some loose ends, some unnecessary steps, etc.


Plugin Handling Class - Extends the CI_Hooks Class - El Forum - 12-30-2008

[eluser]simshaun[/eluser]
Excuse my blatant idiocy, but let me see if I understand this correctly.

My goal is this:

I have a page controller, which loads a block of text from the database and passes it as a variable into the view.

With your hooks code, In my controller I can do
Code:
$data = $this->somemodel->getSampleContent();

$this->hooks->filter('data_filter', $data);

And then someone can make a plugin that contains
Code:
function custom_data_filter($data)
{
    $data = htmlentities($data);
    $data = stripslashes($data);
}

....

As I was making that.. I kinda got lost where I put '....'.
Care to help?

Ideally, this is what I want to do:
In my controller:
Code:
class Hooks extends Controller {

    function Hooks()
    {
        parent::Controller();    

        //Instantiate the hooks class
        $this->hooks =& load_class('Hooks');
    }

    function index()
    {
        $data['body_content'] = 'This sentence & that sentence.';
        
        $this->hooks->apply_filters('body_content_filters', &$data['body_content']); // can you pass by reference like that?

        $this->load->view('page_view', $data);
    }

}

And in a plugin:
Code:
function my_content_filter($input)
{
    $output    = htmlentities($input);
    return $output;
}

$CI =& get_instance();                ## Need to eliminate this line, but I don't know where else to put it so developers don't need to have it.
$CI->hooks =& load_class('Hooks');    ## Need to eliminate this line, but I don't know where else to put it so developers don't need to have it.

$CI->hooks->register_filter('my_content_filter', 'body_content_filters');

Hope you understand that.
Now, is it doable? lol


Plugin Handling Class - Extends the CI_Hooks Class - El Forum - 12-30-2008

[eluser]Xeoncross[/eluser]
That is mostly right. It is the SAME EXACT way the current hooks works - only it allows more hook points (other than the standard 8 and also adds a "filter" function for hooks that should return data (and not just run).


Here is the code:

Hooks.php
Code:
$hook['filter_comment'][] = array(
    'function' => 'filter',
    'filename' => 'filter.php',
    'filepath' => 'hooks',
);

controller:
Code:
//Create data (array, string, object, whatever)
$data = $this->somemodel->getSampleContent();

//Run the hook on the data
$data = $this->hooks->filter('filter_comment', $data);

filter.php
Code:
function filter($data)
{
    $data = htmlentities($data);
    $data = stripslashes($data);
    return $data;
}

And you now have a filter that process comments! You can also pass by reference (if you don't want return statements in your code) and you can register multiple functions/objects to run on data. I.E.

Code:
//Check akismet for spam
$hook['filter_comment'][] = array(
    'function' => 'check_for_spam',
    'filename' => 'akismet.php',
    'filepath' => 'plugins',
);

//Remove Bad stuff
$hook['filter_comment'][] = array(
    'function' => 'remove',
    'filename' => 'filter.php',
    'filepath' => 'hooks',
);

//Filter text
$hook['filter_comment'][] = array(
    'function' => 'filter',
    'filename' => 'filter.php',
    'filepath' => 'hooks',
);

There is no need to load the hooks class in your controller because CI loads it already!

The perfect example of this whole hooks/plugins thing is parsing a comment/text body. Some people want markup others use Cleaned HTML - still others only use BBCODE! With a simple plugin/hook call like above you can swap out the text filter to any type you want!


Plugin Handling Class - Extends the CI_Hooks Class - El Forum - 12-30-2008

[eluser]simshaun[/eluser]
Ah thankyou for clearing that up.

I like what you've done, and might end up using it.
I've developed a plan for something like this, except the plugins are more "plug-and-play".. the hooks file doesn't have to be modified.

http://ellislab.com/forums/viewthread/100944/

Check it out and tell me what you think.


Plugin Handling Class - Extends the CI_Hooks Class - El Forum - 12-30-2008

[eluser]Xeoncross[/eluser]
Actually, it doesn't get anymore plug-in-play than the way CI does it. I used to do it like what you did, but having to change lines by hunting down files and removing/adding filters is really bad practice. Config settings should go in config files (like hooks) that way you can manage all hooks from one place. Also, running code from a plugin/hook/file (like grabbing the CI instance to set a plugins) is really bad form and is MUCH slower than just using hooks.php because you have to load ALL files just to see if they register some hook!