plugin.lib.php 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436
  1. <?php
  2. /* See license terms in /license.txt */
  3. class AppPlugin
  4. {
  5. public $plugin_regions = array(
  6. 'login_top',
  7. 'login_bottom',
  8. 'menu_top',
  9. 'menu_bottom',
  10. 'content_top',
  11. 'content_bottom',
  12. 'header_main',
  13. 'header_center',
  14. 'header_left',
  15. 'header_right',
  16. 'footer_left',
  17. 'footer_center',
  18. 'footer_right',
  19. 'course_tool_plugin'
  20. );
  21. public function __construct()
  22. {
  23. }
  24. function read_plugins_from_path() {
  25. /* We scan the plugin directory. Each folder is a potential plugin. */
  26. $pluginpath = api_get_path(SYS_PLUGIN_PATH);
  27. $possible_plugins = array();
  28. $handle = @opendir($pluginpath);
  29. while (false !== ($file = readdir($handle))) {
  30. if ($file != '.' && $file != '..' && is_dir(api_get_path(SYS_PLUGIN_PATH).$file)) {
  31. $possible_plugins[] = $file;
  32. }
  33. }
  34. @closedir($handle);
  35. sort($possible_plugins);
  36. return $possible_plugins;
  37. }
  38. function get_installed_plugins_by_region(){
  39. $used_plugins = array();
  40. /* We retrieve all the active plugins. */
  41. $result = api_get_settings('Plugins');
  42. foreach ($result as $row) {
  43. $used_plugins[$row['variable']][] = $row['selected_value'];
  44. }
  45. return $used_plugins;
  46. }
  47. function get_installed_plugins() {
  48. $installed_plugins = array();
  49. $plugin_array = api_get_settings_params(array("variable = ? AND selected_value = ? AND category = ? " =>
  50. array('status', 'installed', 'Plugins')));
  51. if (!empty($plugin_array)) {
  52. foreach ($plugin_array as $row) {
  53. $installed_plugins[$row['subkey']] = true;
  54. }
  55. $installed_plugins = array_keys($installed_plugins);
  56. }
  57. return $installed_plugins;
  58. }
  59. function install($plugin_name, $access_url_id = null) {
  60. if (empty($access_url_id)) {
  61. $access_url_id = api_get_current_access_url_id();
  62. } else {
  63. $access_url_id = intval($access_url_id);
  64. }
  65. api_add_setting('installed', 'status', $plugin_name, 'setting', 'Plugins', $plugin_name, null, null, null, $access_url_id, 1);
  66. //api_add_setting($plugin, $area, $plugin, null, 'Plugins', $plugin, null, null, null, $_configuration['access_url'], 1);
  67. $pluginpath = api_get_path(SYS_PLUGIN_PATH).$plugin_name.'/install.php';
  68. if (is_file($pluginpath) && is_readable($pluginpath)) {
  69. // Executes the install procedure
  70. require $pluginpath;
  71. }
  72. }
  73. function uninstall($plugin_name, $access_url_id = null) {
  74. if (empty($access_url_id)) {
  75. $access_url_id = api_get_current_access_url_id();
  76. } else {
  77. $access_url_id = intval($access_url_id);
  78. }
  79. api_delete_settings_params(array('category = ? AND access_url = ? AND subkey = ? ' =>
  80. array('Plugins', $access_url_id, $plugin_name)));
  81. $pluginpath = api_get_path(SYS_PLUGIN_PATH).$plugin_name.'/uninstall.php';
  82. if (is_file($pluginpath) && is_readable($pluginpath)) {
  83. //execute the uninstall procedure
  84. require $pluginpath;
  85. }
  86. }
  87. function get_areas_by_plugin($plugin_name) {
  88. $result = api_get_settings('Plugins');
  89. $areas = array();
  90. foreach ($result as $row) {
  91. if ($plugin_name == $row['selected_value']) {
  92. $areas[] = $row['variable'];
  93. }
  94. }
  95. return $areas;
  96. }
  97. function is_valid_plugin_location($location) {
  98. return in_array($location, $this->plugin_list);
  99. }
  100. function is_valid_plugin($plugin_name) {
  101. if (is_dir(api_get_path(SYS_PLUGIN_PATH).$plugin_name)) {
  102. if (is_file(api_get_path(SYS_PLUGIN_PATH).$plugin_name.'/index.php')) {
  103. return true;
  104. }
  105. }
  106. return false;
  107. }
  108. function get_plugin_regions() {
  109. sort($this->plugin_regions);
  110. return $this->plugin_regions;
  111. }
  112. function load_region($plugins, $region, $main_template, $forced = false)
  113. {
  114. if ($region == 'course_tool_plugin') {
  115. return null;
  116. }
  117. ob_start();
  118. $this->get_all_plugin_contents_by_region($plugins, $region, $main_template, $forced);
  119. $content = ob_get_contents();
  120. ob_end_clean();
  121. return $content;
  122. }
  123. /**
  124. * Loads the translation files inside a plugin if exists. It loads by default english see the hello world plugin
  125. *
  126. * @todo add caching
  127. * @param string $plugin_name
  128. */
  129. function load_plugin_lang_variables($plugin_name) {
  130. global $language_interface;
  131. $root = api_get_path(SYS_PLUGIN_PATH);
  132. //1. Loading english if exists
  133. $english_path = $root.$plugin_name."/lang/english.php";
  134. if (is_readable($english_path)) {
  135. include $english_path;
  136. foreach ($strings as $key => $string) {
  137. $GLOBALS[$key] = $string;
  138. }
  139. }
  140. //2. Loading the system language
  141. if ($language_interface != 'english') {
  142. $path = $root.$plugin_name."/lang/$language_interface.php";
  143. if (is_readable($path)) {
  144. include $path;
  145. if (!empty($strings)) {
  146. foreach ($strings as $key => $string) {
  147. $GLOBALS[$key] = $string;
  148. }
  149. }
  150. }
  151. }
  152. }
  153. /**
  154. *
  155. * @param string $block
  156. * @param obj template obj
  157. * @todo improve this function
  158. */
  159. function get_all_plugin_contents_by_region($_plugins, $region, $template, $forced = false)
  160. {
  161. if (isset($_plugins[$region]) && is_array($_plugins[$region])) {
  162. //if (1) {
  163. //Load the plugin information
  164. foreach ($_plugins[$region] as $plugin_name) {
  165. //The plugin_info variable is available inside the plugin index
  166. $plugin_info = $this->get_plugin_info($plugin_name, $forced);
  167. //We also know where the plugin is
  168. $plugin_info['current_region'] = $region;
  169. // Loading the plugin/XXX/index.php file
  170. $plugin_file = api_get_path(SYS_PLUGIN_PATH)."$plugin_name/index.php";
  171. if (file_exists($plugin_file)) {
  172. //Loading the lang variables of the plugin if exists
  173. self::load_plugin_lang_variables($plugin_name);
  174. //Printing the plugin index.php file
  175. require $plugin_file;
  176. //If the variable $_template is set we assign those values to be accesible in Twig
  177. if (isset($_template)) {
  178. $_template['plugin_info'] = $plugin_info;
  179. } else {
  180. $_template = array();
  181. $_template['plugin_info'] = $plugin_info;
  182. }
  183. //Setting the plugin info available in the template if exists
  184. $template->assign($plugin_name, $_template);
  185. //Loading the Twig template plugin files if exists
  186. $template_list = array();
  187. if (isset($plugin_info) && isset($plugin_info['templates'])) {
  188. $template_list = $plugin_info['templates'];
  189. }
  190. if (!empty($template_list)) {
  191. foreach ($template_list as $plugin_tpl) {
  192. if (!empty($plugin_tpl)) {
  193. //$template_plugin_file = api_get_path(SYS_PLUGIN_PATH)."$plugin_name/$plugin_tpl"; //for smarty
  194. $template_plugin_file = "$plugin_name/$plugin_tpl"; // for twig
  195. $template->display($template_plugin_file);
  196. }
  197. }
  198. }
  199. }
  200. }
  201. }
  202. return true;
  203. }
  204. /**
  205. * Loads plugin info
  206. * @staticvar array $plugin_data
  207. * @param string plugin name
  208. * @param bool load from DB or from the static array
  209. * @todo filter setting_form
  210. * @return array
  211. */
  212. function get_plugin_info($plugin_name, $forced = false) {
  213. static $plugin_data = array();
  214. if (isset($plugin_data[$plugin_name]) && $forced == false) {
  215. return $plugin_data[$plugin_name];
  216. } else {
  217. $plugin_file = api_get_path(SYS_PLUGIN_PATH)."$plugin_name/plugin.php";
  218. $plugin_info = array();
  219. if (file_exists($plugin_file)) {
  220. require $plugin_file;
  221. }
  222. //extra options
  223. $plugin_settings = api_get_settings_params(array("subkey = ? AND category = ? AND type = ? " =>
  224. array($plugin_name, 'Plugins','setting')));
  225. $settings_filtered = array();
  226. foreach ($plugin_settings as $item) {
  227. $settings_filtered[$item['variable']] = $item['selected_value'];
  228. }
  229. $plugin_info['settings'] = $settings_filtered;
  230. $plugin_data[$plugin_name] = $plugin_info;
  231. return $plugin_info;
  232. }
  233. }
  234. /*
  235. * Get the template list
  236. */
  237. function get_templates_list($plugin_name) {
  238. $plugin_info = $this->get_plugin_info($plugin_name);
  239. if (isset($plugin_info) && isset($plugin_info['templates'])) {
  240. return $plugin_info['templates'];
  241. } else {
  242. return false;
  243. }
  244. }
  245. /* *
  246. * Remove all regions of an specific plugin
  247. */
  248. function remove_all_regions($plugin) {
  249. $access_url_id = api_get_current_access_url_id();
  250. if (!empty($plugin)) {
  251. api_delete_settings_params(array('category = ? AND type = ? AND access_url = ? AND subkey = ? ' =>
  252. array('Plugins', 'region', $access_url_id, $plugin)));
  253. }
  254. }
  255. /*
  256. * Add a plugin to a region
  257. */
  258. function add_to_region($plugin, $region) {
  259. $access_url_id = api_get_current_access_url_id();
  260. api_add_setting($plugin, $region, $plugin, 'region', 'Plugins', $plugin, null, null, null, $access_url_id, 1);
  261. }
  262. function install_course_plugins($course_id) {
  263. $plugin_list = $this->get_installed_plugins();
  264. if (!empty($plugin_list)) {
  265. foreach ($plugin_list as $plugin_name) {
  266. $plugin_path = api_get_path(SYS_PLUGIN_PATH).$plugin_name.'/plugin.php';
  267. if (file_exists($plugin_path)) {
  268. require_once $plugin_path;
  269. if (isset($plugin_info) && isset($plugin_info['plugin_class'])) {
  270. $plugin_info['plugin_class']::create()->course_install($course_id);
  271. }
  272. }
  273. }
  274. }
  275. }
  276. function add_course_settings_form($form) {
  277. $plugin_list = $this->get_installed_plugins();
  278. foreach ($plugin_list as $plugin_name) {
  279. $plugin_info = $this->get_plugin_info($plugin_name);
  280. if (isset($plugin_info['plugin_class'])) {
  281. $obj = $plugin_info['plugin_class']::create();
  282. if (!empty($obj->course_settings)) {
  283. $icon = Display::return_icon($plugin_name.'.png', Security::remove_XSS($plugin_info['title']),'', ICON_SIZE_SMALL);
  284. //$icon = null;
  285. $form->addElement('html', '<div><h3>'.$icon.' '.Security::remove_XSS($plugin_info['title']).'</h3><div>');
  286. $groups = array();
  287. foreach ($obj->course_settings as $setting) {
  288. if ($setting['type'] != 'checkbox') {
  289. $form->addElement($setting['type'], $setting['name'], $obj->get_lang($setting['name']));
  290. } else {
  291. //if (isset($groups[$setting['group']])) {
  292. $element = & $form->createElement($setting['type'], $setting['name'], '', $obj->get_lang($setting['name']));
  293. if ($setting['init_value'] == 1) {
  294. $element->setChecked(true);
  295. }
  296. $groups[$setting['group']][] = $element;
  297. //}
  298. }
  299. }
  300. foreach ($groups as $k => $v) {
  301. $form->addGroup($groups[$k], $k, array($obj->get_lang($k)));
  302. }
  303. $form->addElement('style_submit_button', null, get_lang('SaveSettings'), 'class="save"');
  304. $form->addElement('html', '</div></div>');
  305. }
  306. }
  307. }
  308. }
  309. function set_course_settings_defaults(& $values) {
  310. $plugin_list = $this->get_installed_plugins();
  311. foreach ($plugin_list as $plugin_name) {
  312. $plugin_info = $this->get_plugin_info($plugin_name);
  313. if (isset($plugin_info['plugin_class'])) {
  314. $obj = $plugin_info['plugin_class']::create();
  315. if (!empty($obj->course_settings)) {
  316. foreach ($obj->course_settings as $setting) {
  317. if (isset($setting['name'])) {
  318. $result = api_get_course_setting($setting['name']);
  319. if ($result != '-1') {
  320. $values[$setting['name']] = $result;
  321. }
  322. }
  323. }
  324. }
  325. }
  326. }
  327. }
  328. /**
  329. * When saving the plugin values in the course settings, check whether
  330. * a callback method should be called and send it the updated settings
  331. * @param array The new settings the user just saved
  332. * @return void
  333. */
  334. function save_course_settings($values) {
  335. $plugin_list = $this->get_installed_plugins();
  336. foreach ($plugin_list as $plugin_name) {
  337. $settings = $this->get_plugin_course_settings($plugin_name);
  338. $subvalues = array();
  339. $i = 0;
  340. foreach ($settings as $v) {
  341. if (isset($values[$v])) {
  342. $subvalues[$v] = $values[$v];
  343. $i++;
  344. }
  345. }
  346. if ($i>0) {
  347. $plugin_info = $this->get_plugin_info($plugin_name);
  348. if (isset($plugin_info['plugin_class'])) {
  349. $obj = $plugin_info['plugin_class']::create();
  350. $obj->course_settings_updated($subvalues);
  351. }
  352. }
  353. }
  354. }
  355. /**
  356. * Gets a nice array of keys for just the plugin's course settings
  357. * @param string The plugin ID
  358. * @return array Nice array of keys for course settings
  359. */
  360. public function get_plugin_course_settings($plugin_name) {
  361. $settings = array();
  362. if (empty($plugin_name)) {
  363. return $settings;
  364. }
  365. $plugin_info = $this->get_plugin_info($plugin_name);
  366. if (isset($plugin_info['plugin_class'])) {
  367. $obj = $plugin_info['plugin_class']::create();
  368. if (is_array($obj->course_settings)) {
  369. foreach ($obj->course_settings as $item) {
  370. if (isset($item['group'])) {
  371. if (!in_array($item['group'],$settings)) {
  372. $settings[] = $item['group'];
  373. }
  374. } else {
  375. $settings[] = $item['name'];
  376. }
  377. }
  378. }
  379. unset($obj);
  380. unset($plugin_info);
  381. }
  382. return $settings;
  383. }
  384. }