/metabbs/core/plugin.php

https://github.com/devilzz/metabbs · PHP · 237 lines · 156 code · 20 blank · 61 comment · 26 complexity · 72eb39f202b86ffab86bd874db41ac5d MD5 · raw file

  1. <?php
  2. // Filter API
  3. define('META_FILTER_OVERWRITE', 1); // 필터 충돌시 겹쳐쓴다.
  4. define('META_FILTER_PREPEND', 2); // 필터 충돌시 앞에 쓴다.
  5. define('META_FILTER_APPEND', 3); // 필터 충돌시 뒤에 쓴다.
  6. define('META_FILTER_CALLBACK', 4); // 충돌시 콜백 함수를 호출한다.
  7. /**
  8. * 플러그인 등록하기
  9. * @param $name 플러그인의 이름
  10. */
  11. function register_plugin($name) {
  12. global $__plugins;
  13. $plugin = Plugin::find_by_name($name);
  14. if ($plugin->enabled) {
  15. $plugin->on_init();
  16. if (isset($plugin->installed_version) &&
  17. $plugin->version > $plugin->installed_version)
  18. $plugin->on_update();
  19. }
  20. $__plugins[$name] = $plugin;
  21. ksort($__plugins);
  22. }
  23. /**
  24. * 관리자 메뉴 추가하기
  25. * @param $url 추가할 url
  26. * @param $text 화면에 표시할 문자열
  27. */
  28. function add_admin_menu($url, $text) {
  29. global $__admin_menu;
  30. $__admin_menu[] = link_text($url, $text);
  31. }
  32. /**
  33. * 필터를 추가한다.
  34. * @param $event 추가할 이벤트
  35. * @param $callback 이벤트에 호출할 함수
  36. * @param $priority 우선 순위
  37. * @param $collision 충돌시 정책
  38. * @param $fallback 충돌시 폴백을 지정하여 폴백이 해결한다.
  39. * 충돌시 정책이 META_FILTER_CALLBACK 일 경우만 사용.
  40. * @see META_FILTER_OVERWRITE 충돌 정책들
  41. * @see META_FILTER_PREPEND
  42. * @see META_FILTER_APPEND
  43. * @see META_FILTER_CALLBACK
  44. */
  45. function add_filter($event, $callback, $priority, $collision = META_FILTER_OVERWRITE, $fallback = null) {
  46. global $filters;
  47. if (@array_key_exists($priority, $filters[$event])) {
  48. switch ($collision) {
  49. case META_FILTER_OVERWRITE:
  50. $filters[$event][$priority] = $callback;
  51. break;
  52. case META_FILTER_PREPEND:
  53. $priority--;
  54. add_filter($event, $callback, $priority, $collision);
  55. break;
  56. case META_FILTER_APPEND:
  57. $priority++;
  58. add_filter($event, $callback, $priority, $collision);
  59. break;
  60. case META_FILTER_CALLBACK:
  61. if ($fallback) call_user_func($fallback);
  62. break;
  63. }
  64. } else {
  65. $filters[$event][$priority] = $callback;
  66. }
  67. ksort($filters[$event]);
  68. }
  69. /**
  70. * 필터를 제거한다.
  71. * @param $event 이벤트
  72. * @param $callback 등록한 함수
  73. */
  74. function remove_filter($event, $callback) {
  75. global $filters;
  76. $key = array_search($callback, $filters[$event]);
  77. unset($filters[$event][$key]);
  78. }
  79. function remove_all_filters($event) {
  80. global $filters;
  81. $filters[$event] = array();
  82. }
  83. /**
  84. * 필터를 적용한다.
  85. * 해당 이벤트에 등록된 이벤트를 모두 실행
  86. * @param $event 해당 이벤트
  87. * @param $model 적용할 모델
  88. */
  89. function apply_filters($event, &$model, $args = array()) {
  90. global $filters;
  91. if (isset($filters[$event])) {
  92. foreach ($filters[$event] as $callback) {
  93. call_user_func_array($callback, array(&$model, $args));
  94. }
  95. }
  96. }
  97. /**
  98. * 다수의 모델에 대해 필터를 적용한다.
  99. * @param $event 해당 이벤트
  100. * @param $array 적용 모델을 담고 있는 배열
  101. */
  102. function apply_filters_array($event, &$array, $args = array()) {
  103. foreach (array_keys($array) as $key) {
  104. apply_filters($event, $array[$key], $args);
  105. }
  106. }
  107. // Handler API
  108. // TODO: 한 액션을 여러 핸들러가 처리해야 할 때
  109. /**
  110. * 디폴트를 후킹으로 핸들러를 추가한다.
  111. * @param $controller 컨트롤러
  112. * @param $action 액션
  113. * @param $callback 호출할 함수
  114. * @param type 핸들러 타입.
  115. * hook이 디폴트인데 before가 이용가능하다.
  116. */
  117. function add_handler($controller, $action, $callback, $type = 'hook') {
  118. global $handlers;
  119. $handlers[$controller][$action][$type] = $callback;
  120. }
  121. function reset_custom_handler() {
  122. global $handlers;
  123. $handlers = array();
  124. }
  125. /**
  126. * 등록된 후킹 핸들러를 실행한다.
  127. * @param $controller 컨트롤러
  128. * @param $action 액션
  129. * @return 후킹 핸들러가 등록된 경우 실행하고 true를 아닌경우 false.
  130. */
  131. function run_custom_handler($controller, $action) {
  132. global $handlers;
  133. run_before_handler($controller, $action);
  134. if (isset($handlers[$controller][$action]['hook'])) {
  135. call_user_func($handlers[$controller][$action]['hook']);
  136. return true;
  137. } else {
  138. return false;
  139. }
  140. }
  141. /**
  142. * 해당 액션보다 먼저 실행하도록 된 핸들러를 실행한다.
  143. * @param $controller 컨트롤러
  144. * @param $action 액션
  145. */
  146. function run_before_handler($controller, $action) {
  147. global $handlers;
  148. if (isset($handlers[$controller][$action]['before'])) {
  149. call_user_func($handlers[$controller][$action]['before']);
  150. }
  151. }
  152. function import_plugins_from($dir) {
  153. $dp = opendir($dir);
  154. while ($file = readdir($dp)) {
  155. list($name, ) = explode('.', $file);
  156. import_plugin($name, $dir);
  157. }
  158. closedir($dp);
  159. }
  160. function plugin_dirs() {
  161. static $dirs;
  162. if (!isset($dirs)) {
  163. global $config;
  164. $dirs = array(METABBS_DIR . '/plugins/');
  165. $extra = $config->get('plugin_extra_path');
  166. if ($extra)
  167. $dirs[] = $extra;
  168. }
  169. return $dirs;
  170. }
  171. function get_plugins() {
  172. foreach (plugin_dirs() as $dir)
  173. import_plugins_from($dir);
  174. return $GLOBALS['__plugins'];
  175. }
  176. function import_plugin($plugin, $dir = '') {
  177. // to avoid class redeclaration
  178. if (class_exists($plugin))
  179. return;
  180. if (!$dir) {
  181. foreach (plugin_dirs() as $dir)
  182. if (import_plugin($plugin, $dir)) break;
  183. } else {
  184. if (file_exists("$dir$plugin.php")) {
  185. include_once("$dir$plugin.php");
  186. return true;
  187. } else if (file_exists("$dir$plugin/plugin.php")) {
  188. include_once("$dir$plugin/plugin.php");
  189. return true;
  190. }
  191. return false;
  192. }
  193. }
  194. function import_enabled_plugins() {
  195. import_plugin('_base');
  196. foreach (get_enabled_plugins() as $plugin) {
  197. import_plugin($plugin->name);
  198. }
  199. }
  200. function get_plugin_path($plugin) {
  201. global $config;
  202. $base_plugin_path = METABBS_DIR.'/plugins/';
  203. if (file_exists($base_plugin_path.$plugin.'.php')) {
  204. return $base_plugin_path;
  205. } else if (file_exists($base_plugin_path.$plugin.'/plugin.php')) {
  206. return $base_plugin_path.$plugin;
  207. }
  208. $extra = $config->get('plugin_extra_path');
  209. $extra_plugin_path = realpath($extra);
  210. if (file_exists($extra_plugin_path.'/'.$plugin.'.php')) {
  211. return $extra_plugin_path;
  212. } else if (file_exists($extra_plugin_path.'/'.$plugin.'/plugin.php')) {
  213. return $extra_plugin_path.'/'.$plugin;
  214. }
  215. return false;
  216. }
  217. ?>