plugin.class.php 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760
  1. <?php
  2. /* For licensing terms, see /license.txt */
  3. /**
  4. * Class Plugin
  5. * Base class for plugins
  6. *
  7. * This class has to be extended by every plugin. It defines basic methods
  8. * to install/uninstall and get information about a plugin
  9. *
  10. * @author Julio Montoya <gugli100@gmail.com>
  11. * @author Yannick Warnier <ywarnier@beeznest.org>
  12. * @author Laurent Opprecht <laurent@opprecht.info>
  13. * @copyright 2012 University of Geneva
  14. * @license GNU General Public License - http://www.gnu.org/copyleft/gpl.html
  15. *
  16. */
  17. class Plugin
  18. {
  19. protected $version = '';
  20. protected $author = '';
  21. protected $fields = array();
  22. private $settings = null;
  23. // Translation strings.
  24. private $strings = null;
  25. public $isCoursePlugin = false;
  26. public $isAdminPlugin = false;
  27. public $isMailPlugin = false;
  28. /**
  29. * When creating a new course, these settings are added to the course, in
  30. * the course_info/infocours.php
  31. * To show the plugin course icons you need to add these icons:
  32. * main/img/icons/22/plugin_name.png
  33. * main/img/icons/64/plugin_name.png
  34. * main/img/icons/64/plugin_name_na.png
  35. * @example
  36. * $course_settings = array(
  37. array('name' => 'big_blue_button_welcome_message', 'type' => 'text'),
  38. array('name' => 'big_blue_button_record_and_store', 'type' => 'checkbox')
  39. );
  40. */
  41. public $course_settings = array();
  42. /**
  43. * This indicates whether changing the setting should execute the callback
  44. * function.
  45. */
  46. public $course_settings_callback = false;
  47. /**
  48. * Default constructor for the plugin class. By default, it only sets
  49. * a few attributes of the object
  50. * @param string $version of this plugin
  51. * @param string $author of this plugin
  52. * @param array $settings settings to be proposed to configure the plugin
  53. */
  54. protected function __construct($version, $author, $settings = array())
  55. {
  56. $this->version = $version;
  57. $this->author = $author;
  58. $this->fields = $settings;
  59. global $language_files;
  60. $language_files[] = 'plugin_' . $this->get_name();
  61. }
  62. /**
  63. * Gets an array of information about this plugin (name, version, ...)
  64. * @return array Array of information elements about this plugin
  65. */
  66. public function get_info()
  67. {
  68. $result = array();
  69. $result['title'] = $this->get_title();
  70. $result['comment'] = $this->get_comment();
  71. $result['version'] = $this->get_version();
  72. $result['author'] = $this->get_author();
  73. $result['plugin_class'] = get_class($this);
  74. $result['is_course_plugin'] = $this->isCoursePlugin;
  75. $result['is_admin_plugin'] = $this->isAdminPlugin;
  76. $result['is_mail_plugin'] = $this->isMailPlugin;
  77. if ($form = $this->get_settings_form()) {
  78. $result['settings_form'] = $form;
  79. foreach ($this->fields as $name => $type) {
  80. $value = $this->get($name);
  81. if (is_array($type)) {
  82. $value = $type['options'];
  83. }
  84. $result[$name] = $value;
  85. }
  86. }
  87. return $result;
  88. }
  89. /**
  90. * Returns the "system" name of the plugin in lowercase letters
  91. * @return string
  92. */
  93. public function get_name()
  94. {
  95. $result = get_class($this);
  96. $result = str_replace('Plugin', '', $result);
  97. $result = strtolower($result);
  98. return $result;
  99. }
  100. /**
  101. * Returns the title of the plugin
  102. * @return string
  103. */
  104. public function get_title()
  105. {
  106. return $this->get_lang('plugin_title');
  107. }
  108. /**
  109. * Returns the description of the plugin
  110. * @return string
  111. */
  112. public function get_comment()
  113. {
  114. return $this->get_lang('plugin_comment');
  115. }
  116. /**
  117. * Returns the version of the plugin
  118. * @return string
  119. */
  120. public function get_version()
  121. {
  122. return $this->version;
  123. }
  124. /**
  125. * Returns the author of the plugin
  126. * @return string
  127. */
  128. public function get_author()
  129. {
  130. return $this->author;
  131. }
  132. /**
  133. * Returns the contents of the CSS defined by the plugin
  134. * @return array
  135. */
  136. public function get_css()
  137. {
  138. $name = $this->get_name();
  139. $path = api_get_path(SYS_PLUGIN_PATH)."$name/resources/$name.css";
  140. if (!is_readable($path)) {
  141. return '';
  142. }
  143. $css = array();
  144. $css[] = file_get_contents($path);
  145. $result = implode($css);
  146. return $result;
  147. }
  148. /**
  149. * Returns an HTML form (generated by FormValidator) of the plugin settings
  150. * @return string FormValidator-generated form
  151. */
  152. public function get_settings_form()
  153. {
  154. $result = new FormValidator($this->get_name());
  155. $defaults = array();
  156. $checkboxGroup = array();
  157. $checkboxCollection = array();
  158. if ($checkboxNames = array_keys($this->fields, 'checkbox')) {
  159. $pluginInfoCollection = api_get_settings('Plugins');
  160. foreach ($pluginInfoCollection as $pluginInfo) {
  161. if (array_search($pluginInfo['title'], $checkboxNames) !== false) {
  162. $checkboxCollection[$pluginInfo['title']] = $pluginInfo;
  163. }
  164. }
  165. }
  166. foreach ($this->fields as $name => $type) {
  167. $options = null;
  168. if (is_array($type) && isset($type['type']) && $type['type'] === "select") {
  169. $options = $type['options'];
  170. $type = $type['type'];
  171. }
  172. $value = $this->get($name);
  173. $defaults[$name] = $value;
  174. $type = isset($type) ? $type : 'text';
  175. $help = null;
  176. if ($this->get_lang_plugin_exists($name.'_help')) {
  177. $help = $this->get_lang($name.'_help');
  178. if ($name === "show_main_menu_tab") {
  179. $pluginName = strtolower(str_replace('Plugin', '', get_class($this)));
  180. $pluginUrl = api_get_path(WEB_PATH)."plugin/$pluginName/index.php";
  181. $pluginUrl = "<a href=$pluginUrl>$pluginUrl</a>";
  182. $help = sprintf($help, $pluginUrl);
  183. }
  184. }
  185. switch ($type) {
  186. case 'html':
  187. $result->addElement('html', $this->get_lang($name));
  188. break;
  189. case 'wysiwyg':
  190. $result->addHtmlEditor($name, $this->get_lang($name), false);
  191. break;
  192. case 'text':
  193. $result->addElement($type, $name, array($this->get_lang($name), $help));
  194. break;
  195. case 'boolean':
  196. $group = array();
  197. $group[] = $result->createElement('radio', $name, '', get_lang('Yes'), 'true');
  198. $group[] = $result->createElement('radio', $name, '', get_lang('No'), 'false');
  199. $result->addGroup($group, null, array($this->get_lang($name), $help));
  200. break;
  201. case 'checkbox':
  202. $selectedValue = null;
  203. if (isset($checkboxCollection[$name])) {
  204. if ($checkboxCollection[$name]['selected_value'] === 'true') {
  205. $selectedValue = 'checked';
  206. }
  207. }
  208. $element = $result->createElement(
  209. $type,
  210. $name,
  211. '',
  212. $this->get_lang($name),
  213. $selectedValue
  214. );
  215. $element->_attributes['value'] = 'true';
  216. $checkboxGroup[] = $element;
  217. break;
  218. case 'select':
  219. $result->addElement(
  220. $type,
  221. $name,
  222. array($this->get_lang($name), $help),
  223. $options
  224. );
  225. break;
  226. }
  227. }
  228. if (!empty($checkboxGroup)) {
  229. $result->addGroup($checkboxGroup, null, array($this->get_lang('sms_types'), $help));
  230. }
  231. $result->setDefaults($defaults);
  232. $result->addButtonSave($this->get_lang('Save'), 'submit_button');
  233. return $result;
  234. }
  235. /**
  236. * Returns the value of a given plugin global setting
  237. * @param string $name of the plugin
  238. *
  239. * @return string Value of the plugin
  240. */
  241. public function get($name)
  242. {
  243. $settings = $this->get_settings();
  244. foreach ($settings as $setting) {
  245. if ($setting['variable'] == ($this->get_name() . '_' . $name)) {
  246. return $setting['selected_value'];
  247. }
  248. }
  249. return false;
  250. }
  251. /**
  252. * Returns an array with the global settings for this plugin
  253. * @return array Plugin settings as an array
  254. */
  255. public function get_settings()
  256. {
  257. if (is_null($this->settings)) {
  258. $settings = api_get_settings_params(
  259. array(
  260. "subkey = ? AND category = ? AND type = ? " => array($this->get_name(), 'Plugins', 'setting')
  261. )
  262. );
  263. $this->settings = $settings;
  264. }
  265. return $this->settings;
  266. }
  267. /**
  268. * Tells whether language variables are defined for this plugin or not
  269. * @param string $name System name of the plugin
  270. *
  271. * @return bool True if the plugin has language variables defined, false otherwise
  272. */
  273. public function get_lang_plugin_exists($name)
  274. {
  275. return isset($this->strings[$name]);
  276. }
  277. /**
  278. * Hook for the get_lang() function to check for plugin-defined language terms
  279. * @param string $name of the language variable we are looking for
  280. *
  281. * @return string The translated language term of the plugin
  282. */
  283. public function get_lang($name)
  284. {
  285. // Check whether the language strings for the plugin have already been
  286. // loaded. If so, no need to load them again.
  287. if (is_null($this->strings)) {
  288. global $language_interface;
  289. $root = api_get_path(SYS_PLUGIN_PATH);
  290. $plugin_name = $this->get_name();
  291. $interfaceLanguageId = api_get_language_id($language_interface);
  292. $interfaceLanguageInfo = api_get_language_info($interfaceLanguageId);
  293. $languageParentId = (!empty($interfaceLanguageInfo['parent_id'])?intval($interfaceLanguageInfo['parent_id']):0);
  294. //1. Loading english if exists
  295. $english_path = $root.$plugin_name."/lang/english.php";
  296. if (is_readable($english_path)) {
  297. $strings = array();
  298. include $english_path;
  299. $this->strings = $strings;
  300. }
  301. $path = $root.$plugin_name."/lang/$language_interface.php";
  302. //2. Loading the system language
  303. if (is_readable($path)) {
  304. include $path;
  305. if (!empty($strings)) {
  306. foreach ($strings as $key => $string) {
  307. $this->strings[$key] = $string;
  308. }
  309. }
  310. } elseif ($languageParentId > 0) {
  311. $languageParentInfo = api_get_language_info($languageParentId);
  312. $languageParentFolder = $languageParentInfo['dokeos_folder'];
  313. $parentPath = "{$root}{$plugin_name}/lang/{$languageParentFolder}.php";
  314. if (is_readable($parentPath)) {
  315. include $parentPath;
  316. if (!empty($strings)) {
  317. foreach ($strings as $key => $string) {
  318. $this->strings[$key] = $string;
  319. }
  320. }
  321. }
  322. }
  323. }
  324. if (isset($this->strings[$name])) {
  325. return $this->strings[$name];
  326. }
  327. return get_lang($name);
  328. }
  329. /**
  330. * Caller for the install_course_fields() function
  331. * @param int $courseId
  332. *
  333. * @param boolean $addToolLink Whether to add a tool link on the course homepage
  334. *
  335. * @return void
  336. */
  337. public function course_install($courseId, $addToolLink = true)
  338. {
  339. $this->install_course_fields($courseId, $addToolLink);
  340. }
  341. /**
  342. * Add course settings and, if not asked otherwise, add a tool link on the course homepage
  343. * @param int $courseId Course integer ID
  344. * @param boolean $add_tool_link Whether to add a tool link or not
  345. * (some tools might just offer a configuration section and act on the backend)
  346. *
  347. * @return boolean False on error, null otherwise
  348. */
  349. public function install_course_fields($courseId, $add_tool_link = true)
  350. {
  351. $plugin_name = $this->get_name();
  352. $t_course = Database::get_course_table(TABLE_COURSE_SETTING);
  353. $courseId = intval($courseId);
  354. if (empty($courseId)) {
  355. return false;
  356. }
  357. // Adding course settings.
  358. if (!empty($this->course_settings)) {
  359. foreach ($this->course_settings as $setting) {
  360. $variable = $setting['name'];
  361. $value ='';
  362. if (isset($setting['init_value'])) {
  363. $value = ($setting['init_value']);
  364. }
  365. $type = 'textfield';
  366. if (isset($setting['type'])) {
  367. $type = $setting['type'];
  368. }
  369. if (isset($setting['group'])) {
  370. $group = $setting['group'];
  371. $sql = "SELECT value
  372. FROM $t_course
  373. WHERE
  374. c_id = $courseId AND
  375. variable = '".Database::escape_string($group)."' AND
  376. subkey = '".Database::escape_string($variable)."'
  377. ";
  378. $result = Database::query($sql);
  379. if (!Database::num_rows($result)) {
  380. $params = [
  381. 'c_id' => $courseId,
  382. 'variable' => $group,
  383. 'subkey' => $variable,
  384. 'value' => $value,
  385. 'category' => 'plugins',
  386. 'type' => $type
  387. ];
  388. Database::insert($t_course, $params);
  389. }
  390. } else {
  391. $sql = "SELECT value FROM $t_course
  392. WHERE c_id = $courseId AND variable = '$variable' ";
  393. $result = Database::query($sql);
  394. if (!Database::num_rows($result)) {
  395. $params = [
  396. 'c_id' => $courseId,
  397. 'variable' => $variable,
  398. 'subkey' => $plugin_name,
  399. 'value' => $value,
  400. 'category' => 'plugins',
  401. 'type' => $type
  402. ];
  403. Database::insert($t_course, $params);
  404. }
  405. }
  406. }
  407. }
  408. // Stop here if we don't want a tool link on the course homepage
  409. if (!$add_tool_link) {
  410. return true;
  411. }
  412. //Add an icon in the table tool list
  413. $table = Database::get_course_table(TABLE_TOOL_LIST);
  414. $sql = "SELECT name FROM $table
  415. WHERE c_id = $courseId AND name = '$plugin_name' ";
  416. $result = Database::query($sql);
  417. if (!Database::num_rows($result)) {
  418. $tool_link = "$plugin_name/start.php";
  419. //$visibility = AddCourse::string2binary(api_get_setting('course_create_active_tools', $plugin_name));
  420. $cToolId = AddCourse::generateToolId($courseId);
  421. Database::insert(
  422. $table,
  423. [
  424. 'id' => $cToolId,
  425. 'c_id' => $courseId,
  426. 'name' => $plugin_name,
  427. 'link' => $tool_link,
  428. 'image' => "$plugin_name.png",
  429. 'visibility' => 1,
  430. 'admin' => 0,
  431. 'address' => 'squaregrey.gif',
  432. 'added_tool' => 'NO',
  433. 'target' => '_self',
  434. 'category' => 'plugin',
  435. 'session_id' => 0
  436. ]
  437. );
  438. }
  439. }
  440. /**
  441. * Delete the fields added to the course settings page and the link to the
  442. * tool on the course's homepage
  443. * @param int $courseId
  444. *
  445. * @return void
  446. */
  447. public function uninstall_course_fields($courseId)
  448. {
  449. $courseId = intval($courseId);
  450. if (empty($courseId)) {
  451. return false;
  452. }
  453. $plugin_name = $this->get_name();
  454. $t_course = Database::get_course_table(TABLE_COURSE_SETTING);
  455. $t_tool = Database::get_course_table(TABLE_TOOL_LIST);
  456. if (!empty($this->course_settings)) {
  457. foreach ($this->course_settings as $setting) {
  458. $variable = Database::escape_string($setting['name']);
  459. if (!empty($setting['group'])) {
  460. $variable = Database::escape_string($setting['group']);
  461. }
  462. if (empty($variable)) {
  463. continue;
  464. }
  465. $sql = "DELETE FROM $t_course
  466. WHERE c_id = $courseId AND variable = '$variable'";
  467. Database::query($sql);
  468. }
  469. }
  470. $plugin_name = Database::escape_string($plugin_name);
  471. $sql = "DELETE FROM $t_tool
  472. WHERE c_id = $courseId AND name = '$plugin_name'";
  473. Database::query($sql);
  474. }
  475. /**
  476. * Install the course fields and tool link of this plugin in all courses
  477. * @param boolean Whether we want to add a plugin link on the course homepage
  478. *
  479. * @return void
  480. */
  481. public function install_course_fields_in_all_courses($add_tool_link = true)
  482. {
  483. // Update existing courses to add plugin settings
  484. $t_courses = Database::get_main_table(TABLE_MAIN_COURSE);
  485. $sql = "SELECT id FROM $t_courses ORDER BY id";
  486. $res = Database::query($sql);
  487. while ($row = Database::fetch_assoc($res)) {
  488. $this->install_course_fields($row['id'], $add_tool_link);
  489. }
  490. }
  491. /**
  492. * Uninstall the plugin settings fields from all courses
  493. * @return void
  494. */
  495. public function uninstall_course_fields_in_all_courses()
  496. {
  497. // Update existing courses to add conference settings
  498. $t_courses = Database::get_main_table(TABLE_MAIN_COURSE);
  499. $sql = "SELECT id FROM $t_courses
  500. ORDER BY id";
  501. $res = Database::query($sql);
  502. while ($row = Database::fetch_assoc($res)) {
  503. $this->uninstall_course_fields($row['id']);
  504. }
  505. }
  506. /**
  507. * @return array
  508. */
  509. public function getCourseSettings()
  510. {
  511. $settings = array();
  512. if (is_array($this->course_settings)) {
  513. foreach ($this->course_settings as $item) {
  514. if (isset($item['group'])) {
  515. if (!in_array($item['group'], $settings)) {
  516. $settings[] = $item['group'];
  517. }
  518. } else {
  519. $settings[] = $item['name'];
  520. }
  521. }
  522. }
  523. return $settings;
  524. }
  525. /**
  526. * Method to be extended when changing the setting in the course
  527. * configuration should trigger the use of a callback method
  528. * @param array $values sent back from the course configuration script
  529. *
  530. * @return void
  531. */
  532. public function course_settings_updated($values = array())
  533. {
  534. }
  535. /**
  536. * Add a tab to platform
  537. * @param string $tabName
  538. * @param string $url
  539. *
  540. * @return boolean
  541. */
  542. public function addTab($tabName, $url)
  543. {
  544. $sql = "SELECT * FROM settings_current
  545. WHERE
  546. variable = 'show_tabs' AND
  547. subkey LIKE 'custom_tab_%'";
  548. $result = Database::query($sql);
  549. $customTabsNum = Database::num_rows($result);
  550. $tabNum = $customTabsNum + 1;
  551. //Avoid Tab Name Spaces
  552. $tabNameNoSpaces = preg_replace('/\s+/', '', $tabName);
  553. $subkeytext = "Tabs" . $tabNameNoSpaces;
  554. //Check if it is already added
  555. $checkCondition = array(
  556. 'where' =>
  557. array(
  558. "variable = 'show_tabs' AND subkeytext = ?" => array(
  559. $subkeytext
  560. )
  561. )
  562. );
  563. $checkDuplicate = Database::select('*', 'settings_current', $checkCondition);
  564. if (!empty($checkDuplicate)) {
  565. return false;
  566. }
  567. //End Check
  568. $subkey = 'custom_tab_' . $tabNum;
  569. $attributes = array(
  570. 'variable' => 'show_tabs',
  571. 'subkey' => $subkey,
  572. 'type' => 'checkbox',
  573. 'category' => 'Platform',
  574. 'selected_value' => 'true',
  575. 'title' => $tabName,
  576. 'comment' => $url,
  577. 'subkeytext' => $subkeytext,
  578. 'access_url' => 1,
  579. 'access_url_changeable' => 0,
  580. 'access_url_locked' => 0
  581. );
  582. $resp = Database::insert('settings_current', $attributes);
  583. //Save the id
  584. $settings = $this->get_settings();
  585. $setData = array (
  586. 'comment' => $subkey
  587. );
  588. $whereCondition = array(
  589. 'id = ?' => key($settings)
  590. );
  591. Database::update('settings_current', $setData, $whereCondition);
  592. return $resp;
  593. }
  594. /**
  595. * Delete a tab to chamilo's platform
  596. * @param string $key
  597. * @return boolean $resp Transaction response
  598. */
  599. public function deleteTab($key)
  600. {
  601. $t = Database::get_main_table(TABLE_MAIN_SETTINGS_CURRENT);
  602. $sql = "SELECT *
  603. FROM $t
  604. WHERE variable = 'show_tabs'
  605. AND subkey <> '$key'
  606. AND subkey like 'custom_tab_%'
  607. ";
  608. $resp = $result = Database::query($sql);
  609. $customTabsNum = Database::num_rows($result);
  610. if (!empty($key)) {
  611. $whereCondition = array(
  612. 'variable = ? AND subkey = ?' => array('show_tabs', $key)
  613. );
  614. $resp = Database::delete('settings_current', $whereCondition);
  615. //if there is more than one tab
  616. //re enumerate them
  617. if (!empty($customTabsNum) && $customTabsNum > 0) {
  618. $tabs = Database::store_result($result, 'ASSOC');
  619. $i = 1;
  620. foreach ($tabs as $row) {
  621. $attributes = array(
  622. 'subkey' => 'custom_tab_' . $i
  623. );
  624. $this->updateTab($row['subkey'], $attributes);
  625. $i++;
  626. }
  627. }
  628. }
  629. return $resp;
  630. }
  631. /**
  632. * Update the tabs attributes
  633. * @param string $key
  634. * @param array $attributes
  635. *
  636. * @return boolean
  637. */
  638. public function updateTab($key, $attributes)
  639. {
  640. $whereCondition = array(
  641. 'variable = ? AND subkey = ?' => array('show_tabs', $key)
  642. );
  643. $resp = Database::update('settings_current', $attributes, $whereCondition);
  644. return $resp;
  645. }
  646. /**
  647. * This method shows or hides plugin's tab
  648. * @param boolean $showTab Shows or hides the main menu plugin tab
  649. * @param string $filePath Plugin starter file path
  650. */
  651. public function manageTab($showTab, $filePath = 'index.php')
  652. {
  653. $langString = str_replace('Plugin', '', get_class($this));
  654. $pluginName = strtolower($langString);
  655. $pluginUrl = 'plugin/'.$pluginName.'/'.$filePath;
  656. if ($showTab === 'true') {
  657. $tabAdded = $this->addTab($langString, $pluginUrl);
  658. if ($tabAdded) {
  659. // The page must be refreshed to show the recently created tab
  660. echo "<script>location.href = '".Security::remove_XSS($_SERVER['REQUEST_URI'])."';</script>";
  661. }
  662. } else {
  663. $settingsCurrentTable = Database::get_main_table(TABLE_MAIN_SETTINGS_CURRENT);
  664. $conditions = array(
  665. 'where' => array(
  666. "variable = 'show_tabs' AND title = ? AND comment = ? " => array(
  667. $langString,
  668. $pluginUrl
  669. )
  670. )
  671. );
  672. $result = Database::select('subkey', $settingsCurrentTable, $conditions);
  673. if (!empty($result)) {
  674. $this->deleteTab($result[0]['subkey']);
  675. }
  676. }
  677. }
  678. /**
  679. * @param string $variable
  680. * @return bool
  681. */
  682. public function validateCourseSetting($variable)
  683. {
  684. return true;
  685. }
  686. }