-
jLinux
The Linux Dude
-
Posts: 157
Threads: 35
Joined: Jun 2015
Reputation:
2
09-25-2015, 02:25 PM
(This post was last modified: 09-26-2015, 11:08 AM by jLinux.)
I needed a decent plugin system, I tried this one, and while im sure it was awesome when it first came out, I had some issues with it (Deprecated functions used, Plugins couldn't be OOP, didn't use a model, etc)
So I created my own, and thought id share it: https://github.com/jhyland87/CI3_Plugin_System
Ill add a better README later, and some demos and instructions, so just bookmark it for meow.
Heres an example plugin..
PHP Code: /** * Plugin Name: Hello World * Plugin URI: https://github.com/jhyland87/CI3_Plugin_System * Version: 1.0 * Description: Apply colors to asset table cells or rows depending on values * Author: Justin Hyland * Author URI: http://justinhyland.com */ class Hello_world extends CI3_plugin_system { use plugin_trait;
public function __construct() { parent::__construct();
add_filter('plugin_test.name', [$this,'alter_name'], 10);
add_action('plugin_test.log', [$this, 'log_stuff']);
}
// Controller for plugin, used to manage the plugin, not required though. public function controller($data = NULL) { $content = '';
// See if form was submitted if($foo = $this->post('foo')) { // Do something with POST data $content .= "You said <strong>{$foo}</strong>..<hr>"; }
$content .= '<form action="" method="POST">' . '<input type="text" name="foo" value="' . @$foo . '"><br>' . '<input type="submit">' . '</form>';
return $content; }
// Just an example filter to alter the values of an array public function alter_name($data) { array_walk($data, function(&$item, $key){ if(strtolower($item) === 'jane') $item = 'john';
$item = ucfirst($item); });
return $data; }
// Example plugin action, just logs.. stuff public function log_stuff($prefix, $data) {
log_message('info', "[{$prefix}] " . __METHOD__ . ": Logging stuff - " . ((is_array($data) || is_object($data)) ? serialize($data) : $data)); } }
Then to use it, just put a bunch of do_action() functions all over..
PHP Code: // Fire off an action do_action('namespace.action1');
// Fire off an action with parameters do_action('namespace.action2', array('hello','world'));
// Filter some data $name = do_action('namespace.action3', array('John','Doe'));
And before you go through the code and tear it apart, I'm just gonna say, I'm a Linux Engineer, not a PHP developer, I just do PHP on my free time, and I'm in the middle of a PHP project that I needed this for.
Thanks!
P.S. Here are some of the main functions and the comments for them, just because
PHP Code: /** * Update All Plugin Headers * * Execute self::update_plugin_headers for each plugin found in static::$plugins * * @access public * @since 0.1.0 * @return boolean */ update_all_plugin_headers();
/** * Update Plugin Headers * * Parse a given plugins PHP file for the header information in the comments, and update the database info * accordingly * * @param string $plugin Plugin System Name to check * @access public * @todo Try to retrieve only the top X lines of the file, not the whole file * @since 0.1.0 * @return TRUE Always true */ update_plugin_headers($plugin);
/** * Install Plugin * * Install a plugin by adding it to the database and executing any installation code thats in * the plugins install method * * @param string $plugin Plugins system name (Folder name) * @access public * @param boolean */ install_plugin($system_name);
/** * Enable Plugin * * Enable a plugin by setting the plugins.status to 1 in the plugins table * * @oaram string $plugin Plugin Name * @param mixed $data Any data that should be handed down to the * plugins deactivate method (optional) * @access public * @since 0.1.0 * @return bool */ enable_plugin($system_name, $data);
/** * Disable Plugin * * Disable a plugin by setting the plugins.status to 0 in the plugins table * * @oaram string $plugin Plugin Name * @param mixed $data Any data that should be handed down to the * plugins activate method (optional) * @access public * @since 0.1.0 * @return bool */ disable_plugin($system_name, $data);
/** * Plugin Details * * Retrieve the details of a plugin from the database * * @param string $plugin Plugin system name * @access public * @since 0.1.0 * @return object|bool */ plugin_details($system_name);
/** * Get Messages * * Get all messages, or a specific type of message * * @param string $type Type of error to retrieve (error, debug, warn) * @access public * @since 0.1.0 * @return array|bool */ get_messages();
/** * Print Messages * * Print all messages, or messages of a certain type * * @param string $type Type of error to display (error, debug, warn) * @access public * @since 0.1.0 * @return array|bool */ print_messages();
/** * Get Orphaned Plugins * * Look in the plugin directory for any folders that do not have an associated entry * in the plugins table * * @access public * @since 0.1.0 * @return array|bool If no orphaned plugins are found, return false */ get_orphaned_plugins();
/** * Add Action * * Assign a function to be executed by a certain tag. An action will just fire off a function * when the tag is called, a filter will parse data and return the modified data * * @param string $tag Tag to add filter to * @param string|array $function Either a string (function), or an array (Object, method) * @param integer $priority Priority * @param string $type Either action or filter * @access public * @since 0.1.0 * @return boolean */ add_action('namespace.action', [$this, 'method'], 10); add_action('namespace.action', 'print_r');
/** * Add Filter * * Just a wrapper for add_function except adds it as type 'filter'. Filters will * take in data and perform an action on it, then return it, actions will just * fire off a function * * @param string $tag Tag to add filter to * @param string|array $function Either a string (function), or an array (Object, method) * @param integer $priority Priority * @access public * @since 0.1.0 * @return boolean */ add_filter('namespace.tag', [$this, 'method', 2]);
/** * Get Actions * * Gets actions.... * * @access public * @since 0.1.0 * @return array */ get_actions();
/** * Print Plugins * * Retrieve all plugin information from the database * * @access public * @since 0.1.0 * @return array */ retrieve_plugins();
/** * Do Action * * Execute a specific action, pass optional arguments to it * @param string $tag Tag to execute * @param null $args Arguments to hand to functions assigned to tag * @access public * @since 0.1.0 * @return mixed Returns whatever the type of $args is */ do_action('namespace.tag', ['one','two']);
/** * Remove Action * * Remove a function from an action * * @param string $tag Tag to check in * @param mixed $function Function to be removed * @param integer $priority Priority to check for function * @access public * @since 0.1.0 * @return boolean */ remove_action('namespace.tag', $func);
/** * Current Action * * Set the currently running action * * @access public * @since 0.1.0 * @return string */ current_action();
/** * Has Run * * See if a particular action has ran yet * * @param string $action Action to check for * @access public * @since 0.1.0 * @return boolean */ has_run('namespace.tag');
/** * Doing Action * * If the param is NULL, then this will return what action is being executed, * if an action is supplied, then it will return boolean based on if that action * is being executed or not * * @param null $action Action to check for */ doing_action('namespace.tag');
/** * Did Action * * Returns if a tag has been fired or not * * @param string $tag Tag to check if ran or not */ did_action('namespace.tag');
-
jLinux
The Linux Dude
-
Posts: 157
Threads: 35
Joined: Jun 2015
Reputation:
2
09-26-2015, 11:09 AM
(This post was last modified: 09-26-2015, 11:10 AM by jLinux.)
Oh, and if anyone wants an AWESOME plugin for JS written by WordPress, let me know. I had to do a lot of digging to find it, its open source, but impossible to find... I found it tucked away in a response to a ticket that was like 30 pages deep in a google search, lol.
Its not released by WP yet, but it works AWESOME. Supports actions, filters, priorities, etc
-
mwhitney
Posting Freak
-
Posts: 1,101
Threads: 4
Joined: Nov 2014
Reputation:
95
Please don't take this the wrong way. I understand you're primarily a Linux engineer, I just want to point out a few things which might make it easier for you to maintain the code in the long run.
- If you name your config file the same as your library (though in all lowercase), CI's loader will load the config file and pass it to your library's constructor. If you modified the constructor to get the argument:
PHP Code: public function __construct(array $config = array()) { // You'll want to change this to whatever makes the most sense for you. $this->pluginDir = isset($config['plugin_dir']) ? $config['plugin_dir'] : '';
// ... }
Then you wouldn't need to call the config class through the CI instance in set_plugin_dir().
- Your call in set_plugin_dir() requests a different config item ('plugin_path') from the one set in your plugins config ('plugin_dir').
- Your has_run() method doesn't need the if/else:
PHP Code: public function has_run($action) { return isset(static::$run_actions[$action]); }
- in print_messages() you have the following:
PHP Code: if (@empty(static::$messages[strtolower($type)]) || ! isset(static::$messages[ strtolower($type) ]))
I can't think of a condition in which !isset($something) would be true if empty($something) was false. Generally, if both are used in the same statement, isset() is called first because it is faster and can prevent errors in empty(). Since you're suppressing errors on empty() and calling empty() first, I'm not sure what the isset() call is doing for you.
- It also seems like print_messages() should use get_messages(), so you don't have multiple pieces of code doing the same thing (and one of the reasons for that is evident here, as the code to get the messages isn't the same even though it should be doing the same thing).
- The same basic idea could be applied to installing/loading the plugin(s), as you have at least three methods which build a path to a plugin and load the file (two of which have slightly different error messages, but the same basic error handling, the third, which gets the file's contents rather than including it, has no error handling at all when attempting to read the file).
I was also going to go into the use of static for all of the properties, but I really just hope you had some specific need for that outside of CI, because I don't really see the point (when CI loads the class as a singleton) unless you just really like the syntax.
-
jLinux
The Linux Dude
-
Posts: 157
Threads: 35
Joined: Jun 2015
Reputation:
2
09-28-2015, 09:09 PM
(This post was last modified: 09-28-2015, 09:24 PM by jLinux.)
@ solidcodes
Thanks for the pointers! Theres no reason for anyone to take input the "wrong way", unless its clear the intention was more to be an ass than to actually help. But you're right, my primary role is a Linux Engineer, I usually just use PHP for quick solutions to things, (automation typically, or Web tools, then Perl/Bash for CLI tools). However, I'm in the middle of a project for a web app that I've wanted to do for a while now, so I'm learning a lot more PHP than I knew before.
Most (not all) of the pointers you gave I kinda already knew, they were just left like that as a result of sloppy coding, except for #1, thats going to be a big help! Ill be sure to incorporate all the above into it and update it, and the plugin_dir/path is an obvious mistake I looked over.
As for why they are static, it was first because I created this outside of CI, then when I adapted it for CI, I just left it, because I think static properties are easier to use, and it doesnt really make much of a difference.
Thanks for the input! Ive been using it on my CI app and it seems to be working great. granted I havent created too many intense plugins. (And I'm surprised that plugin_dir/path hasn't caused a fatal error, obviously theres a logic error somewhere as well)
P.S. You totally busted me for some of the little discrepancies that I hound my co-workers about, if they saw this thread, id never hear the end of it, lol
-
sampoyigi
Web Developer
-
Posts: 22
Threads: 1
Joined: Nov 2014
Reputation:
3
Thanks for sharing. I'm definitely going to try it and maybe incorporate it into my project (if i may).
TastyIgniter - Open Source Restaurant Ordering and Management System
-
jLinux
The Linux Dude
-
Posts: 157
Threads: 35
Joined: Jun 2015
Reputation:
2
(10-04-2015, 05:44 AM)sampoyigi Wrote: Thanks for sharing. I'm definitely going to try it and maybe incorporate it into my project (if i may).
Absolutely. If you have anything to contribute, go ahead. And also id keep an eye on the repo, ill be doing a lot of updates.
Currently, Plugins have the ability to include a "config" page, as well as "Install" and "Uninstall" methods/resources. I got the config page idea from WordPress, where each plugin has its own configuration page.
Also, if you dont want to contribute, but have some ideas or input, let me know! Ill be using this heavily in a project im working on, so ill be making some changes.
I may end up using the core code of this for a Laravel project as well, (Unless Laravel has something for this already)
|