├── LICENSE ├── README.md ├── application ├── .htaccess ├── config │ ├── autoload.php │ ├── config.php │ └── plugins.php ├── controllers │ └── Plugins.php ├── helpers │ └── plugin_helper.php ├── libraries │ ├── Plugins_lib.php │ ├── abstract.plugins.php │ └── trait.plugins.php ├── models │ ├── Plugins_model.php │ └── index.html └── views │ ├── plugin_list.php │ └── plugin_settings.php ├── plugin_database.sql └── plugins └── hello_world ├── hello_world.php └── views └── settings.php /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 J 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | > :warning: **Deprecation warning**: I wrote this a very long time ago and no longer use CI - Or any PHP framework for that matter. I stay away from PHP like the plague. But since people seem to continue to star/watch it, I'll leave it up here. 2 | > 3 | > Someone please steal this and make it better. 4 | 5 | 6 | # CI3_Plugin_System 7 | Plugin system for CodeIgniter 3 8 | 9 | Ill add more info to the readme later, but for now, just drop the helper/model/library where they go, import the table in the .sql file, and look at the application/controllers/Plugins.php for some info, and look at the plugins/hello_world/hello_world.php for a very basic demo. 10 | -------------------------------------------------------------------------------- /application/.htaccess: -------------------------------------------------------------------------------- 1 | 2 | Require all denied 3 | 4 | 5 | Deny from all 6 | -------------------------------------------------------------------------------- /application/config/autoload.php: -------------------------------------------------------------------------------- 1 | 'ua'); 61 | */ 62 | 63 | $autoload['libraries'] = array('database','Plugins_lib'); 64 | 65 | 66 | /* 67 | | ------------------------------------------------------------------- 68 | | Auto-load Drivers 69 | | ------------------------------------------------------------------- 70 | | These classes are located in the system/libraries folder or in your 71 | | application/libraries folder within their own subdirectory. They 72 | | offer multiple interchangeable driver options. 73 | | 74 | | Prototype: 75 | | 76 | | $autoload['drivers'] = array('cache'); 77 | */ 78 | 79 | $autoload['drivers'] = array(); 80 | 81 | 82 | /* 83 | | ------------------------------------------------------------------- 84 | | Auto-load Helper Files 85 | | ------------------------------------------------------------------- 86 | | Prototype: 87 | | 88 | | $autoload['helper'] = array('url', 'file'); 89 | */ 90 | 91 | $autoload['helper'] = array('plugin'); 92 | 93 | 94 | /* 95 | | ------------------------------------------------------------------- 96 | | Auto-load Config files 97 | | ------------------------------------------------------------------- 98 | | Prototype: 99 | | 100 | | $autoload['config'] = array('config1', 'config2'); 101 | | 102 | | NOTE: This item is intended for use ONLY if you have created custom 103 | | config files. Otherwise, leave it blank. 104 | | 105 | */ 106 | 107 | $autoload['config'] = array('plugins'); 108 | 109 | 110 | /* 111 | | ------------------------------------------------------------------- 112 | | Auto-load Language files 113 | | ------------------------------------------------------------------- 114 | | Prototype: 115 | | 116 | | $autoload['language'] = array('lang1', 'lang2'); 117 | | 118 | | NOTE: Do not include the "_lang" part of your file. For example 119 | | "codeigniter_lang.php" would be referenced as array('codeigniter'); 120 | | 121 | */ 122 | 123 | $autoload['language'] = array(); 124 | 125 | 126 | /* 127 | | ------------------------------------------------------------------- 128 | | Auto-load Models 129 | | ------------------------------------------------------------------- 130 | | Prototype: 131 | | 132 | | $autoload['model'] = array('first_model', 'second_model'); 133 | | 134 | | You can also supply an alternative model name to be assigned 135 | | in the controller: 136 | | 137 | | $autoload['model'] = array('first_model' => 'first'); 138 | */ 139 | 140 | $autoload['model'] = array('Plugins_model'); 141 | -------------------------------------------------------------------------------- /application/config/config.php: -------------------------------------------------------------------------------- 1 | ]+$/i 152 | | 153 | | DO NOT CHANGE THIS UNLESS YOU FULLY UNDERSTAND THE REPERCUSSIONS!! 154 | | 155 | */ 156 | $config['permitted_uri_chars'] = 'a-z 0-9~%.:_\-'; 157 | 158 | 159 | /* 160 | |-------------------------------------------------------------------------- 161 | | Enable Query Strings 162 | |-------------------------------------------------------------------------- 163 | | 164 | | By default CodeIgniter uses search-engine friendly segment based URLs: 165 | | example.com/who/what/where/ 166 | | 167 | | By default CodeIgniter enables access to the $_GET array. If for some 168 | | reason you would like to disable it, set 'allow_get_array' to FALSE. 169 | | 170 | | You can optionally enable standard query string based URLs: 171 | | example.com?who=me&what=something&where=here 172 | | 173 | | Options are: TRUE or FALSE (boolean) 174 | | 175 | | The other items let you set the query string 'words' that will 176 | | invoke your controllers and its functions: 177 | | example.com/index.php?c=controller&m=function 178 | | 179 | | Please note that some of the helpers won't work as expected when 180 | | this feature is enabled, since CodeIgniter is designed primarily to 181 | | use segment based URLs. 182 | | 183 | */ 184 | $config['allow_get_array'] = TRUE; 185 | $config['enable_query_strings'] = FALSE; 186 | $config['controller_trigger'] = 'c'; 187 | $config['function_trigger'] = 'm'; 188 | $config['directory_trigger'] = 'd'; 189 | 190 | /* 191 | |-------------------------------------------------------------------------- 192 | | Error Logging Threshold 193 | |-------------------------------------------------------------------------- 194 | | 195 | | If you have enabled error logging, you can set an error threshold to 196 | | determine what gets logged. Threshold options are: 197 | | You can enable error logging by setting a threshold over zero. The 198 | | threshold determines what gets logged. Threshold options are: 199 | | 200 | | 0 = Disables logging, Error logging TURNED OFF 201 | | 1 = Error Messages (including PHP errors) 202 | | 2 = Debug Messages 203 | | 3 = Informational Messages 204 | | 4 = All Messages 205 | | 206 | | You can also pass an array with threshold levels to show individual error types 207 | | 208 | | array(2) = Debug Messages, without Error Messages 209 | | 210 | | For a live site you'll usually only enable Errors (1) to be logged otherwise 211 | | your log files will fill up very fast. 212 | | 213 | */ 214 | $config['log_threshold'] = 0; 215 | 216 | /* 217 | |-------------------------------------------------------------------------- 218 | | Error Logging Directory Path 219 | |-------------------------------------------------------------------------- 220 | | 221 | | Leave this BLANK unless you would like to set something other than the default 222 | | application/logs/ directory. Use a full server path with trailing slash. 223 | | 224 | */ 225 | $config['log_path'] = ''; 226 | 227 | /* 228 | |-------------------------------------------------------------------------- 229 | | Log File Extension 230 | |-------------------------------------------------------------------------- 231 | | 232 | | The default filename extension for log files. The default 'php' allows for 233 | | protecting the log files via basic scripting, when they are to be stored 234 | | under a publicly accessible directory. 235 | | 236 | | Note: Leaving it blank will default to 'php'. 237 | | 238 | */ 239 | $config['log_file_extension'] = ''; 240 | 241 | /* 242 | |-------------------------------------------------------------------------- 243 | | Log File Permissions 244 | |-------------------------------------------------------------------------- 245 | | 246 | | The file system permissions to be applied on newly created log files. 247 | | 248 | | IMPORTANT: This MUST be an integer (no quotes) and you MUST use octal 249 | | integer notation (i.e. 0700, 0644, etc.) 250 | */ 251 | $config['log_file_permissions'] = 0644; 252 | 253 | /* 254 | |-------------------------------------------------------------------------- 255 | | Date Format for Logs 256 | |-------------------------------------------------------------------------- 257 | | 258 | | Each item that is logged has an associated date. You can use PHP date 259 | | codes to set your own date formatting 260 | | 261 | */ 262 | $config['log_date_format'] = 'Y-m-d H:i:s'; 263 | 264 | /* 265 | |-------------------------------------------------------------------------- 266 | | Error Views Directory Path 267 | |-------------------------------------------------------------------------- 268 | | 269 | | Leave this BLANK unless you would like to set something other than the default 270 | | application/views/errors/ directory. Use a full server path with trailing slash. 271 | | 272 | */ 273 | $config['error_views_path'] = ''; 274 | 275 | /* 276 | |-------------------------------------------------------------------------- 277 | | Cache Directory Path 278 | |-------------------------------------------------------------------------- 279 | | 280 | | Leave this BLANK unless you would like to set something other than the default 281 | | application/cache/ directory. Use a full server path with trailing slash. 282 | | 283 | */ 284 | $config['cache_path'] = ''; 285 | 286 | /* 287 | |-------------------------------------------------------------------------- 288 | | Cache Include Query String 289 | |-------------------------------------------------------------------------- 290 | | 291 | | Set this to TRUE if you want to use different cache files depending on the 292 | | URL query string. Please be aware this might result in numerous cache files. 293 | | 294 | */ 295 | $config['cache_query_string'] = FALSE; 296 | 297 | /* 298 | |-------------------------------------------------------------------------- 299 | | Encryption Key 300 | |-------------------------------------------------------------------------- 301 | | 302 | | If you use the Encryption class, you must set an encryption key. 303 | | See the user guide for more info. 304 | | 305 | | http://codeigniter.com/user_guide/libraries/encryption.html 306 | | 307 | */ 308 | $config['encryption_key'] = ''; 309 | 310 | /* 311 | |-------------------------------------------------------------------------- 312 | | Session Variables 313 | |-------------------------------------------------------------------------- 314 | | 315 | | 'sess_driver' 316 | | 317 | | The storage driver to use: files, database, redis, memcached 318 | | 319 | | 'sess_cookie_name' 320 | | 321 | | The session cookie name, must contain only [0-9a-z_-] characters 322 | | 323 | | 'sess_expiration' 324 | | 325 | | The number of SECONDS you want the session to last. 326 | | Setting to 0 (zero) means expire when the browser is closed. 327 | | 328 | | 'sess_save_path' 329 | | 330 | | The location to save sessions to, driver dependant. 331 | | 332 | | For the 'files' driver, it's a path to a writable directory. 333 | | WARNING: Only absolute paths are supported! 334 | | 335 | | For the 'database' driver, it's a table name. 336 | | Please read up the manual for the format with other session drivers. 337 | | 338 | | IMPORTANT: You are REQUIRED to set a valid save path! 339 | | 340 | | 'sess_match_ip' 341 | | 342 | | Whether to match the user's IP address when reading the session data. 343 | | 344 | | 'sess_time_to_update' 345 | | 346 | | How many seconds between CI regenerating the session ID. 347 | | 348 | | 'sess_regenerate_destroy' 349 | | 350 | | Whether to destroy session data associated with the old session ID 351 | | when auto-regenerating the session ID. When set to FALSE, the data 352 | | will be later deleted by the garbage collector. 353 | | 354 | | Other session cookie settings are shared with the rest of the application, 355 | | except for 'cookie_prefix' and 'cookie_httponly', which are ignored here. 356 | | 357 | */ 358 | $config['sess_driver'] = 'files'; 359 | $config['sess_cookie_name'] = 'ci_session'; 360 | $config['sess_expiration'] = 7200; 361 | $config['sess_save_path'] = NULL; 362 | $config['sess_match_ip'] = FALSE; 363 | $config['sess_time_to_update'] = 300; 364 | $config['sess_regenerate_destroy'] = FALSE; 365 | 366 | /* 367 | |-------------------------------------------------------------------------- 368 | | Cookie Related Variables 369 | |-------------------------------------------------------------------------- 370 | | 371 | | 'cookie_prefix' = Set a cookie name prefix if you need to avoid collisions 372 | | 'cookie_domain' = Set to .your-domain.com for site-wide cookies 373 | | 'cookie_path' = Typically will be a forward slash 374 | | 'cookie_secure' = Cookie will only be set if a secure HTTPS connection exists. 375 | | 'cookie_httponly' = Cookie will only be accessible via HTTP(S) (no javascript) 376 | | 377 | | Note: These settings (with the exception of 'cookie_prefix' and 378 | | 'cookie_httponly') will also affect sessions. 379 | | 380 | */ 381 | $config['cookie_prefix'] = ''; 382 | $config['cookie_domain'] = ''; 383 | $config['cookie_path'] = '/'; 384 | $config['cookie_secure'] = FALSE; 385 | $config['cookie_httponly'] = FALSE; 386 | 387 | /* 388 | |-------------------------------------------------------------------------- 389 | | Standardize newlines 390 | |-------------------------------------------------------------------------- 391 | | 392 | | Determines whether to standardize newline characters in input data, 393 | | meaning to replace \r\n, \r, \n occurences with the PHP_EOL value. 394 | | 395 | | This is particularly useful for portability between UNIX-based OSes, 396 | | (usually \n) and Windows (\r\n). 397 | | 398 | */ 399 | $config['standardize_newlines'] = FALSE; 400 | 401 | /* 402 | |-------------------------------------------------------------------------- 403 | | Global XSS Filtering 404 | |-------------------------------------------------------------------------- 405 | | 406 | | Determines whether the XSS filter is always active when GET, POST or 407 | | COOKIE data is encountered 408 | | 409 | | WARNING: This feature is DEPRECATED and currently available only 410 | | for backwards compatibility purposes! 411 | | 412 | */ 413 | $config['global_xss_filtering'] = FALSE; 414 | 415 | /* 416 | |-------------------------------------------------------------------------- 417 | | Cross Site Request Forgery 418 | |-------------------------------------------------------------------------- 419 | | Enables a CSRF cookie token to be set. When set to TRUE, token will be 420 | | checked on a submitted form. If you are accepting user data, it is strongly 421 | | recommended CSRF protection be enabled. 422 | | 423 | | 'csrf_token_name' = The token name 424 | | 'csrf_cookie_name' = The cookie name 425 | | 'csrf_expire' = The number in seconds the token should expire. 426 | | 'csrf_regenerate' = Regenerate token on every submission 427 | | 'csrf_exclude_uris' = Array of URIs which ignore CSRF checks 428 | */ 429 | $config['csrf_protection'] = FALSE; 430 | $config['csrf_token_name'] = 'csrf_test_name'; 431 | $config['csrf_cookie_name'] = 'csrf_cookie_name'; 432 | $config['csrf_expire'] = 7200; 433 | $config['csrf_regenerate'] = TRUE; 434 | $config['csrf_exclude_uris'] = array(); 435 | 436 | /* 437 | |-------------------------------------------------------------------------- 438 | | Output Compression 439 | |-------------------------------------------------------------------------- 440 | | 441 | | Enables Gzip output compression for faster page loads. When enabled, 442 | | the output class will test whether your server supports Gzip. 443 | | Even if it does, however, not all browsers support compression 444 | | so enable only if you are reasonably sure your visitors can handle it. 445 | | 446 | | Only used if zlib.output_compression is turned off in your php.ini. 447 | | Please do not use it together with httpd-level output compression. 448 | | 449 | | VERY IMPORTANT: If you are getting a blank page when compression is enabled it 450 | | means you are prematurely outputting something to your browser. It could 451 | | even be a line of whitespace at the end of one of your scripts. For 452 | | compression to work, nothing can be sent before the output buffer is called 453 | | by the output class. Do not 'echo' any values with compression enabled. 454 | | 455 | */ 456 | $config['compress_output'] = FALSE; 457 | 458 | /* 459 | |-------------------------------------------------------------------------- 460 | | Master Time Reference 461 | |-------------------------------------------------------------------------- 462 | | 463 | | Options are 'local' or any PHP supported timezone. This preference tells 464 | | the system whether to use your server's local time as the master 'now' 465 | | reference, or convert it to the configured one timezone. See the 'date 466 | | helper' page of the user guide for information regarding date handling. 467 | | 468 | */ 469 | $config['time_reference'] = 'local'; 470 | 471 | /* 472 | |-------------------------------------------------------------------------- 473 | | Rewrite PHP Short Tags 474 | |-------------------------------------------------------------------------- 475 | | 476 | | If your PHP installation does not have short tag support enabled CI 477 | | can rewrite the tags on-the-fly, enabling you to utilize that syntax 478 | | in your view files. Options are TRUE or FALSE (boolean) 479 | | 480 | */ 481 | $config['rewrite_short_tags'] = FALSE; 482 | 483 | 484 | /* 485 | |-------------------------------------------------------------------------- 486 | | Reverse Proxy IPs 487 | |-------------------------------------------------------------------------- 488 | | 489 | | If your server is behind a reverse proxy, you must whitelist the proxy 490 | | IP addresses from which CodeIgniter should trust headers such as 491 | | HTTP_X_FORWARDED_FOR and HTTP_CLIENT_IP in order to properly identify 492 | | the visitor's IP address. 493 | | 494 | | You can use both an array or a comma-separated list of proxy addresses, 495 | | as well as specifying whole subnets. Here are a few examples: 496 | | 497 | | Comma-separated: '10.0.1.200,192.168.5.0/24' 498 | | Array: array('10.0.1.200', '192.168.5.0/24') 499 | */ 500 | $config['proxy_ips'] = ''; 501 | -------------------------------------------------------------------------------- /application/config/plugins.php: -------------------------------------------------------------------------------- 1 | /plugins/) 11 | */ 12 | $config['plugin_dir'] = FCPATH . 'plugins/'; 13 | 14 | require_once( APPPATH . 'libraries/abstract.plugins.php' ); 15 | require_once( APPPATH . 'libraries/trait.plugins.php' ); -------------------------------------------------------------------------------- /application/controllers/Plugins.php: -------------------------------------------------------------------------------- 1 | _plugins = $this->Plugins_model->get_plugins(); 13 | 14 | $this->plugins_lib->update_all_plugin_headers(); 15 | } 16 | 17 | public function index() 18 | { 19 | 20 | $data = array(); 21 | 22 | $data['plugins'] = $this->Plugins_model->get_plugins(); 23 | 24 | $this->load->view('plugin_list', $data); 25 | } 26 | 27 | public function config() 28 | { 29 | $data = array(); 30 | 31 | if( ! $plugin = $this->input->get('plugin')) 32 | { 33 | redirect('/'); 34 | } 35 | elseif( ! isset($this->_plugins[$plugin])) 36 | { 37 | die("Unknown plugin {$plugin}"); 38 | } 39 | elseif($this->_plugins[$plugin]->status != 1) 40 | { 41 | die("The plugin {$plugin} isn't enabled"); 42 | } 43 | else 44 | { 45 | $data['plugin'] = $plugin; 46 | 47 | // Just some random stuff to send to the data, not needed unless the plugin 48 | // controller requires it 49 | $plugin_data = array('some' => 'data'); 50 | 51 | if( ! $data['plugin_content'] = $this->plugins_lib->view_controller($plugin, $plugin_data)) 52 | { 53 | die('No controller for this plugin'); 54 | } 55 | } 56 | 57 | 58 | $this->load->view('plugin_settings', $data); 59 | } 60 | 61 | } 62 | -------------------------------------------------------------------------------- /application/helpers/plugin_helper.php: -------------------------------------------------------------------------------- 1 | update_all_plugin_headers(); 16 | } 17 | } 18 | 19 | // ------------------------------------------------------------------------ 20 | 21 | if( ! function_exists('update_plugin_headers')) 22 | { 23 | /** 24 | * Shortcut to Plugins_lib::update_plugin_headers() 25 | * 26 | * Updates the plugin headers for a specified plugin based on the plugins .php file comments 27 | * 28 | * @param string $plugin Plugin system name 29 | * 30 | * @since 0.1.0 31 | * @return bool 32 | */ 33 | function update_plugin_headers( $plugin ) 34 | { 35 | return Plugins_lib::$instance->update_plugin_headers( $plugin ); 36 | } 37 | } 38 | 39 | // ------------------------------------------------------------------------ 40 | 41 | if( ! function_exists('install_plugin')) 42 | { 43 | /** 44 | * Shortcut to Plugins_lib::install_plugin() 45 | * 46 | * Executes whatevers in the plugins install method 47 | * 48 | * @param string $plugin Plugin system name 49 | * 50 | * @since 0.1.0 51 | * @return bool 52 | */ 53 | function install_plugin( $plugin, $data = NULL ) 54 | { 55 | return Plugins_lib::$instance->install_plugin( $plugin, $data ); 56 | } 57 | } 58 | 59 | // ------------------------------------------------------------------------ 60 | 61 | if( ! function_exists('enable_plugin')) 62 | { 63 | /** 64 | * Shortcut to Plugins_lib::enable_plugin() 65 | * 66 | * Enable a specified plugin by setting the database status value to 1 67 | * 68 | * @param string $plugin Plugin system name 69 | * @param mixed $data Any data that should be handed down to the plugins activation method (optional) 70 | * 71 | * @since 0.1.0 72 | * @return bool 73 | */ 74 | function enable_plugin( $plugin, $data = NULL ) 75 | { 76 | return Plugins_lib::$instance->enable_plugin( $plugin, $data ); 77 | } 78 | } 79 | 80 | // ------------------------------------------------------------------------ 81 | 82 | if( ! function_exists('disable_plugin')) 83 | { 84 | /** 85 | * Shortcut to Plugins_lib::disable_plugin() 86 | * 87 | * Disable a specified plugin by setting the database status value to 0 88 | * 89 | * @param string $plugin Plugin system name 90 | * @param mixed $data Any data that should be handed down to the plugins deactivate method (optional) 91 | * 92 | * @since 0.1.0 93 | * @return bool 94 | */ 95 | function disable_plugin( $plugin, $data = NULL ) 96 | { 97 | return Plugins_lib::$instance->disable_plugin( $plugin, $data ); 98 | } 99 | } 100 | 101 | // ------------------------------------------------------------------------ 102 | 103 | if( ! function_exists('plugin_details')) 104 | { 105 | /** 106 | * Shortcut to Plugins_lib::plugin_details() 107 | * 108 | * Return the details of a plugin from the plugins database table 109 | * 110 | * @param string $plugin Plugin system name 111 | * 112 | * @since 0.1.0 113 | * @return array 114 | */ 115 | function plugin_details( $plugin ) 116 | { 117 | return Plugins_lib::$instance->plugin_details( $plugin ); 118 | } 119 | } 120 | 121 | // ------------------------------------------------------------------------ 122 | 123 | if( ! function_exists('get_messages')) 124 | { 125 | /** 126 | * Shortcut to Plugins_lib::get_messages() 127 | * 128 | * Gets all the plugin messages thus far (errors, debug messages, warnings) 129 | * 130 | * @param string $type Specific type to retrieve, if NULL, all are returned 131 | * 132 | * @since 0.1.0 133 | * @return array 134 | */ 135 | function get_messages( $type = NULL ) 136 | { 137 | return Plugins_lib::$instance->get_messages( $type ); 138 | } 139 | } 140 | 141 | // ------------------------------------------------------------------------ 142 | 143 | if( ! function_exists('print_messages')) 144 | { 145 | /** 146 | * Shortcut to Plugins_lib::print_messages() 147 | * 148 | * Displays all the plugin messages thus far (errors, debug messages, warnings) 149 | * 150 | * @param string $type Specific type to retrieve, if NULL, all are printed 151 | * 152 | * @since 0.1.0 153 | * @return array 154 | */ 155 | function print_messages( $type = NULL ) 156 | { 157 | return Plugins_lib::$instance->print_messages( $type ); 158 | } 159 | } 160 | 161 | // ------------------------------------------------------------------------ 162 | 163 | if( ! function_exists('get_orphaned_plugins')) 164 | { 165 | /** 166 | * Shortcut to Plugins_lib::get_orphaned_plugins() 167 | * 168 | * See if there are any plugins in the plugins directory that arent in the database 169 | * 170 | * @since 0.1.0 171 | * @return array 172 | */ 173 | function get_orphaned_plugins() 174 | { 175 | return Plugins_lib::$instance->get_orphaned_plugins(); 176 | } 177 | } 178 | 179 | // ------------------------------------------------------------------------ 180 | 181 | if( ! function_exists('add_action')) 182 | { 183 | /** 184 | * Shortcut to Plugins_lib::add_action() 185 | * 186 | * Add an action - a function that will fire off when a tag/action is executed (NOT 187 | * the same as add_filter - which will return a value 188 | * 189 | * @param string $tag Tag/Action thats being executed 190 | * @param string|array $function Either a single function (string), or a class and method (array) 191 | * @param int $priority Priority of this action 192 | * 193 | * @since 0.1.0 194 | * @return boolean 195 | */ 196 | function add_action( $tag, $function, $priority = 10 ) 197 | { 198 | return Plugins_lib::$instance->add_action( $tag, $function, $priority ); 199 | } 200 | } 201 | 202 | // ------------------------------------------------------------------------ 203 | 204 | if( ! function_exists('add_filter')) 205 | { 206 | /** 207 | * Shortcut to Plugins_lib::add_filter() 208 | * 209 | * Add a filter - a function that can be used to effect/parse/filter out some content (NOT 210 | * the same as add_action - which will just fire off a function 211 | * 212 | * @param string $tag Tag/Action thats being executed 213 | * @param string|array $function Either a single function (string), or a class and method (array) 214 | * @param int $priority Priority of this action 215 | * 216 | * @since 0.1.0 217 | * @return boolean 218 | */ 219 | function add_filter( $tag, $function, $priority = 10 ) 220 | { 221 | return Plugins_lib::$instance->add_filter( $tag, $function, $priority ); 222 | } 223 | } 224 | 225 | // ------------------------------------------------------------------------ 226 | 227 | if( ! function_exists('get_actions')) 228 | { 229 | /** 230 | * Shortcut to Plugins_lib::get_actions() 231 | * 232 | * Retrieve all actions/filters that are assigned to actions/tags 233 | * 234 | * @since 0.1.0 235 | * @return array 236 | */ 237 | function get_actions() 238 | { 239 | return Plugins_lib::$instance->get_actions(); 240 | } 241 | } 242 | 243 | // ------------------------------------------------------------------------ 244 | 245 | if( ! function_exists('retrieve_plugins')) 246 | { 247 | /** 248 | * Shortcut to Plugins_lib::retrieve_plugins() 249 | * 250 | * Retrieve all plugins 251 | * 252 | * @since 0.1.0 253 | * @return array 254 | */ 255 | function retrieve_plugins() 256 | { 257 | return Plugins_lib::$instance->retrieve_plugins(); 258 | } 259 | } 260 | 261 | // ------------------------------------------------------------------------ 262 | 263 | if( ! function_exists('do_action')) 264 | { 265 | /** 266 | * Shortcut to Plugins_lib::do_action() 267 | * 268 | * Execute all plugin functions tied to a specific tag 269 | * 270 | * @param string $tag Tag to execute 271 | * @param mixed $args Arguments to hand to plugin (Can be anything) 272 | * 273 | * @since 0.1.0 274 | * @return mixed 275 | */ 276 | function do_action( $tag, array $args = NULL ) 277 | { 278 | //log_message('error',"Doing $tag " . ($args ? "With args: " . serialize($args) : "With no args")); 279 | return Plugins_lib::$instance->do_action( $tag, $args ); 280 | } 281 | } 282 | 283 | // ------------------------------------------------------------------------ 284 | 285 | if( ! function_exists('remove_action')) 286 | { 287 | /** 288 | * Shortcut to Plugins_lib::remove_action() 289 | * 290 | * Remove a specific plugin function assigned to execute on a specific tag at a specific priority 291 | * 292 | * @param string $tag Tag to clear actions from 293 | * @param string|array $function Function or object/method to remove from tag 294 | * @param int $priority Priority to clear 295 | * 296 | * @since 0.1.0 297 | * @return boolean 298 | */ 299 | function remove_action( $tag, $function, $priority = 10 ) 300 | { 301 | return Plugins_lib::$instance->remove_action( $tag, $function, $priority ); 302 | } 303 | } 304 | 305 | // ------------------------------------------------------------------------ 306 | 307 | if( ! function_exists('current_action')) 308 | { 309 | /** 310 | * Shortcut to Plugins_lib::current_action() 311 | * 312 | * Get the current plugin action being executed 313 | * 314 | * @since 0.1.0 315 | * @return string 316 | */ 317 | function current_action() 318 | { 319 | return Plugins_lib::$instance->current_action(); 320 | } 321 | } 322 | 323 | // ------------------------------------------------------------------------ 324 | 325 | if( ! function_exists('has_run')) 326 | { 327 | /** 328 | * Shortcut to Plugins_lib::has_run() 329 | * 330 | * See if an action has run or not 331 | * 332 | * @param string $action Tag/action to check 333 | * 334 | * @since 0.1.0 335 | * @return boolean 336 | */ 337 | function has_run( $action = NULL ) 338 | { 339 | return Plugins_lib::$instance->has_run( $action ); 340 | } 341 | } 342 | 343 | // ------------------------------------------------------------------------ 344 | 345 | if( ! function_exists('doing_action')) 346 | { 347 | /** 348 | * Shortcut to Plugins_lib::doing_action() 349 | * 350 | * If no action is specified, then the current action being executed will be returned, if 351 | * an action is specified, then TRUE/FALSE will be returned based on if the action is 352 | * being executed or not 353 | * 354 | * @oaran string $action Action to check 355 | * @since 0.1.0 356 | * @return boolean|string 357 | */ 358 | function doing_action( $action = NULL ) 359 | { 360 | return Plugins_lib::$instance->doing_action( $action ); 361 | } 362 | } 363 | 364 | // ------------------------------------------------------------------------ 365 | 366 | if( ! function_exists('did_action')) 367 | { 368 | /** 369 | * Shortcut to Plugins_lib::did_action() 370 | * 371 | * Check if an action/tag has been executed or not 372 | * 373 | * @param string $tag Tag/action to check 374 | * 375 | * @since 0.1.0 376 | * @return boolean 377 | */ 378 | function did_action( $tag ) 379 | { 380 | return Plugins_lib::$instance->did_action( $tag ); 381 | } 382 | } 383 | -------------------------------------------------------------------------------- /application/libraries/Plugins_lib.php: -------------------------------------------------------------------------------- 1 | load->model('Plugins_model'); 132 | 133 | // Load the plugins helper 134 | static::$CI->load->helper('plugin'); 135 | 136 | // Set a shorter handle for the plugins model 137 | static::$PM = static::$CI->Plugins_model; 138 | 139 | static::$messages = array( 140 | 'error' => [], 141 | 'debug' => [], 142 | 'warn' => [] 143 | ); 144 | 145 | // Set plugin path 146 | $this->set_plugin_dir(); 147 | 148 | // Get all activated plugins 149 | $this->get_plugins(); 150 | 151 | // Include plugins 152 | $this->include_enabled_plugins(); 153 | 154 | // Load them 155 | $this->load_enabled_plugins(); 156 | } 157 | 158 | // ------------------------------------------------------------------------ 159 | 160 | /** 161 | * Set Plugin Directory 162 | * 163 | * Set the plugins directory that contains all the plugin folders, at the local 164 | * private property: static::$plugin_path 165 | * 166 | * @param str $dir Directory, an ending slash is appended if not found, and any 167 | * accidental double slashes are replaced with single slashes 168 | * @access private 169 | */ 170 | private function set_plugin_dir() 171 | { 172 | if($path = static::$CI->config->item('plugin_path')) 173 | { 174 | $this->_debug("Plugin path set to {$path} via config setting"); 175 | } 176 | elseif(defined('PLUGIN_DIR')) 177 | { 178 | $this->_debug("Plugin path set to ".PLUGIN_DIR."via constant PLUGIN_DIR"); 179 | 180 | $path = PLUGIN_DIR; 181 | } 182 | else 183 | { 184 | $path = FCPATH . 'plugins/'; 185 | 186 | $this->_debug("Plugin path defaulted to {$path}"); 187 | 188 | $this->_warn("No plugin path specified in CI settings or PLUGIN_DIR constant, defaulting to {$path}"); 189 | } 190 | 191 | // Make sure it ends in / 192 | if( preg_match('%/$%', $path) === FALSE ) 193 | { 194 | $path = "{$path}/"; 195 | } 196 | 197 | static::$plugin_path = str_replace('//','/',$path); 198 | } 199 | 200 | // ------------------------------------------------------------------------ 201 | 202 | /** 203 | * View Controller 204 | * 205 | * View the controller from the plugin. 206 | * 207 | * @param string $plugin Systen name of plugin 208 | * @param mixed $plugin_data Any data to hand down to the plugin (Anything 209 | * processed from the controller, etc) 210 | * @access public 211 | * @since 0.1.0 212 | * @return string Whatever content is returned from the plugins controller (which 213 | * is usually HTML from the settings form) 214 | */ 215 | public function view_controller($plugin, $plugin_data = NULL) 216 | { 217 | if( ! isset(static::$plugins[$plugin])) 218 | { 219 | log_message('error',"The plugin {$plugin} was not found"); 220 | 221 | return FALSE; 222 | } 223 | elseif( ! method_exists(static::$plugins[$plugin]['handler'], 'controller')) 224 | { 225 | $this->_error('error','Plugin Error',"The plugin {$plugin} does not have a controller", TRUE); 226 | 227 | return FALSE; 228 | } 229 | 230 | return call_user_func(array(static::$plugins[$plugin]['handler'], 'controller'), $plugin_data); 231 | } 232 | 233 | // ------------------------------------------------------------------------ 234 | 235 | /** 236 | * Plugin Error Collector 237 | * 238 | * Push an error message into the messages array 239 | * 240 | * @param string $message Message to push 241 | * @access private 242 | */ 243 | private function _error($message) 244 | { 245 | //log_message('error', 'PLUGIN-ERROR: ' . $message); 246 | 247 | array_push(static::$messages['error'], $message); 248 | } 249 | 250 | // ------------------------------------------------------------------------ 251 | 252 | /** 253 | * Plugin Debug Collector 254 | * 255 | * Push a debug message into the messages array 256 | * 257 | * @param string $message Message to push 258 | * @access private 259 | */ 260 | private function _debug($message) 261 | { 262 | //log_message('debug', 'PLUGIN-DEBUG: ' . $message); 263 | 264 | array_push(static::$messages['debug'], $message); 265 | } 266 | 267 | // ------------------------------------------------------------------------ 268 | 269 | /** 270 | * Plugin Warn Collector 271 | * 272 | * Push a warn message into the messages array 273 | * 274 | * @param string $message Message to push 275 | * @access private 276 | */ 277 | private function _warn($message) 278 | { 279 | //log_message('error', 'PLUGIN-WARN: ' . $message); 280 | 281 | array_push(static::$messages['warn'], $message); 282 | } 283 | 284 | // ------------------------------------------------------------------------ 285 | 286 | /** 287 | * Enable Plugin 288 | * 289 | * Enable a plugin by setting the plugins.status to 1 in the plugins table 290 | * 291 | * @oaram string $plugin Plugin Name 292 | * @param mixed $data Any data that should be handed down to the plugins deactivate method (optional) 293 | * @access public 294 | * @since 0.1.0 295 | * @return bool 296 | */ 297 | public function enable_plugin($plugin, $data = NULL) 298 | { 299 | // Run the plugins activation method to run anything required by the plugin 300 | call_user_func(array(static::$plugins[$plugin]['handler'], 'activate'), $data); 301 | 302 | // Enable it in the database 303 | return static::$PM->set_status($plugin, 1); 304 | } 305 | 306 | // ------------------------------------------------------------------------ 307 | 308 | /** 309 | * Disable Plugin 310 | * 311 | * Disable a plugin by setting the plugins.status to 0 in the plugins table 312 | * 313 | * @oaram string $plugin Plugin Name 314 | * @param mixed $data Any data that should be handed down to the plugins activate method (optional) 315 | * @access public 316 | * @since 0.1.0 317 | * @return bool 318 | */ 319 | public function disable_plugin($plugin, $data = NULL) 320 | { 321 | // Run the plugins deactivation method to run anything required by the plugin 322 | call_user_func(array(static::$plugins[$plugin]['handler'], 'deactivate'), $data); 323 | 324 | // Disable it in the database 325 | return static::$PM->set_status($plugin, 0); 326 | } 327 | 328 | // ------------------------------------------------------------------------ 329 | 330 | /** 331 | * Install Plugin 332 | * 333 | * Install a plugin by adding it to the database and executing any installation code thats in 334 | * the plugins install method 335 | * 336 | * @param string $plugin Plugins system name (Folder name) 337 | * @access public 338 | * @param boolean 339 | */ 340 | public function install_plugin($plugin, $data = NULL) 341 | { 342 | // System name for folder and file 343 | $system_name = strtolower($plugin); 344 | 345 | // Class name is just system name with ucfirst 346 | $class_name = ucfirst($system_name); 347 | 348 | // Path to plugins main file 349 | $plugin_path = static::$plugin_path . "{$system_name}/{$system_name}.php"; 350 | 351 | // If the plugins class hasnt been loaded... 352 | if( ! class_exists($class_name)) 353 | { 354 | // Make sure a valid plugin file by the same name as the folder exists 355 | if (file_exists($plugin_path)) 356 | { 357 | if( ! include_once $plugin_path) 358 | { 359 | $this->_error("Failed to install {$plugin}, there was an error loading the plugin file {$plugin_path}, is it readable?"); 360 | } 361 | else 362 | { 363 | $this->_debug("Successfully loaded the plugin file {$plugin_path}"); 364 | } 365 | } 366 | else 367 | { 368 | $this->_error("Failed to install {$plugin}, unable to find the file {$plugin_path}"); 369 | } 370 | } 371 | 372 | // Execute the plugin installation 373 | return call_user_func("{$class_name}::install", $data); 374 | } 375 | 376 | // ------------------------------------------------------------------------ 377 | 378 | /** 379 | * Plugin Details 380 | * 381 | * Retrieve the details of a plugin from the database 382 | * 383 | * @param string $plugin Plugin system name 384 | * @access public 385 | * @since 0.1.0 386 | * @return object|bool 387 | */ 388 | public function plugin_details($plugin) 389 | { 390 | return static::$PM->get_plugin($plugin); 391 | } 392 | 393 | // ------------------------------------------------------------------------ 394 | 395 | /** 396 | * Get Enabled Plugins 397 | * 398 | * Retrieve the enabled plugins from the database and load them into the enabled_plugins 399 | * array. This does not initiate the plugins, thats done in a different method 400 | * 401 | * @access private 402 | */ 403 | private function get_plugins() 404 | { 405 | // Fetch all plugins 406 | if( ! $plugins = static::$PM->get_plugins()) 407 | { 408 | return FALSE; 409 | } 410 | 411 | // Load the plugins 412 | foreach($plugins as $p) 413 | { 414 | if( ! isset( static::$plugins[ $p->system_name ] ) ) 415 | { 416 | $this->_debug( "Adding plugin {$p->system_name}" ); 417 | 418 | static::$plugins[$p->system_name] = array( 419 | 'data' => $p->data 420 | ); 421 | 422 | // If its enabled, add it to $enabled_plugins referencing the plugin in $plugins 423 | if($p->status == '1') 424 | { 425 | $this->_debug( "Enabling plugin {$p->system_name}" ); 426 | 427 | static::$enabled_plugins[ $p->system_name ] = &static::$plugins[$p->system_name]; 428 | } 429 | } 430 | } 431 | } 432 | 433 | // ------------------------------------------------------------------------ 434 | 435 | /** 436 | * Print Plugins 437 | * 438 | * Retrieve all plugin information from the database 439 | * 440 | * @access public 441 | * @since 0.1.0 442 | * @return array 443 | */ 444 | public function retrieve_plugins() 445 | { 446 | return static::$PM->get_plugins(); 447 | } 448 | 449 | // ------------------------------------------------------------------------ 450 | 451 | /** 452 | * Include Enabled Plugins 453 | * 454 | * Iterate through the enabled_plugins property array and include the actual plugin files 455 | * 456 | * @access private 457 | */ 458 | private function include_enabled_plugins() 459 | { 460 | if(empty(static::$enabled_plugins)) 461 | { 462 | $this->_error("Unable to include enabled plugin files, enabled plugins not retrieved"); 463 | 464 | return FALSE; 465 | } 466 | 467 | foreach(static::$enabled_plugins as $name => $p) 468 | { 469 | $plugin_path = static::$plugin_path . "{$name}/{$name}.php"; 470 | 471 | // Make sure a valid plugin file by the same name as the folder exists 472 | if (file_exists($plugin_path)) 473 | { 474 | if( ! include_once $plugin_path) 475 | { 476 | $this->_error("There was an error loading the plugin file {$plugin_path}"); 477 | } 478 | else 479 | { 480 | $this->_debug("Successfully loaded the plugin file {$plugin_path}"); 481 | } 482 | } 483 | else 484 | { 485 | $this->_error("Failed to include the plugin {$name}, unable to find the file {$plugin_path}"); 486 | } 487 | } 488 | } 489 | 490 | // ------------------------------------------------------------------------ 491 | 492 | /** 493 | * Load Enabled Plugins 494 | * 495 | * Load the enabled plugins into objects, store the objects into the loaded plugins array 496 | * 497 | * @access private 498 | */ 499 | private function load_enabled_plugins() 500 | { 501 | if(static::$enabled_plugins) 502 | { 503 | foreach( static::$enabled_plugins as $name => $p ) 504 | { 505 | new $name; 506 | } 507 | } 508 | } 509 | 510 | // ------------------------------------------------------------------------ 511 | 512 | /** 513 | * Add Action 514 | * 515 | * Assign a function to be executed by a certain tag. An action will just fire off a function 516 | * when the tag is called, a filter will parse data and return the modified data 517 | * 518 | * @param string $tag Tag to add filter to 519 | * @param string|array $function Either a string (function), or an array (Object, method) 520 | * @param integer $priority Priority 521 | * @param string $type Either action or filter 522 | * @access public 523 | * @since 0.1.0 524 | * @return boolean 525 | */ 526 | public function add_action($tag, $function, $priority = 10, $type = 'action') 527 | { 528 | if(is_array($function)) 529 | { 530 | if(count($function) < 2) 531 | { 532 | // If its an array of one element, then just add the first element 533 | $function = $function[0]; 534 | } 535 | elseif( ! is_object($function[0])) 536 | { 537 | $this->_error("Failing to add method '" . implode('::', $function) . "'' as {$type} to tag {$tag}, an array was given, first element was not an object"); 538 | 539 | return FALSE; 540 | } 541 | elseif( ! method_exists($function[0], $function[1])) 542 | { 543 | $this->_error("Failing to add method '" . get_class($function[0]) . "::{$function[1]}' as {$type} to tag {$tag}, the method does not exist"); 544 | 545 | return FALSE; 546 | } 547 | } 548 | 549 | // Execute is_array again, since the above could have converted it to an array 550 | if( ! is_array($function)) 551 | { 552 | if( ! function_exists($function)) 553 | { 554 | $this->_error("Failing to add function {$function} as {$type} to tag {$tag}, the function does not exist"); 555 | 556 | return FALSE; 557 | } 558 | } 559 | 560 | if( ! in_array($type, ['action','filter'])) 561 | { 562 | $this->_error("Unknown type '{$type}', must be 'filter' or 'action'"); 563 | 564 | return FALSE; 565 | } 566 | 567 | static::$actions[$tag][$priority][] = array( 568 | 'function' => $function, 569 | 'type' => $type 570 | ); 571 | 572 | return TRUE; 573 | } 574 | 575 | // ------------------------------------------------------------------------ 576 | 577 | /** 578 | * Add Filter 579 | * 580 | * Just a wrapper for add_function except adds it as type 'filter'. Filters will 581 | * take in data and perform an action on it, then return it, actions will just 582 | * fire off a function 583 | * 584 | * @param string $tag Tag to add filter to 585 | * @param string|array $function Either a string (function), or an array (Object, method) 586 | * @param integer $priority Priority 587 | * @access public 588 | * @since 0.1.0 589 | * @return boolean 590 | */ 591 | public function add_filter($tag, $function, $priority = 10) 592 | { 593 | return $this->add_action($tag, $function, $priority, 'filter'); 594 | } 595 | 596 | // ------------------------------------------------------------------------ 597 | 598 | /** 599 | * Get Actions 600 | * 601 | * Get actions.... 602 | * 603 | * @access public 604 | * @since 0.1.0 605 | * @return array 606 | */ 607 | public function get_actions() 608 | { 609 | foreach(static::$actions as $k => $a) 610 | ksort(static::$actions[$k]); 611 | 612 | return static::$actions; 613 | } 614 | 615 | // ------------------------------------------------------------------------ 616 | 617 | /** 618 | * Do Action 619 | * 620 | * Execute a specific action, pass optional arguments to it 621 | * @param string $tag Tag to execute 622 | * @param null $args Arguments to hand to functions assigned to tag 623 | * @access public 624 | * @since 0.1.0 625 | * @return mixed Returns whatever the type of $args is 626 | */ 627 | public function do_action($tag, array $args = NULL) 628 | { 629 | static::$current_action = $tag; 630 | 631 | array_push(static::$run_actions, $tag); 632 | 633 | if( ! isset(static::$actions[$tag])) 634 | { 635 | $this->_debug("No actions found for tag {$tag}"); 636 | 637 | return $args; 638 | } 639 | 640 | ksort(static::$actions[$tag]); 641 | 642 | //die('
' . print_r(static::$actions, TRUE));
 643 | 
 644 |         foreach(static::$actions[$tag] as $actions)
 645 |         {
 646 |             foreach($actions as $a)
 647 |             {
 648 |                 // Make sure the function or method exists
 649 |                 if(is_array($a['function']))
 650 |                 {
 651 |                     // Methods are setup as an array, [0] is the object/class, [1] is the method
 652 |                     if( ! method_exists($a['function'][0], $a['function'][1]))
 653 |                     {
 654 |                         $this->_error("Unable to execute method '" . get_class($a['function'][0]) . "::{$a['function'][1]}' for action {$tag}, the method doesn't exist");
 655 | 
 656 |                         return $args;
 657 |                     }
 658 |                 }
 659 |                 else
 660 |                 {
 661 |                     // Strings are just functions
 662 |                     if( ! function_exists($a['function']))
 663 |                     {
 664 |                         $this->_error("Unable to execute function '{$a['function']}' for action {$tag}, the function doesn't exist");
 665 | 
 666 |                         return $args;
 667 |                     }
 668 |                 }
 669 | 
 670 |                 // Actions
 671 |                 if($a['type'] == 'action')
 672 |                 {
 673 |                     // No arguments/null
 674 |                     if( ! $args)
 675 |                     {
 676 |                         call_user_func( $a['function'] );
 677 |                     }
 678 |                     else
 679 |                     {
 680 |                         call_user_func_array( $a['function'], $args );
 681 |                     }
 682 |                 }
 683 |                 // Filters
 684 |                 else
 685 |                 {
 686 |                     // No arguments/null
 687 |                     if( ! $args)
 688 |                     {
 689 |                         $args = call_user_func( $a['function'] );
 690 |                     }
 691 |                     else
 692 |                     {
 693 |                         $args = call_user_func_array( $a['function'], $args );
 694 |                     }
 695 |                 }
 696 |             }
 697 |         }
 698 | 
 699 |         static::$current_action = NULL;
 700 | 
 701 |         // Be polite, return it as you found it
 702 |         settype($args, gettype($args));
 703 | 
 704 |         return $args;
 705 |     }
 706 | 
 707 |     // ------------------------------------------------------------------------
 708 | 
 709 |     /**
 710 |      * Remove Action
 711 |      *
 712 |      * Remove a function from an action
 713 |      *
 714 |      * @param   string  $tag Tag to check in
 715 |      * @param   mixed   $function Function to be removed
 716 |      * @param   integer $priority Priority to check for function
 717 |      * @access  public
 718 |      * @since   0.1.0
 719 |      * @return  boolean
 720 |      */
 721 |     public function remove_action($tag, $function, $priority = 10)
 722 |     {
 723 |         if (isset(static::$actions[$tag][$priority][$function]))
 724 |         {
 725 |             // Remove the action hook from our hooks array
 726 |             unset(static::$actions[$tag][$priority][$function]);
 727 |         }
 728 | 
 729 |         return TRUE;
 730 | 
 731 |     }
 732 | 
 733 |     // ------------------------------------------------------------------------
 734 | 
 735 |     /**
 736 |      * Current Action
 737 |      *
 738 |      * Set the currently running action
 739 |      *
 740 |      * @access public
 741 |      * @since   0.1.0
 742 |      * @return string
 743 |      */
 744 |     public function current_action()
 745 |     {
 746 |         return static::$current_action;
 747 |     }
 748 | 
 749 |     // ------------------------------------------------------------------------
 750 | 
 751 |     /**
 752 |      * Has Run
 753 |      *
 754 |      * See if a particular action has ran yet
 755 |      *
 756 |      * @param  string  $action  Action to check for
 757 |      * @access public
 758 |      * @since   0.1.0
 759 |      * @return boolean
 760 |      */
 761 |     public function has_run($action)
 762 |     {
 763 |         if (isset(static::$run_actions[$action]))
 764 |         {
 765 |             return true;
 766 |         }
 767 |         else
 768 |         {
 769 |             return false;
 770 |         }
 771 |     }
 772 | 
 773 |     // ------------------------------------------------------------------------
 774 | 
 775 |     /**
 776 |      * Update Plugin Headers
 777 |      *
 778 |      * Parse a given plugins PHP file for the header information in the comments, and update the database info
 779 |      * accordingly
 780 |      *
 781 |      * @param   string  $plugin Plugin System Name to check
 782 |      * @access  public
 783 |      * @todo    Try to retrieve only the top X lines of the file, not the whole file
 784 |      * @since   0.1.0
 785 |      * @return  TRUE Always true
 786 |      */
 787 |     public function update_plugin_headers($plugin)
 788 |     {
 789 |         if (isset(static::$plugins[$plugin]))
 790 |         {
 791 |             $arr = array();
 792 | 
 793 |             $plugin_data = file_get_contents(static::$plugin_path.$plugin."/".$plugin.".php"); // Load the plugin we want
 794 | 
 795 |             preg_match ('|Plugin Name:(.*)$|mi', $plugin_data, $name);
 796 |             preg_match ('|Plugin URI:(.*)$|mi', $plugin_data, $uri);
 797 |             preg_match ('|Version:(.*)|i', $plugin_data, $version);
 798 |             preg_match ('|Description:(.*)$|mi', $plugin_data, $description);
 799 |             preg_match ('|Author:(.*)$|mi', $plugin_data, $author_name);
 800 |             preg_match ('|Author URI:(.*)$|mi', $plugin_data, $author_uri);
 801 | 
 802 |             if (isset($name[1]))
 803 |             {
 804 |                 $arr['name'] = trim($name[1]);
 805 |             }
 806 | 
 807 |             if (isset($uri[1]))
 808 |             {
 809 |                 $arr['uri'] = trim($uri[1]);
 810 |             }
 811 | 
 812 |             if (isset($version[1]))
 813 |             {
 814 |                 $arr['version'] = trim($version[1]);
 815 |             }
 816 | 
 817 |             if (isset($description[1]))
 818 |             {
 819 |                 $arr['description'] = trim($description[1]);
 820 |             }
 821 | 
 822 |             if (isset($author_name[1]))
 823 |             {
 824 |                 $arr['author'] = trim($author_name[1]);
 825 |             }
 826 | 
 827 |             if (isset($author_uri[1]))
 828 |             {
 829 |                 $arr['author_uri'] = trim($author_uri[1]);
 830 |             }
 831 | 
 832 |             if(empty($arr))
 833 |             {
 834 |                 $this->_warn("Skipping header update for {$plugin}, no headers matched");
 835 |             }
 836 |             elseif(self::$PM->update_plugin_info($plugin, $arr))
 837 |             {
 838 |                 $this->_debug("Updated plugin headers for {$plugin}: " . serialize($arr));
 839 |             }
 840 |             else
 841 |             {
 842 |                 $this->_error("Failed to update plugin headers for {$plugin}: " . serialize($arr));
 843 |             }
 844 |         }
 845 | 
 846 |         return TRUE;
 847 |     }
 848 | 
 849 |     // ------------------------------------------------------------------------
 850 | 
 851 |     /**
 852 |      * Update All Plugin Headers
 853 |      *
 854 |      * Execute self::update_plugin_headers for each plugin found in static::$plugins
 855 |      *
 856 |      * @access public
 857 |      * @since   0.1.0
 858 |      * @return boolean
 859 |      */
 860 |     public function update_all_plugin_headers()
 861 |     {
 862 |         if(empty(static::$plugins))
 863 |         {
 864 |             $this->_warn("No plugins to update headers for");
 865 | 
 866 |             return TRUE;
 867 |         }
 868 | 
 869 |         foreach(static::$plugins as $name => $plugin)
 870 |         {
 871 |             $this->_debug("Updating plugin headers for {$name}");
 872 | 
 873 |             if( ! $this->update_plugin_headers($name))
 874 |             {
 875 |                 return FALSE;
 876 |             }
 877 |         }
 878 | 
 879 |         return TRUE;
 880 |     }
 881 | 
 882 |     // ------------------------------------------------------------------------
 883 | 
 884 |     /**
 885 |      * Doing Action
 886 |      *
 887 |      * If the param is NULL, then this will return what action is being executed,
 888 |      * if an action is supplied, then it will return boolean based on if that action
 889 |      * is being executed or not
 890 |      *
 891 |      * @param null $action  Action to check for
 892 |      */
 893 |     public function doing_action($action = NULL)
 894 |     {
 895 |         if(is_null($action))
 896 |         {
 897 |             return static::$current_action;
 898 |         }
 899 |         else
 900 |         {
 901 |             return $action === static::$current_action;
 902 |         }
 903 |     }
 904 | 
 905 |     // ------------------------------------------------------------------------
 906 | 
 907 |     /**
 908 |      * Did Action
 909 |      *
 910 |      * Returns if a tag has been fired or not
 911 |      *
 912 |      * @param $tag
 913 |      */
 914 |     public function did_action($tag)
 915 |     {
 916 |         return in_array($tag, static::$run_actions);
 917 |     }
 918 | 
 919 |     // ------------------------------------------------------------------------
 920 | 
 921 |     /**
 922 |      * Get Orphaned Plugins
 923 |      *
 924 |      * Look in the plugin directory for any folders that do not have an associated entry
 925 |      * in the plugins table
 926 |      *
 927 |      * @access public
 928 |      * @since   0.1.0
 929 |      * @return array|bool   If no orphaned plugins are found, return false
 930 |      */
 931 |     public function get_orphaned_plugins()
 932 |     {
 933 |         $files = scandir(static::$plugin_path);
 934 | 
 935 |         $plugins = static::$PM->get_plugins();
 936 | 
 937 |         $orphaned = array();
 938 | 
 939 |         foreach($files as $f)
 940 |         {
 941 |             // Skip directories
 942 |             if(in_array($f, ['.','..'])) continue;
 943 | 
 944 |             if( ! isset($plugins[$f]))
 945 |             {
 946 |                 array_push($orphaned, $f);
 947 |             }
 948 |         }
 949 | 
 950 |         return (count($orphaned) > 0 ? $orphaned : FALSE);
 951 |     }
 952 | 
 953 |     // ------------------------------------------------------------------------
 954 | 
 955 |     /**
 956 |      * Get Messages
 957 |      *
 958 |      * Get all messages, or a specific type of message
 959 |      *
 960 |      * @param   string  $type   Type of error to retrieve (error, debug, warn)
 961 |      * @access  public
 962 |      * @since   0.1.0
 963 |      * @return  array|bool
 964 |      */
 965 |     public function get_messages($type = NULL)
 966 |     {
 967 |         if( ! $type)
 968 |         {
 969 |             return static::$messages;
 970 |         }
 971 |         elseif( ! isset(static::$messages[ strtolower($type) ]))
 972 |         {
 973 |             $this->_error("Failed to retrieve error type '{$type}', no such type found. Use 'error', 'warn' or 'debug'");
 974 | 
 975 |             return FALSE;
 976 |         }
 977 | 
 978 |         return static::$messages[strtolower($type)];
 979 |     }
 980 | 
 981 |     // ------------------------------------------------------------------------
 982 | 
 983 |     /**
 984 |      * Print Messages
 985 |      *
 986 |      * Print all messages, or messages of a certain type
 987 |      *
 988 |      * @param   string  $type   Type of error to display (error, debug, warn)
 989 |      * @access  public
 990 |      * @since   0.1.0
 991 |      * @return  array|bool
 992 |      */
 993 |     public function print_messages($type = NULL)
 994 |     {
 995 |         if($type)
 996 |         {
 997 |             if(@empty(static::$messages[ strtolower($type) ]) || ! isset(static::$messages[ strtolower($type) ]))
 998 |             {
 999 |                 echo "{$type} IS EMPTY\n";
1000 |                 return TRUE;
1001 |             }
1002 | 
1003 |             echo "

Plugin Messages - " . ucfirst($type) . "

\n"; 1004 | 1005 | echo "
    \n"; 1006 | 1007 | foreach(static::$messages[ strtolower($type) ] as $m) 1008 | { 1009 | echo "
  1. $m
  2. \n"; 1010 | } 1011 | 1012 | echo "
\n\n"; 1013 | 1014 | return TRUE; 1015 | } 1016 | 1017 | foreach(static::$messages as $type => $messages) 1018 | { 1019 | if(@empty($messages)) 1020 | { 1021 | echo "{$type} IS EMPTY\n"; 1022 | continue; 1023 | } 1024 | 1025 | echo "

Plugin Messages - " . ucfirst($type) . "

\n"; 1026 | 1027 | echo "
    \n"; 1028 | 1029 | foreach($messages as $m) 1030 | { 1031 | echo "
  1. $m
  2. \n"; 1032 | } 1033 | 1034 | echo "
\n\n"; 1035 | } 1036 | 1037 | return TRUE; 1038 | } 1039 | } -------------------------------------------------------------------------------- /application/libraries/abstract.plugins.php: -------------------------------------------------------------------------------- 1 | input->get($index, $xss_clean); 61 | } 62 | 63 | // ------------------------------------------------------------------------ 64 | 65 | /** 66 | * Fetch an item from the POST array 67 | * 68 | * Shortcut to Loader::post() 69 | * 70 | * @param mixed $index Index for item to be fetched from $_POST 71 | * @param bool $xss_clean Whether to apply XSS filtering 72 | * @access protected 73 | * @since 0.1.0 74 | * @return mixed 75 | */ 76 | protected function post($index = NULL, $xss_clean = NULL) 77 | { 78 | return parent::$CI->input->post($index, $xss_clean); 79 | } 80 | 81 | // ------------------------------------------------------------------------ 82 | 83 | /** 84 | * Fetch an item from POST data with fallback to GET 85 | * 86 | * Shortcut to Loader::post_get() 87 | * 88 | * @param string $index Index for item to be fetched from $_POST or $_GET 89 | * @param bool $xss_clean Whether to apply XSS filtering 90 | * @access protected 91 | * @since 0.1.0 92 | * @return mixed 93 | */ 94 | protected function post_get($index, $xss_clean = NULL) 95 | { 96 | return parent::$CI->input->post_get($index, $xss_clean); 97 | } 98 | 99 | // ------------------------------------------------------------------------ 100 | 101 | /** 102 | * Fetch an item from GET data with fallback to POST 103 | * 104 | * Shortcut to Loader::get_post() 105 | * 106 | * @param string $index Index for item to be fetched from $_GET or $_POST 107 | * @param bool $xss_clean Whether to apply XSS filtering 108 | * @access protected 109 | * @since 0.1.0 110 | * @return mixed 111 | */ 112 | protected function get_post($index, $xss_clean = NULL) 113 | { 114 | return parent::$CI->input->get_post($index, $xss_clean); 115 | } 116 | 117 | // ------------------------------------------------------------------------ 118 | 119 | /** 120 | * Plugin View 121 | * 122 | * Load a plugin view via Loader::plugin_view() 123 | * 124 | * @param str $view Plugin view to load, must exist in the /views/ folder of the plugins root directory 125 | * @param array $data Data to load into view. 126 | * @access protected 127 | * @since 0.1.0 128 | * @return str String value of processed view 129 | */ 130 | protected function view($view, array $data = array()) 131 | { 132 | $backtrace = debug_backtrace(); 133 | 134 | if( ! isset($backtrace[1]['class'])) 135 | { 136 | return FALSE; 137 | } 138 | 139 | // The strtolower version of the class name should be the plugin folder name 140 | $class = strtolower($backtrace[1]['class']); 141 | 142 | return parent::$CI->load->plugin_view($class, $view, $data, TRUE); 143 | } 144 | } 145 | -------------------------------------------------------------------------------- /application/models/Plugins_model.php: -------------------------------------------------------------------------------- 1 | db; 63 | } 64 | 65 | // ------------------------------------------------------------------------ 66 | 67 | /** 68 | * Get Plugins 69 | * 70 | * Get all plugins, return an array of the plugins from the database, with the system_name 71 | * as the keys 72 | * 73 | * @access public 74 | * @since 0.1.0 75 | * @return array|bool 76 | */ 77 | public function get_plugins() 78 | { 79 | $query = static::$db->get('plugins'); 80 | 81 | if( ! $result = $query->result()) 82 | { 83 | log_message('error','Error retrieving plugins from database'); 84 | 85 | return FALSE; 86 | } 87 | 88 | $return = array(); 89 | 90 | foreach($result as $r) 91 | { 92 | if( ! empty($r->data)) 93 | { 94 | $r->data = unserialize($r->data); 95 | } 96 | 97 | $return[$r->system_name] = $r; 98 | } 99 | 100 | return $return; 101 | } 102 | 103 | // ------------------------------------------------------------------------ 104 | 105 | /** 106 | * Update Plugin Info 107 | * 108 | * Update the plugin information in the database. This is typically executed by the 109 | * Plugins_lib::update_headers() which parses the comments of the plugin for the info 110 | * 111 | * @param str $plugin The system_name of the plugin 112 | * @param array $settings New settings for plugin 113 | * @access public 114 | * @since 0.1.0 115 | * @return bool 116 | */ 117 | public function update_plugin_info($plugin, array $settings) 118 | { 119 | return static::$db->where('system_name', $plugin)->update('plugins', $settings); 120 | } 121 | 122 | // ------------------------------------------------------------------------ 123 | 124 | /** 125 | * Set Status 126 | * 127 | * Enable/Disable plugin 128 | * 129 | * @param string $plugin Plugin system name 130 | * @param bool $status Status to set plugin as 131 | * @access public 132 | * @since 0.1.0 133 | * @return bool 134 | */ 135 | public function set_status($plugin, $status) 136 | { 137 | log_message("error","PLUGIN: $plugin; STATUS: $status"); 138 | 139 | if( ! static::$db 140 | ->where('system_name', $plugin) 141 | ->update('plugins', ['status' => $status])) 142 | { 143 | return FALSE; 144 | } 145 | 146 | return TRUE; 147 | } 148 | 149 | // ------------------------------------------------------------------------ 150 | 151 | /** 152 | * Get Plugin 153 | * 154 | * Retrieve the data from the database for a single plugin by the plugin system name 155 | * 156 | * @param string $plugin Plugin System Name 157 | * @access public 158 | * @since 0.1.0 159 | * @return bool|object 160 | */ 161 | public function get_plugin($plugin) 162 | { 163 | $query = static::$db->get_where('plugins', ['system_name' => $plugin]); 164 | 165 | $result = $query->result(); 166 | 167 | return ( ! @empty($result[0]) ? $result[0] : FALSE); 168 | } 169 | } 170 | -------------------------------------------------------------------------------- /application/models/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 403 Forbidden 5 | 6 | 7 | 8 |

Directory access is forbidden.

9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /application/views/plugin_list.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | $p): ?> 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 |
PluginStatusURIVersionDescriptionAuthorData
system_name . '">' . $p->name . ''; ?>status ? 'Enabled' : 'Disabled'); ?>uri . '" target="_blank">' . $p->uri . ''; ?>version; ?>description; ?>author_uri . '" target="_blank">' . $p->author . ''; ?>
data ? print_r(unserialize($p->data), TRUE) : 'No Data'); ?>
-------------------------------------------------------------------------------- /application/views/plugin_settings.php: -------------------------------------------------------------------------------- 1 |

Settings for

2 |
3 | 


--------------------------------------------------------------------------------
/plugin_database.sql:
--------------------------------------------------------------------------------
  1 | -- MySQL dump 10.13  Distrib 5.5.42, for osx10.6 (i386)
  2 | --
  3 | -- Host: localhost    Database: citest
  4 | -- ------------------------------------------------------
  5 | -- Server version	5.5.42
  6 | 
  7 | /*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
  8 | /*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
  9 | /*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
 10 | /*!40101 SET NAMES utf8 */;
 11 | /*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */;
 12 | /*!40103 SET TIME_ZONE='+00:00' */;
 13 | /*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;
 14 | /*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
 15 | /*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
 16 | /*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;
 17 | 
 18 | --
 19 | -- Table structure for table `citest_table1`
 20 | --
 21 | 
 22 | DROP TABLE IF EXISTS `citest_table1`;
 23 | /*!40101 SET @saved_cs_client     = @@character_set_client */;
 24 | /*!40101 SET character_set_client = utf8 */;
 25 | CREATE TABLE `citest_table1` (
 26 |   `id` int(11) NOT NULL AUTO_INCREMENT,
 27 |   `first_name` varchar(100) DEFAULT NULL,
 28 |   PRIMARY KEY (`id`)
 29 | ) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=latin1;
 30 | /*!40101 SET character_set_client = @saved_cs_client */;
 31 | 
 32 | --
 33 | -- Dumping data for table `citest_table1`
 34 | --
 35 | 
 36 | LOCK TABLES `citest_table1` WRITE;
 37 | /*!40000 ALTER TABLE `citest_table1` DISABLE KEYS */;
 38 | INSERT INTO `citest_table1` VALUES (1,'Justin'),(2,'Amanda');
 39 | /*!40000 ALTER TABLE `citest_table1` ENABLE KEYS */;
 40 | UNLOCK TABLES;
 41 | 
 42 | --
 43 | -- Table structure for table `citest_table2`
 44 | --
 45 | 
 46 | DROP TABLE IF EXISTS `citest_table2`;
 47 | /*!40101 SET @saved_cs_client     = @@character_set_client */;
 48 | /*!40101 SET character_set_client = utf8 */;
 49 | CREATE TABLE `citest_table2` (
 50 |   `id` int(11) NOT NULL AUTO_INCREMENT,
 51 |   `last_name` varchar(100) NOT NULL,
 52 |   PRIMARY KEY (`id`)
 53 | ) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=latin1;
 54 | /*!40101 SET character_set_client = @saved_cs_client */;
 55 | 
 56 | --
 57 | -- Dumping data for table `citest_table2`
 58 | --
 59 | 
 60 | LOCK TABLES `citest_table2` WRITE;
 61 | /*!40000 ALTER TABLE `citest_table2` DISABLE KEYS */;
 62 | INSERT INTO `citest_table2` VALUES (1,'Hyland'),(2,'Trueba');
 63 | /*!40000 ALTER TABLE `citest_table2` ENABLE KEYS */;
 64 | UNLOCK TABLES;
 65 | 
 66 | --
 67 | -- Table structure for table `plugins`
 68 | --
 69 | 
 70 | DROP TABLE IF EXISTS `plugins`;
 71 | /*!40101 SET @saved_cs_client     = @@character_set_client */;
 72 | /*!40101 SET character_set_client = utf8 */;
 73 | CREATE TABLE `plugins` (
 74 |   `plugin_id` int(11) NOT NULL AUTO_INCREMENT,
 75 |   `system_name` varchar(150) NOT NULL,
 76 |   `name` varchar(150) NOT NULL,
 77 |   `status` tinyint(1) NOT NULL DEFAULT '1',
 78 |   `uri` varchar(255) DEFAULT NULL,
 79 |   `version` varchar(10) NOT NULL,
 80 |   `description` varchar(255) DEFAULT NULL,
 81 |   `author` varchar(50) DEFAULT NULL,
 82 |   `author_uri` varchar(255) DEFAULT NULL,
 83 |   `data` longtext,
 84 |   PRIMARY KEY (`plugin_id`)
 85 | ) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=latin1;
 86 | /*!40101 SET character_set_client = @saved_cs_client */;
 87 | 
 88 | --
 89 | -- Dumping data for table `plugins`
 90 | --
 91 | 
 92 | LOCK TABLES `plugins` WRITE;
 93 | /*!40000 ALTER TABLE `plugins` DISABLE KEYS */;
 94 | INSERT INTO `plugins` VALUES (1,'hello_world','Hello World',1,'https://github.com/jhyland87/CI3_Plugin_System','1.0','Apply colors to asset table cells or rows depending on values','Justin Hyland','http://justinhyland.com',NULL);
 95 | /*!40000 ALTER TABLE `plugins` ENABLE KEYS */;
 96 | UNLOCK TABLES;
 97 | /*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */;
 98 | 
 99 | /*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
100 | /*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;
101 | /*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */;
102 | /*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
103 | /*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
104 | /*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
105 | /*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;
106 | 
107 | -- Dump completed on 2015-09-25 13:36:16
108 | 


--------------------------------------------------------------------------------
/plugins/hello_world/hello_world.php:
--------------------------------------------------------------------------------
 1 | {$foo}..
"; 39 | } 40 | 41 | 42 | $content .= '
' 43 | . '
' 44 | . '' 45 | . '
'; 46 | 47 | return $content; 48 | } 49 | 50 | 51 | // Just an example filter to alter the values of an array 52 | public function alter_name($data) 53 | { 54 | array_walk($data, function(&$item, $key){ 55 | if(strtolower($item) === 'jane') 56 | $item = 'john'; 57 | 58 | $item = ucfirst($item); 59 | }); 60 | 61 | return $data; 62 | } 63 | 64 | // Example plugin action, just logs.. stuff 65 | public function log_stuff($prefix, $data) 66 | { 67 | 68 | log_message('info', "[{$prefix}] " . __METHOD__ . ": Logging stuff - " . ((is_array($data) || is_object($data)) ? serialize($data) : $data)); 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /plugins/hello_world/views/settings.php: -------------------------------------------------------------------------------- 1 | 2 |

3 | Result: 4 |

5 |
6 | 7 |
8 |
9 | 10 |
--------------------------------------------------------------------------------