plugin.class.php 31 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024
  1. <?php
  2. /* For licensing terms, see /license.txt */
  3. use Chamilo\CourseBundle\Entity\CTool;
  4. /**
  5. * Class Plugin
  6. * Base class for plugins.
  7. *
  8. * This class has to be extended by every plugin. It defines basic methods
  9. * to install/uninstall and get information about a plugin
  10. *
  11. * @author Julio Montoya <gugli100@gmail.com>
  12. * @author Yannick Warnier <ywarnier@beeznest.org>
  13. * @author Laurent Opprecht <laurent@opprecht.info>
  14. * @copyright 2012 University of Geneva
  15. * @license GNU General Public License - http://www.gnu.org/copyleft/gpl.html
  16. */
  17. class Plugin
  18. {
  19. const TAB_FILTER_NO_STUDENT = '::no-student';
  20. const TAB_FILTER_ONLY_STUDENT = '::only-student';
  21. public $isCoursePlugin = false;
  22. public $isAdminPlugin = false;
  23. public $isMailPlugin = false;
  24. // Adds icon in the course home
  25. public $addCourseTool = true;
  26. public $hasPersonalEvents = false;
  27. /**
  28. * When creating a new course, these settings are added to the course, in
  29. * the course_info/infocours.php
  30. * To show the plugin course icons you need to add these icons:
  31. * main/img/icons/22/plugin_name.png
  32. * main/img/icons/64/plugin_name.png
  33. * main/img/icons/64/plugin_name_na.png.
  34. *
  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 = [];
  42. /**
  43. * This indicates whether changing the setting should execute the callback
  44. * function.
  45. */
  46. public $course_settings_callback = false;
  47. protected $version = '';
  48. protected $author = '';
  49. protected $fields = [];
  50. private $settings = [];
  51. // Translation strings.
  52. private $strings = null;
  53. /**
  54. * Default constructor for the plugin class. By default, it only sets
  55. * a few attributes of the object.
  56. *
  57. * @param string $version of this plugin
  58. * @param string $author of this plugin
  59. * @param array $settings settings to be proposed to configure the plugin
  60. */
  61. protected function __construct($version, $author, $settings = [])
  62. {
  63. $this->version = $version;
  64. $this->author = $author;
  65. $this->fields = $settings;
  66. global $language_files;
  67. $language_files[] = 'plugin_'.$this->get_name();
  68. }
  69. /**
  70. * Gets an array of information about this plugin (name, version, ...).
  71. *
  72. * @return array Array of information elements about this plugin
  73. */
  74. public function get_info()
  75. {
  76. $result = [];
  77. $result['obj'] = $this;
  78. $result['title'] = $this->get_title();
  79. $result['comment'] = $this->get_comment();
  80. $result['version'] = $this->get_version();
  81. $result['author'] = $this->get_author();
  82. $result['plugin_class'] = get_class($this);
  83. $result['is_course_plugin'] = $this->isCoursePlugin;
  84. $result['is_admin_plugin'] = $this->isAdminPlugin;
  85. $result['is_mail_plugin'] = $this->isMailPlugin;
  86. if ($form = $this->getSettingsForm()) {
  87. $result['settings_form'] = $form;
  88. foreach ($this->fields as $name => $type) {
  89. $value = $this->get($name);
  90. if (is_array($type)) {
  91. $value = $type['options'];
  92. }
  93. $result[$name] = $value;
  94. }
  95. }
  96. return $result;
  97. }
  98. /**
  99. * Returns the "system" name of the plugin in lowercase letters.
  100. *
  101. * @return string
  102. */
  103. public function get_name()
  104. {
  105. $result = get_class($this);
  106. $result = str_replace('Plugin', '', $result);
  107. $result = strtolower($result);
  108. return $result;
  109. }
  110. /**
  111. * @return string
  112. */
  113. public function getCamelCaseName()
  114. {
  115. $result = get_class($this);
  116. return str_replace('Plugin', '', $result);
  117. }
  118. /**
  119. * Returns the title of the plugin.
  120. *
  121. * @return string
  122. */
  123. public function get_title()
  124. {
  125. return $this->get_lang('plugin_title');
  126. }
  127. /**
  128. * Returns the description of the plugin.
  129. *
  130. * @return string
  131. */
  132. public function get_comment()
  133. {
  134. return $this->get_lang('plugin_comment');
  135. }
  136. /**
  137. * Returns the version of the plugin.
  138. *
  139. * @return string
  140. */
  141. public function get_version()
  142. {
  143. return $this->version;
  144. }
  145. /**
  146. * Returns the author of the plugin.
  147. *
  148. * @return string
  149. */
  150. public function get_author()
  151. {
  152. return $this->author;
  153. }
  154. /**
  155. * Returns the contents of the CSS defined by the plugin.
  156. *
  157. * @return string
  158. */
  159. public function get_css()
  160. {
  161. $name = $this->get_name();
  162. $path = api_get_path(SYS_PLUGIN_PATH)."$name/resources/$name.css";
  163. if (!is_readable($path)) {
  164. return '';
  165. }
  166. $css = [];
  167. $css[] = file_get_contents($path);
  168. $result = implode($css);
  169. return $result;
  170. }
  171. /**
  172. * Returns an HTML form (generated by FormValidator) of the plugin settings.
  173. *
  174. * @return FormValidator FormValidator-generated form
  175. */
  176. public function getSettingsForm()
  177. {
  178. $result = new FormValidator($this->get_name());
  179. $defaults = [];
  180. $checkboxGroup = [];
  181. $checkboxCollection = [];
  182. if ($checkboxNames = array_keys($this->fields, 'checkbox')) {
  183. $pluginInfoCollection = api_get_settings('Plugins');
  184. foreach ($pluginInfoCollection as $pluginInfo) {
  185. if (array_search($pluginInfo['title'], $checkboxNames) !== false) {
  186. $checkboxCollection[$pluginInfo['title']] = $pluginInfo;
  187. }
  188. }
  189. }
  190. foreach ($this->fields as $name => $type) {
  191. $options = null;
  192. if (is_array($type) && isset($type['type']) && $type['type'] === 'select') {
  193. $attributes = isset($type['attributes']) ? $type['attributes'] : [];
  194. if (!empty($type['options']) && isset($type['translate_options']) && $type['translate_options']) {
  195. foreach ($type['options'] as $key => &$optionName) {
  196. $optionName = $this->get_lang($optionName);
  197. }
  198. }
  199. $options = $type['options'];
  200. $type = $type['type'];
  201. }
  202. $value = $this->get($name);
  203. $defaults[$name] = $value;
  204. $type = isset($type) ? $type : 'text';
  205. $help = null;
  206. if ($this->get_lang_plugin_exists($name.'_help')) {
  207. $help = $this->get_lang($name.'_help');
  208. if ($name === "show_main_menu_tab") {
  209. $pluginName = strtolower(str_replace('Plugin', '', get_class($this)));
  210. $pluginUrl = api_get_path(WEB_PATH)."plugin/$pluginName/index.php";
  211. $pluginUrl = "<a href=$pluginUrl>$pluginUrl</a>";
  212. $help = sprintf($help, $pluginUrl);
  213. }
  214. }
  215. switch ($type) {
  216. case 'html':
  217. $result->addHtml($this->get_lang($name));
  218. break;
  219. case 'wysiwyg':
  220. $result->addHtmlEditor($name, $this->get_lang($name), false);
  221. break;
  222. case 'text':
  223. $result->addElement($type, $name, [$this->get_lang($name), $help]);
  224. break;
  225. case 'boolean':
  226. $group = [];
  227. $group[] = $result->createElement(
  228. 'radio',
  229. $name,
  230. '',
  231. get_lang('Yes'),
  232. 'true'
  233. );
  234. $group[] = $result->createElement(
  235. 'radio',
  236. $name,
  237. '',
  238. get_lang('No'),
  239. 'false'
  240. );
  241. $result->addGroup($group, null, [$this->get_lang($name), $help]);
  242. break;
  243. case 'checkbox':
  244. $selectedValue = null;
  245. if (isset($checkboxCollection[$name])) {
  246. if ($checkboxCollection[$name]['selected_value'] === 'true') {
  247. $selectedValue = 'checked';
  248. }
  249. }
  250. $element = $result->createElement(
  251. $type,
  252. $name,
  253. '',
  254. $this->get_lang($name),
  255. $selectedValue
  256. );
  257. $element->_attributes['value'] = 'true';
  258. $checkboxGroup[] = $element;
  259. break;
  260. case 'select':
  261. $result->addElement(
  262. $type,
  263. $name,
  264. [$this->get_lang($name), $help],
  265. $options,
  266. $attributes
  267. );
  268. break;
  269. }
  270. }
  271. if (!empty($checkboxGroup)) {
  272. $result->addGroup(
  273. $checkboxGroup,
  274. null,
  275. [$this->get_lang('sms_types'), $help]
  276. );
  277. }
  278. $result->setDefaults($defaults);
  279. $result->addButtonSave($this->get_lang('Save'), 'submit_button');
  280. return $result;
  281. }
  282. /**
  283. * Returns the value of a given plugin global setting.
  284. *
  285. * @param string $name of the plugin
  286. *
  287. * @return string Value of the plugin
  288. */
  289. public function get($name)
  290. {
  291. $settings = $this->get_settings();
  292. foreach ($settings as $setting) {
  293. if ($setting['variable'] == $this->get_name().'_'.$name) {
  294. $unserialized = UnserializeApi::unserialize('not_allowed_classes', $setting['selected_value'], true);
  295. if (!empty($setting['selected_value']) &&
  296. false !== $unserialized
  297. ) {
  298. $setting['selected_value'] = $unserialized;
  299. }
  300. return $setting['selected_value'];
  301. }
  302. }
  303. return false;
  304. }
  305. /**
  306. * Returns an array with the global settings for this plugin.
  307. *
  308. * @param bool $forceFromDB Optional. Force get settings from the database
  309. *
  310. * @return array Plugin settings as an array
  311. */
  312. public function get_settings($forceFromDB = false)
  313. {
  314. if (empty($this->settings) || $forceFromDB) {
  315. $settings = api_get_settings_params(
  316. [
  317. "subkey = ? AND category = ? AND type = ? AND access_url = ?" => [
  318. $this->get_name(),
  319. 'Plugins',
  320. 'setting',
  321. api_get_current_access_url_id(),
  322. ],
  323. ]
  324. );
  325. $this->settings = $settings;
  326. }
  327. return $this->settings;
  328. }
  329. /**
  330. * Tells whether language variables are defined for this plugin or not.
  331. *
  332. * @param string $name System name of the plugin
  333. *
  334. * @return bool True if the plugin has language variables defined, false otherwise
  335. */
  336. public function get_lang_plugin_exists($name)
  337. {
  338. return isset($this->strings[$name]);
  339. }
  340. /**
  341. * Hook for the get_lang() function to check for plugin-defined language terms.
  342. *
  343. * @param string $name of the language variable we are looking for
  344. *
  345. * @return string The translated language term of the plugin
  346. */
  347. public function get_lang($name)
  348. {
  349. // Check whether the language strings for the plugin have already been
  350. // loaded. If so, no need to load them again.
  351. if (is_null($this->strings)) {
  352. $language_interface = api_get_interface_language();
  353. $root = api_get_path(SYS_PLUGIN_PATH);
  354. $plugin_name = $this->get_name();
  355. $interfaceLanguageId = api_get_language_id($language_interface);
  356. if (empty($interfaceLanguageId)) {
  357. $language_interface = api_get_setting('platformLanguage');
  358. $interfaceLanguageId = api_get_language_id($language_interface);
  359. }
  360. $interfaceLanguageInfo = api_get_language_info($interfaceLanguageId);
  361. $languageParentId = !empty($interfaceLanguageInfo['parent_id']) ? (int) $interfaceLanguageInfo['parent_id'] : 0;
  362. // 1. Loading english if exists
  363. $english_path = $root.$plugin_name."/lang/english.php";
  364. if (is_readable($english_path)) {
  365. $strings = [];
  366. include $english_path;
  367. $this->strings = $strings;
  368. }
  369. $path = $root.$plugin_name."/lang/$language_interface.php";
  370. // 2. Loading the system language
  371. if (is_readable($path)) {
  372. include $path;
  373. if (!empty($strings)) {
  374. foreach ($strings as $key => $string) {
  375. $this->strings[$key] = $string;
  376. }
  377. }
  378. } elseif ($languageParentId > 0) {
  379. $languageParentInfo = api_get_language_info($languageParentId);
  380. $languageParentFolder = $languageParentInfo['dokeos_folder'];
  381. $parentPath = "{$root}{$plugin_name}/lang/{$languageParentFolder}.php";
  382. if (is_readable($parentPath)) {
  383. include $parentPath;
  384. if (!empty($strings)) {
  385. foreach ($strings as $key => $string) {
  386. $this->strings[$key] = $string;
  387. }
  388. }
  389. }
  390. }
  391. }
  392. if (isset($this->strings[$name])) {
  393. return $this->strings[$name];
  394. }
  395. return get_lang($name);
  396. }
  397. /**
  398. * Caller for the install_course_fields() function.
  399. *
  400. * @param int $courseId
  401. * @param bool $addToolLink Whether to add a tool link on the course homepage
  402. */
  403. public function course_install($courseId, $addToolLink = true)
  404. {
  405. $this->install_course_fields($courseId, $addToolLink);
  406. }
  407. /**
  408. * Add course settings and, if not asked otherwise, add a tool link on the course homepage.
  409. *
  410. * @param int $courseId Course integer ID
  411. * @param bool $add_tool_link Whether to add a tool link or not
  412. * (some tools might just offer a configuration section and act on the backend)
  413. *
  414. * @return bool|null False on error, null otherwise
  415. */
  416. public function install_course_fields($courseId, $add_tool_link = true)
  417. {
  418. $plugin_name = $this->get_name();
  419. $t_course = Database::get_course_table(TABLE_COURSE_SETTING);
  420. $courseId = (int) $courseId;
  421. if (empty($courseId)) {
  422. return false;
  423. }
  424. // Adding course settings.
  425. if (!empty($this->course_settings)) {
  426. foreach ($this->course_settings as $setting) {
  427. $variable = $setting['name'];
  428. $value = '';
  429. if (isset($setting['init_value'])) {
  430. $value = $setting['init_value'];
  431. }
  432. $type = 'textfield';
  433. if (isset($setting['type'])) {
  434. $type = $setting['type'];
  435. }
  436. if (isset($setting['group'])) {
  437. $group = $setting['group'];
  438. $sql = "SELECT value
  439. FROM $t_course
  440. WHERE
  441. c_id = $courseId AND
  442. variable = '".Database::escape_string($group)."' AND
  443. subkey = '".Database::escape_string($variable)."'
  444. ";
  445. $result = Database::query($sql);
  446. if (!Database::num_rows($result)) {
  447. $params = [
  448. 'c_id' => $courseId,
  449. 'variable' => $group,
  450. 'subkey' => $variable,
  451. 'value' => $value,
  452. 'category' => 'plugins',
  453. 'type' => $type,
  454. 'title' => '',
  455. ];
  456. Database::insert($t_course, $params);
  457. }
  458. } else {
  459. $sql = "SELECT value FROM $t_course
  460. WHERE c_id = $courseId AND variable = '$variable' ";
  461. $result = Database::query($sql);
  462. if (!Database::num_rows($result)) {
  463. $params = [
  464. 'c_id' => $courseId,
  465. 'variable' => $variable,
  466. 'subkey' => $plugin_name,
  467. 'value' => $value,
  468. 'category' => 'plugins',
  469. 'type' => $type,
  470. 'title' => '',
  471. ];
  472. Database::insert($t_course, $params);
  473. }
  474. }
  475. }
  476. }
  477. // Stop here if we don't want a tool link on the course homepage
  478. if (!$add_tool_link || $this->addCourseTool == false) {
  479. return true;
  480. }
  481. // Add an icon in the table tool list
  482. $this->createLinkToCourseTool($plugin_name, $courseId);
  483. }
  484. /**
  485. * Delete the fields added to the course settings page and the link to the
  486. * tool on the course's homepage.
  487. *
  488. * @param int $courseId
  489. *
  490. * @return false|null
  491. */
  492. public function uninstall_course_fields($courseId)
  493. {
  494. $courseId = (int) $courseId;
  495. if (empty($courseId)) {
  496. return false;
  497. }
  498. $pluginName = $this->get_name();
  499. $t_course = Database::get_course_table(TABLE_COURSE_SETTING);
  500. $t_tool = Database::get_course_table(TABLE_TOOL_LIST);
  501. if (!empty($this->course_settings)) {
  502. foreach ($this->course_settings as $setting) {
  503. $variable = Database::escape_string($setting['name']);
  504. if (!empty($setting['group'])) {
  505. $variable = Database::escape_string($setting['group']);
  506. }
  507. if (empty($variable)) {
  508. continue;
  509. }
  510. $sql = "DELETE FROM $t_course
  511. WHERE c_id = $courseId AND variable = '$variable'";
  512. Database::query($sql);
  513. }
  514. }
  515. $pluginName = Database::escape_string($pluginName);
  516. $sql = "DELETE FROM $t_tool
  517. WHERE c_id = $courseId AND
  518. (
  519. name = '$pluginName' OR
  520. name = '$pluginName:student' OR
  521. name = '$pluginName:teacher'
  522. )";
  523. Database::query($sql);
  524. }
  525. /**
  526. * Install the course fields and tool link of this plugin in all courses.
  527. *
  528. * @param bool $add_tool_link Whether we want to add a plugin link on the course homepage
  529. */
  530. public function install_course_fields_in_all_courses($add_tool_link = true)
  531. {
  532. // Update existing courses to add plugin settings
  533. $table = Database::get_main_table(TABLE_MAIN_COURSE);
  534. $sql = "SELECT id FROM $table ORDER BY id";
  535. $res = Database::query($sql);
  536. while ($row = Database::fetch_assoc($res)) {
  537. $this->install_course_fields($row['id'], $add_tool_link);
  538. }
  539. }
  540. /**
  541. * Uninstall the plugin settings fields from all courses.
  542. */
  543. public function uninstall_course_fields_in_all_courses()
  544. {
  545. // Update existing courses to add conference settings
  546. $table = Database::get_main_table(TABLE_MAIN_COURSE);
  547. $sql = "SELECT id FROM $table
  548. ORDER BY id";
  549. $res = Database::query($sql);
  550. while ($row = Database::fetch_assoc($res)) {
  551. $this->uninstall_course_fields($row['id']);
  552. }
  553. }
  554. /**
  555. * @return array
  556. */
  557. public function getCourseSettings()
  558. {
  559. $settings = [];
  560. if (is_array($this->course_settings)) {
  561. foreach ($this->course_settings as $item) {
  562. if (isset($item['group'])) {
  563. if (!in_array($item['group'], $settings)) {
  564. $settings[] = $item['group'];
  565. }
  566. } else {
  567. $settings[] = $item['name'];
  568. }
  569. }
  570. }
  571. return $settings;
  572. }
  573. /**
  574. * Method to be extended when changing the setting in the course
  575. * configuration should trigger the use of a callback method.
  576. *
  577. * @param array $values sent back from the course configuration script
  578. */
  579. public function course_settings_updated($values = [])
  580. {
  581. }
  582. /**
  583. * Add a tab to platform.
  584. *
  585. * @param string $tabName
  586. * @param string $url
  587. * @param string $userFilter Optional. Filter tab type
  588. *
  589. * @return false|string
  590. */
  591. public function addTab($tabName, $url, $userFilter = null)
  592. {
  593. $sql = "SELECT * FROM settings_current
  594. WHERE
  595. variable = 'show_tabs' AND
  596. subkey LIKE 'custom_tab_%'";
  597. $result = Database::query($sql);
  598. $customTabsNum = Database::num_rows($result);
  599. $tabNum = $customTabsNum + 1;
  600. // Avoid Tab Name Spaces
  601. $tabNameNoSpaces = preg_replace('/\s+/', '', $tabName);
  602. $subkeytext = "Tabs".$tabNameNoSpaces;
  603. // Check if it is already added
  604. $checkCondition = [
  605. 'where' => [
  606. "variable = 'show_tabs' AND subkeytext = ?" => [
  607. $subkeytext,
  608. ],
  609. ],
  610. ];
  611. $checkDuplicate = Database::select('*', 'settings_current', $checkCondition);
  612. if (!empty($checkDuplicate)) {
  613. return false;
  614. }
  615. // End Check
  616. $subkey = 'custom_tab_'.$tabNum;
  617. if (!empty($userFilter)) {
  618. switch ($userFilter) {
  619. case self::TAB_FILTER_NO_STUDENT:
  620. case self::TAB_FILTER_ONLY_STUDENT:
  621. $subkey .= $userFilter;
  622. break;
  623. }
  624. }
  625. $currentUrlId = api_get_current_access_url_id();
  626. $attributes = [
  627. 'variable' => 'show_tabs',
  628. 'subkey' => $subkey,
  629. 'type' => 'checkbox',
  630. 'category' => 'Platform',
  631. 'selected_value' => 'true',
  632. 'title' => $tabName,
  633. 'comment' => $url,
  634. 'subkeytext' => $subkeytext,
  635. 'access_url' => $currentUrlId,
  636. 'access_url_changeable' => 1,
  637. 'access_url_locked' => 0,
  638. ];
  639. $resp = Database::insert('settings_current', $attributes);
  640. // Save the id
  641. $settings = $this->get_settings();
  642. $setData = [
  643. 'comment' => $subkey,
  644. ];
  645. $whereCondition = [
  646. 'id = ?' => key($settings),
  647. ];
  648. Database::update('settings_current', $setData, $whereCondition);
  649. return $resp;
  650. }
  651. /**
  652. * Delete a tab to chamilo's platform.
  653. *
  654. * @param string $key
  655. *
  656. * @return bool $resp Transaction response
  657. */
  658. public function deleteTab($key)
  659. {
  660. $table = Database::get_main_table(TABLE_MAIN_SETTINGS_CURRENT);
  661. $sql = "SELECT *
  662. FROM $table
  663. WHERE variable = 'show_tabs'
  664. AND subkey <> '$key'
  665. AND subkey like 'custom_tab_%'
  666. ";
  667. $resp = $result = Database::query($sql);
  668. $customTabsNum = Database::num_rows($result);
  669. if (!empty($key)) {
  670. $whereCondition = [
  671. 'variable = ? AND subkey = ?' => ['show_tabs', $key],
  672. ];
  673. $resp = Database::delete('settings_current', $whereCondition);
  674. //if there is more than one tab
  675. //re enumerate them
  676. if (!empty($customTabsNum) && $customTabsNum > 0) {
  677. $tabs = Database::store_result($result, 'ASSOC');
  678. $i = 1;
  679. foreach ($tabs as $row) {
  680. $newSubKey = "custom_tab_$i";
  681. if (strpos($row['subkey'], self::TAB_FILTER_NO_STUDENT) !== false) {
  682. $newSubKey .= self::TAB_FILTER_NO_STUDENT;
  683. } elseif (strpos($row['subkey'], self::TAB_FILTER_ONLY_STUDENT) !== false) {
  684. $newSubKey .= self::TAB_FILTER_ONLY_STUDENT;
  685. }
  686. $attributes = ['subkey' => $newSubKey];
  687. $this->updateTab($row['subkey'], $attributes);
  688. $i++;
  689. }
  690. }
  691. }
  692. return $resp;
  693. }
  694. /**
  695. * Update the tabs attributes.
  696. *
  697. * @param string $key
  698. * @param array $attributes
  699. *
  700. * @return bool
  701. */
  702. public function updateTab($key, $attributes)
  703. {
  704. $whereCondition = [
  705. 'variable = ? AND subkey = ?' => ['show_tabs', $key],
  706. ];
  707. $resp = Database::update('settings_current', $attributes, $whereCondition);
  708. return $resp;
  709. }
  710. /**
  711. * This method shows or hides plugin's tab.
  712. *
  713. * @param bool $showTab Shows or hides the main menu plugin tab
  714. * @param string $filePath Plugin starter file path
  715. */
  716. public function manageTab($showTab, $filePath = 'index.php')
  717. {
  718. $langString = str_replace('Plugin', '', get_class($this));
  719. $pluginName = strtolower($langString);
  720. $pluginUrl = 'plugin/'.$pluginName.'/'.$filePath;
  721. if ($showTab === 'true') {
  722. $tabAdded = $this->addTab($langString, $pluginUrl);
  723. if ($tabAdded) {
  724. // The page must be refreshed to show the recently created tab
  725. echo "<script>location.href = '".Security::remove_XSS($_SERVER['REQUEST_URI'])."';</script>";
  726. }
  727. } else {
  728. $settingsCurrentTable = Database::get_main_table(TABLE_MAIN_SETTINGS_CURRENT);
  729. $conditions = [
  730. 'where' => [
  731. "variable = 'show_tabs' AND title = ? AND comment = ? " => [
  732. $langString,
  733. $pluginUrl,
  734. ],
  735. ],
  736. ];
  737. $result = Database::select('subkey', $settingsCurrentTable, $conditions);
  738. if (!empty($result)) {
  739. $this->deleteTab($result[0]['subkey']);
  740. }
  741. }
  742. }
  743. /**
  744. * @param string $variable
  745. *
  746. * @return bool
  747. */
  748. public function validateCourseSetting($variable)
  749. {
  750. return true;
  751. }
  752. /**
  753. * @param string $region
  754. *
  755. * @return string
  756. */
  757. public function renderRegion($region)
  758. {
  759. return '';
  760. }
  761. /**
  762. * Returns true if the plugin is installed, false otherwise.
  763. *
  764. * @return bool True if plugin is installed/enabled, false otherwise
  765. */
  766. public function isEnabled()
  767. {
  768. $settings = api_get_settings_params_simple(
  769. [
  770. "subkey = ? AND category = ? AND type = ? AND variable = 'status' " => [
  771. $this->get_name(),
  772. 'Plugins',
  773. 'setting',
  774. ],
  775. ]
  776. );
  777. if (is_array($settings) && isset($settings['selected_value']) && $settings['selected_value'] == 'installed') {
  778. return true;
  779. }
  780. return false;
  781. }
  782. /**
  783. * Allow make some actions after configure the plugin parameters
  784. * This function is called from main/admin/configure_plugin.php page
  785. * when saving the plugin parameters.
  786. *
  787. * @return \Plugin
  788. */
  789. public function performActionsAfterConfigure()
  790. {
  791. return $this;
  792. }
  793. /**
  794. * This function allows to change the visibility of the icon inside a course
  795. * :student tool will be visible only for students
  796. * :teacher tool will be visible only for teachers
  797. * If nothing it's set then tool will be visible for both as a normal icon.
  798. *
  799. * @return string
  800. */
  801. public function getToolIconVisibilityPerUserStatus()
  802. {
  803. return '';
  804. }
  805. /**
  806. * Default tool icon visibility.
  807. *
  808. * @return bool
  809. */
  810. public function isIconVisibleByDefault()
  811. {
  812. return true;
  813. }
  814. /**
  815. * Get the admin URL for the plugin if Plugin::isAdminPlugin is true.
  816. *
  817. * @return string
  818. */
  819. public function getAdminUrl()
  820. {
  821. if (!$this->isAdminPlugin) {
  822. return '';
  823. }
  824. $name = $this->get_name();
  825. $sysPath = api_get_path(SYS_PLUGIN_PATH).$name;
  826. $webPath = api_get_path(WEB_PLUGIN_PATH).$name;
  827. if (file_exists("$sysPath/admin.php")) {
  828. return "$webPath/admin.php";
  829. }
  830. if (file_exists("$sysPath/start.php")) {
  831. return "$webPath/start.php";
  832. }
  833. return '';
  834. }
  835. /**
  836. * @param bool $value
  837. */
  838. public function setHasPersonalEvents($value)
  839. {
  840. $this->hasPersonalEvents = $value;
  841. }
  842. /**
  843. * Overwrite to perform some actions when deleting a user.
  844. *
  845. * @param int $userId
  846. */
  847. public function doWhenDeletingUser($userId)
  848. {
  849. }
  850. /**
  851. * Overwrite to perform some actions when deleting a course.
  852. *
  853. * @param int $courseId
  854. */
  855. public function doWhenDeletingCourse($courseId)
  856. {
  857. }
  858. /**
  859. * Overwrite to perform some actions when deleting a session.
  860. *
  861. * @param int $sessionId
  862. */
  863. public function doWhenDeletingSession($sessionId)
  864. {
  865. }
  866. /**
  867. * Add an link for a course tool.
  868. *
  869. * @param string $name The tool name
  870. * @param int $courseId The course ID
  871. * @param string $iconName Optional. Icon file name
  872. * @param string $link Optional. Link URL
  873. *
  874. * @return CTool|null
  875. */
  876. protected function createLinkToCourseTool(
  877. $name,
  878. $courseId,
  879. $iconName = null,
  880. $link = null
  881. ) {
  882. if (!$this->addCourseTool) {
  883. return null;
  884. }
  885. $visibilityPerStatus = $this->getToolIconVisibilityPerUserStatus();
  886. $visibility = $this->isIconVisibleByDefault();
  887. $em = Database::getManager();
  888. /** @var CTool $tool */
  889. $tool = $em
  890. ->getRepository('ChamiloCourseBundle:CTool')
  891. ->findOneBy([
  892. 'name' => $name,
  893. 'course' => $courseId,
  894. 'category' => 'plugin',
  895. ]);
  896. if (!$tool) {
  897. $cToolId = AddCourse::generateToolId($courseId);
  898. $pluginName = $this->get_name();
  899. $tool = new CTool();
  900. $tool
  901. ->setId($cToolId)
  902. ->setCourse(api_get_course_entity($courseId))
  903. ->setName($name.$visibilityPerStatus)
  904. ->setLink($link ?: "$pluginName/start.php")
  905. ->setImage($iconName ?: "$pluginName.png")
  906. ->setVisibility($visibility)
  907. ->setAdmin(0)
  908. ->setAddress('squaregrey.gif')
  909. ->setAddedTool(false)
  910. ->setTarget('_self')
  911. ->setCategory('plugin')
  912. ->setSessionId(0);
  913. $em->persist($tool);
  914. $em->flush();
  915. }
  916. return $tool;
  917. }
  918. }