link.lib.php 67 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793
  1. <?php
  2. /* For licensing terms, see /license.txt */
  3. /**
  4. * Function library for the links tool.
  5. *
  6. * This is a complete remake of the original link tool.
  7. * New features:
  8. * - Organize links into categories;
  9. * - favorites/bookmarks interface;
  10. * - move links up/down within a category;
  11. * - move categories up/down;
  12. * - expand/collapse all categories;
  13. * - add link to 'root' category => category-less link is always visible.
  14. *
  15. * @author Patrick Cool, complete remake (December 2003 - January 2004)
  16. * @author René Haentjens, CSV file import (October 2004)
  17. * @package chamilo.link
  18. */
  19. class Link extends Model
  20. {
  21. public $table;
  22. public $is_course_model = true;
  23. public $columns = array(
  24. 'id',
  25. 'c_id',
  26. 'url',
  27. 'title',
  28. 'description',
  29. 'category_id',
  30. 'display_order',
  31. 'on_homepage',
  32. 'target',
  33. 'session_id'
  34. );
  35. public $required = array('url', 'title');
  36. private $course;
  37. /**
  38. *
  39. */
  40. public function __construct()
  41. {
  42. $this->table = Database::get_course_table(TABLE_LINK);
  43. }
  44. /**
  45. * @param array $course
  46. */
  47. public function setCourse($course)
  48. {
  49. $this->course = $course;
  50. }
  51. /**
  52. * @return array
  53. */
  54. public function getCourse()
  55. {
  56. return !empty($this->course) ? $this->course : api_get_course_info();
  57. }
  58. /**
  59. * Organize the saving of a link, using the parent's save method and
  60. * updating the item_property table
  61. * @param array $params
  62. * @param boolean $show_query Whether to show the query in logs when
  63. * calling parent's save method
  64. *
  65. * @return bool True if link could be saved, false otherwise
  66. */
  67. public function save($params, $show_query = null)
  68. {
  69. $course_info = $this->getCourse();
  70. $courseId = $course_info['real_id'];
  71. $params['session_id'] = api_get_session_id();
  72. $params['category_id'] = isset($params['category_id']) ? $params['category_id'] : 0;
  73. $sql = "SELECT MAX(display_order)
  74. FROM ".$this->table."
  75. WHERE
  76. c_id = $courseId AND
  77. category_id = '" . intval($params['category_id'])."'";
  78. $result = Database:: query($sql);
  79. list ($orderMax) = Database:: fetch_row($result);
  80. $order = $orderMax + 1;
  81. $params['display_order'] = $order;
  82. $id = parent::save($params, $show_query);
  83. if (!empty($id)) {
  84. // iid
  85. $sql = "UPDATE ".$this->table." SET id = iid WHERE iid = $id";
  86. Database:: query($sql);
  87. api_set_default_visibility($id, TOOL_LINK);
  88. api_item_property_update(
  89. $course_info,
  90. TOOL_LINK,
  91. $id,
  92. 'LinkAdded',
  93. api_get_user_id()
  94. );
  95. }
  96. return $id;
  97. }
  98. /**
  99. * Update a link in the database
  100. * @param int $linkId The ID of the link to update
  101. * @param string $linkUrl The new URL to be saved
  102. * @param int Course ID
  103. * @param int Session ID
  104. * @return bool
  105. */
  106. public function updateLink(
  107. $linkId,
  108. $linkUrl,
  109. $courseId = null,
  110. $sessionId = null
  111. ) {
  112. $tblLink = Database:: get_course_table(TABLE_LINK);
  113. $linkUrl = Database::escape_string($linkUrl);
  114. $linkId = intval($linkId);
  115. if (is_null($courseId)) {
  116. $courseId = api_get_course_int_id();
  117. }
  118. $courseId = intval($courseId);
  119. if (is_null($sessionId)) {
  120. $sessionId = api_get_session_id();
  121. }
  122. $sessionId = intval($sessionId);
  123. if ($linkUrl != '') {
  124. $sql = "UPDATE $tblLink SET url = '$linkUrl'
  125. WHERE id = $linkId AND c_id = $courseId AND session_id = $sessionId";
  126. $resLink = Database::query($sql);
  127. return $resLink;
  128. }
  129. return false;
  130. }
  131. /**
  132. * Used to add a link or a category
  133. * @param string $type , "link" or "category"
  134. * @todo replace strings by constants
  135. * @author Patrick Cool <patrick.cool@UGent.be>, Ghent University
  136. * @return bool True on success, false on failure
  137. */
  138. public static function addlinkcategory($type)
  139. {
  140. global $catlinkstatus;
  141. global $msgErr;
  142. $ok = true;
  143. $_course = api_get_course_info();
  144. $course_id = $_course['real_id'];
  145. $session_id = api_get_session_id();
  146. if ($type == 'link') {
  147. $title = Security::remove_XSS(stripslashes($_POST['title']));
  148. $urllink = Security::remove_XSS($_POST['url']);
  149. $description = Security::remove_XSS($_POST['description']);
  150. $selectcategory = Security::remove_XSS($_POST['category_id']);
  151. if (!isset($_POST['on_homepage'])) {
  152. $onhomepage = 0;
  153. } else {
  154. $onhomepage = Security::remove_XSS($_POST['on_homepage']);
  155. }
  156. if (empty($_POST['target'])) {
  157. $target = '_self'; // Default target.
  158. } else {
  159. $target = Security::remove_XSS($_POST['target']);
  160. }
  161. $urllink = trim($urllink);
  162. $title = trim($title);
  163. $description = trim($description);
  164. // We ensure URL to be absolute.
  165. if (strpos($urllink, '://') === false) {
  166. $urllink = 'http://' . $urllink;
  167. }
  168. // If the title is empty, we use the URL as title.
  169. if ($title == '') {
  170. $title = $urllink;
  171. }
  172. // If the URL is invalid, an error occurs.
  173. if (!api_valid_url($urllink, true)) {
  174. // A check against an absolute URL
  175. Display::addFlash(Display::return_message(get_lang('GiveURL'), 'error'));
  176. return false;
  177. } else {
  178. // Looking for the largest order number for this category.
  179. $link = new Link();
  180. $params = [
  181. 'c_id' => $course_id,
  182. 'url' => $urllink,
  183. 'title' => $title,
  184. 'description' => $description ,
  185. 'category_id' => $selectcategory,
  186. 'on_homepage' => $onhomepage,
  187. 'target' => $target,
  188. 'session_id' => $session_id,
  189. ];
  190. $link_id = $link->save($params);
  191. $catlinkstatus = get_lang('LinkAdded');
  192. if ((api_get_setting('search_enabled') == 'true') &&
  193. $link_id && extension_loaded('xapian')
  194. ) {
  195. require_once api_get_path(LIBRARY_PATH) . 'search/ChamiloIndexer.class.php';
  196. require_once api_get_path(LIBRARY_PATH) . 'search/IndexableChunk.class.php';
  197. require_once api_get_path(LIBRARY_PATH) . 'specific_fields_manager.lib.php';
  198. $course_int_id = $_course['real_id'];
  199. $courseCode = $_course['code'];
  200. $specific_fields = get_specific_field_list();
  201. $ic_slide = new IndexableChunk();
  202. // Add all terms to db.
  203. $all_specific_terms = '';
  204. foreach ($specific_fields as $specific_field) {
  205. if (isset ($_REQUEST[$specific_field['code']])) {
  206. $sterms = trim($_REQUEST[$specific_field['code']]);
  207. if (!empty ($sterms)) {
  208. $all_specific_terms .= ' ' . $sterms;
  209. $sterms = explode(',', $sterms);
  210. foreach ($sterms as $sterm) {
  211. $ic_slide->addTerm(
  212. trim($sterm),
  213. $specific_field['code']
  214. );
  215. add_specific_field_value(
  216. $specific_field['id'],
  217. $courseCode,
  218. TOOL_LINK,
  219. $link_id,
  220. $sterm
  221. );
  222. }
  223. }
  224. }
  225. }
  226. // Build the chunk to index.
  227. $ic_slide->addValue('title', $title);
  228. $ic_slide->addCourseId($courseCode);
  229. $ic_slide->addToolId(TOOL_LINK);
  230. $xapian_data = array(
  231. SE_COURSE_ID => $courseCode,
  232. SE_TOOL_ID => TOOL_LINK,
  233. SE_DATA => array(
  234. 'link_id' => (int)$link_id
  235. ),
  236. SE_USER => (int)api_get_user_id(),
  237. );
  238. $ic_slide->xapian_data = serialize($xapian_data);
  239. $description = $all_specific_terms . ' ' . $description;
  240. $ic_slide->addValue('content', $description);
  241. // Add category name if set.
  242. if (isset($selectcategory) && $selectcategory > 0) {
  243. $table_link_category = Database:: get_course_table(
  244. TABLE_LINK_CATEGORY
  245. );
  246. $sql_cat = 'SELECT * FROM %s WHERE id=%d AND c_id = %d LIMIT 1';
  247. $sql_cat = sprintf(
  248. $sql_cat,
  249. $table_link_category,
  250. (int)$selectcategory,
  251. $course_int_id
  252. );
  253. $result = Database:: query($sql_cat);
  254. if (Database:: num_rows($result) == 1) {
  255. $row = Database:: fetch_array($result);
  256. $ic_slide->addValue(
  257. 'category',
  258. $row['category_title']
  259. );
  260. }
  261. }
  262. $di = new ChamiloIndexer();
  263. isset ($_POST['language']) ? $lang = Database:: escape_string(
  264. $_POST['language']
  265. ) : $lang = 'english';
  266. $di->connectDb(null, null, $lang);
  267. $di->addChunk($ic_slide);
  268. // Index and return search engine document id.
  269. $did = $di->index();
  270. if ($did) {
  271. // Save it to db.
  272. $tbl_se_ref = Database:: get_main_table(
  273. TABLE_MAIN_SEARCH_ENGINE_REF
  274. );
  275. $sql = 'INSERT INTO %s (id, course_code, tool_id, ref_id_high_level, search_did)
  276. VALUES (NULL , \'%s\', \'%s\', %s, %s)';
  277. $sql = sprintf(
  278. $sql,
  279. $tbl_se_ref,
  280. $course_int_id,
  281. $courseCode,
  282. TOOL_LINK,
  283. $link_id,
  284. $did
  285. );
  286. Database:: query($sql);
  287. }
  288. }
  289. Display::addFlash(Display::return_message(get_lang('LinkAdded')));
  290. }
  291. } elseif ($type == 'category') {
  292. $tbl_categories = Database:: get_course_table(TABLE_LINK_CATEGORY);
  293. $category_title = trim($_POST['category_title']);
  294. $description = trim($_POST['description']);
  295. if (empty($category_title)) {
  296. $msgErr = get_lang('GiveCategoryName');
  297. Display:: display_error_message(get_lang('GiveCategoryName'));
  298. $ok = false;
  299. } else {
  300. // Looking for the largest order number for this category.
  301. $result = Database:: query(
  302. "SELECT MAX(display_order) FROM $tbl_categories
  303. WHERE c_id = $course_id "
  304. );
  305. list ($orderMax) = Database:: fetch_row($result);
  306. $order = $orderMax + 1;
  307. $order = intval($order);
  308. $session_id = api_get_session_id();
  309. $params = [
  310. 'c_id' => $course_id,
  311. 'category_title' => $category_title,
  312. 'description' => $description,
  313. 'display_order' => $order,
  314. 'session_id' => $session_id
  315. ];
  316. $linkId = Database::insert($tbl_categories, $params);
  317. if ($linkId) {
  318. // iid
  319. $sql = "UPDATE $tbl_categories SET id = iid WHERE iid = $linkId";
  320. Database:: query($sql);
  321. // add link_category visibility
  322. // course ID is taken from context in api_set_default_visibility
  323. api_set_default_visibility($linkId, TOOL_LINK_CATEGORY);
  324. }
  325. Display::addFlash(Display::return_message(get_lang('CategoryAdded')));
  326. }
  327. }
  328. return $ok;
  329. }
  330. /**
  331. * Used to delete a link or a category
  332. * @author Patrick Cool <patrick.cool@UGent.be>, Ghent University
  333. * @param int $id
  334. * @param string $type The type of item to delete
  335. * @return bool
  336. */
  337. public static function deletelinkcategory($id, $type)
  338. {
  339. $courseInfo = api_get_course_info();
  340. $tbl_link = Database:: get_course_table(TABLE_LINK);
  341. $tbl_categories = Database:: get_course_table(TABLE_LINK_CATEGORY);
  342. $course_id = $courseInfo['real_id'];
  343. $id = intval($id);
  344. if (empty($id)) {
  345. return false;
  346. }
  347. $result = false;
  348. switch ($type) {
  349. case 'link':
  350. // -> Items are no longer physically deleted,
  351. // but the visibility is set to 2 (in item_property).
  352. // This will make a restore function possible for the platform administrator.
  353. $sql = "UPDATE $tbl_link SET on_homepage='0'
  354. WHERE c_id = $course_id AND id='" . $id . "'";
  355. Database:: query($sql);
  356. api_item_property_update(
  357. $courseInfo,
  358. TOOL_LINK,
  359. $id,
  360. 'delete',
  361. api_get_user_id()
  362. );
  363. self::delete_link_from_search_engine(api_get_course_id(), $id);
  364. Display:: display_confirmation_message(get_lang('LinkDeleted'));
  365. $result = true;
  366. break;
  367. case 'category':
  368. // First we delete the category itself and afterwards all the links of this category.
  369. $sql = "DELETE FROM " . $tbl_categories . "
  370. WHERE c_id = $course_id AND id='" . $id . "'";
  371. Database:: query($sql);
  372. $sql = "DELETE FROM " . $tbl_link . "
  373. WHERE c_id = $course_id AND category_id='" . $id . "'";
  374. Database:: query($sql);
  375. api_item_property_update(
  376. $courseInfo,
  377. TOOL_LINK_CATEGORY,
  378. $id,
  379. 'delete',
  380. api_get_user_id()
  381. );
  382. Display::addFlash(Display::return_message(get_lang('CategoryDeleted')));
  383. $result = true;
  384. break;
  385. }
  386. return $result;
  387. }
  388. /**
  389. * Removes a link from search engine database
  390. * @param string $course_id Course code
  391. * @param int $link_id Document id to delete
  392. * @return void
  393. */
  394. public static function delete_link_from_search_engine($course_id, $link_id)
  395. {
  396. // Remove from search engine if enabled.
  397. if (api_get_setting('search_enabled') == 'true') {
  398. $tbl_se_ref = Database:: get_main_table(
  399. TABLE_MAIN_SEARCH_ENGINE_REF
  400. );
  401. $sql = 'SELECT * FROM %s WHERE course_code=\'%s\' AND tool_id=\'%s\' AND ref_id_high_level=%s LIMIT 1';
  402. $sql = sprintf($sql, $tbl_se_ref, $course_id, TOOL_LINK, $link_id);
  403. $res = Database:: query($sql);
  404. if (Database:: num_rows($res) > 0) {
  405. $row = Database:: fetch_array($res);
  406. require_once api_get_path(
  407. LIBRARY_PATH
  408. ) . 'search/ChamiloIndexer.class.php';
  409. $di = new ChamiloIndexer();
  410. $di->remove_document((int)$row['search_did']);
  411. }
  412. $sql = 'DELETE FROM %s WHERE course_code=\'%s\' AND tool_id=\'%s\' AND ref_id_high_level=%s LIMIT 1';
  413. $sql = sprintf($sql, $tbl_se_ref, $course_id, TOOL_LINK, $link_id);
  414. Database:: query($sql);
  415. // Remove terms from db.
  416. require_once api_get_path(LIBRARY_PATH) . 'specific_fields_manager.lib.php';
  417. delete_all_values_for_item($course_id, TOOL_DOCUMENT, $link_id);
  418. }
  419. }
  420. /**
  421. *
  422. * Get link info
  423. * @param int link id
  424. * @return array link info
  425. *
  426. **/
  427. public static function get_link_info($id)
  428. {
  429. $tbl_link = Database:: get_course_table(TABLE_LINK);
  430. $course_id = api_get_course_int_id();
  431. $sql = "SELECT * FROM " . $tbl_link . "
  432. WHERE c_id = $course_id AND id='" . intval($id) . "' ";
  433. $result = Database::query($sql);
  434. $data = array();
  435. if (Database::num_rows($result)) {
  436. $data = Database::fetch_array($result);
  437. }
  438. return $data;
  439. }
  440. /**
  441. * @param int $id
  442. * @param array $values
  443. */
  444. public static function editLink($id, $values = array())
  445. {
  446. $tbl_link = Database:: get_course_table(TABLE_LINK);
  447. $_course = api_get_course_info();
  448. $course_id = $_course['real_id'];
  449. $values['url'] = trim($values['url']);
  450. $values['title'] = trim($values['title']);
  451. $values['description'] = trim($values['description']);
  452. $values['target'] = empty($values['target']) ? '_self' : $values['target'];
  453. $values['on_homepage'] = isset($values['on_homepage']) ? $values['on_homepage'] : '';
  454. $categoryId = intval($values['category_id']);
  455. // We ensure URL to be absolute.
  456. if (strpos($values['url'], '://') === false) {
  457. $values['url'] = 'http://' . $_POST['url'];
  458. }
  459. // If the title is empty, we use the URL as title.
  460. if ($values['title'] == '') {
  461. $values['title'] = $values['url'];
  462. }
  463. // If the URL is invalid, an error occurs.
  464. if (!api_valid_url($values['url'], true)) {
  465. Display::addFlash(
  466. Display::return_message(get_lang('GiveURL'), 'error')
  467. );
  468. return false;
  469. }
  470. // Finding the old category_id.
  471. $sql = "SELECT * FROM " . $tbl_link . "
  472. WHERE c_id = $course_id AND id='" . $id . "'";
  473. $result = Database:: query($sql);
  474. $row = Database:: fetch_array($result);
  475. $category_id = $row['category_id'];
  476. if ($category_id != $values['category_id']) {
  477. $sql = "SELECT MAX(display_order)
  478. FROM " . $tbl_link . "
  479. WHERE
  480. c_id = $course_id AND
  481. category_id='" . intval($values['category_id']) . "'";
  482. $result = Database:: query($sql);
  483. list ($max_display_order) = Database:: fetch_row($result);
  484. $max_display_order++;
  485. } else {
  486. $max_display_order = $row['display_order'];
  487. }
  488. $params = [
  489. 'url' => $values['url'],
  490. 'title' => $values['title'],
  491. 'description' => $values['description'],
  492. 'category_id' => $values['category_id'],
  493. 'display_order' => $max_display_order,
  494. 'on_homepage' => $values['on_homepage'],
  495. 'target' => $values['target'],
  496. 'category_id' => $values['category_id'],
  497. ];
  498. Database::update($tbl_link, $params, ['c_id = ? AND id = ?' => [$course_id, $id] ]);
  499. // Update search enchine and its values table if enabled.
  500. if (api_get_setting('search_enabled') == 'true') {
  501. $course_int_id = api_get_course_int_id();
  502. $course_id = api_get_course_id();
  503. $link_title = Database:: escape_string($values['title']);
  504. $link_description = Database:: escape_string($values['description']);
  505. // Actually, it consists on delete terms from db,
  506. // insert new ones, create a new search engine document, and remove the old one.
  507. // Get search_did.
  508. $tbl_se_ref = Database:: get_main_table(
  509. TABLE_MAIN_SEARCH_ENGINE_REF
  510. );
  511. $sql = 'SELECT * FROM %s WHERE course_code=\'%s\' AND tool_id=\'%s\' AND ref_id_high_level=%s LIMIT 1';
  512. $sql = sprintf(
  513. $sql,
  514. $tbl_se_ref,
  515. $course_id,
  516. TOOL_LINK,
  517. $id
  518. );
  519. $res = Database:: query($sql);
  520. if (Database:: num_rows($res) > 0) {
  521. require_once api_get_path(
  522. LIBRARY_PATH
  523. ).'search/ChamiloIndexer.class.php';
  524. require_once api_get_path(
  525. LIBRARY_PATH
  526. ).'search/IndexableChunk.class.php';
  527. require_once api_get_path(
  528. LIBRARY_PATH
  529. ).'specific_fields_manager.lib.php';
  530. $se_ref = Database:: fetch_array($res);
  531. $specific_fields = get_specific_field_list();
  532. $ic_slide = new IndexableChunk();
  533. $all_specific_terms = '';
  534. foreach ($specific_fields as $specific_field) {
  535. delete_all_specific_field_value(
  536. $course_id,
  537. $specific_field['id'],
  538. TOOL_LINK,
  539. $id
  540. );
  541. if (isset ($_REQUEST[$specific_field['code']])) {
  542. $sterms = trim(
  543. $_REQUEST[$specific_field['code']]
  544. );
  545. if (!empty ($sterms)) {
  546. $all_specific_terms .= ' ' . $sterms;
  547. $sterms = explode(',', $sterms);
  548. foreach ($sterms as $sterm) {
  549. $ic_slide->addTerm(
  550. trim($sterm),
  551. $specific_field['code']
  552. );
  553. add_specific_field_value(
  554. $specific_field['id'],
  555. $course_id,
  556. TOOL_LINK,
  557. $id,
  558. $sterm
  559. );
  560. }
  561. }
  562. }
  563. }
  564. // Build the chunk to index.
  565. $ic_slide->addValue("title", $link_title);
  566. $ic_slide->addCourseId($course_id);
  567. $ic_slide->addToolId(TOOL_LINK);
  568. $xapian_data = array(
  569. SE_COURSE_ID => $course_id,
  570. SE_TOOL_ID => TOOL_LINK,
  571. SE_DATA => array(
  572. 'link_id' => (int)$id
  573. ),
  574. SE_USER => (int)api_get_user_id(),
  575. );
  576. $ic_slide->xapian_data = serialize($xapian_data);
  577. $link_description = $all_specific_terms . ' ' . $link_description;
  578. $ic_slide->addValue('content', $link_description);
  579. // Add category name if set.
  580. if (isset ($categoryId) && $categoryId > 0) {
  581. $table_link_category = Database:: get_course_table(
  582. TABLE_LINK_CATEGORY
  583. );
  584. $sql_cat = 'SELECT * FROM %s WHERE id=%d and c_id = %d LIMIT 1';
  585. $sql_cat = sprintf(
  586. $sql_cat,
  587. $table_link_category,
  588. $categoryId,
  589. $course_int_id
  590. );
  591. $result = Database:: query($sql_cat);
  592. if (Database:: num_rows($result) == 1) {
  593. $row = Database:: fetch_array($result);
  594. $ic_slide->addValue(
  595. 'category',
  596. $row['category_title']
  597. );
  598. }
  599. }
  600. $di = new ChamiloIndexer();
  601. isset ($_POST['language']) ? $lang = Database:: escape_string($_POST['language']) : $lang = 'english';
  602. $di->connectDb(null, null, $lang);
  603. $di->remove_document((int)$se_ref['search_did']);
  604. $di->addChunk($ic_slide);
  605. // Index and return search engine document id.
  606. $did = $di->index();
  607. if ($did) {
  608. // Save it to db.
  609. $sql = 'DELETE FROM %s
  610. WHERE course_code=\'%s\'
  611. AND tool_id=\'%s\'
  612. AND ref_id_high_level=\'%s\'';
  613. $sql = sprintf(
  614. $sql,
  615. $tbl_se_ref,
  616. $course_id,
  617. TOOL_LINK,
  618. $id
  619. );
  620. Database:: query($sql);
  621. $sql = 'INSERT INTO %s (c_id, id, course_code, tool_id, ref_id_high_level, search_did)
  622. VALUES (NULL , \'%s\', \'%s\', %s, %s)';
  623. $sql = sprintf(
  624. $sql,
  625. $tbl_se_ref,
  626. $course_int_id,
  627. $course_id,
  628. TOOL_LINK,
  629. $id,
  630. $did
  631. );
  632. Database:: query($sql);
  633. }
  634. }
  635. }
  636. // "WHAT'S NEW" notification: update table last_toolEdit.
  637. api_item_property_update(
  638. $_course,
  639. TOOL_LINK,
  640. $id,
  641. 'LinkUpdated',
  642. api_get_user_id()
  643. );
  644. Display::addFlash(Display::return_message(get_lang('LinkModded')));
  645. }
  646. /**
  647. * @param int $id
  648. * @return bool
  649. */
  650. public static function editCategory($id, $values)
  651. {
  652. $tbl_categories = Database:: get_course_table(TABLE_LINK_CATEGORY);
  653. $course_id = api_get_course_int_id();
  654. $id = intval($id);
  655. // This is used to put the modified info of the category-form into the database.
  656. $params = [
  657. 'category_title' => $values['category_title'],
  658. 'description' => $values['description']
  659. ];
  660. Database::update($tbl_categories, $params, ['c_id = ? AND id = ?' => [$course_id, $id]]);
  661. Display::addFlash(Display::return_message(get_lang('CategoryModded')));
  662. return true;
  663. }
  664. /**
  665. * Changes the visibility of a link
  666. * @todo add the changing of the visibility of a course
  667. * @author Patrick Cool <patrick.cool@UGent.be>, Ghent University
  668. */
  669. public static function change_visibility_link($id, $scope)
  670. {
  671. $_course = api_get_course_info();
  672. $_user = api_get_user_info();
  673. if ($scope == TOOL_LINK) {
  674. api_item_property_update(
  675. $_course,
  676. TOOL_LINK,
  677. $id,
  678. $_GET['action'],
  679. $_user['user_id']
  680. );
  681. Display::addFlash(Display::return_message(get_lang('VisibilityChanged')));
  682. } elseif ($scope == TOOL_LINK_CATEGORY) {
  683. api_item_property_update(
  684. $_course,
  685. TOOL_LINK_CATEGORY,
  686. $id,
  687. $_GET['action'],
  688. $_user['user_id']
  689. );
  690. Display::addFlash(Display::return_message(get_lang('VisibilityChanged')));
  691. }
  692. }
  693. /**
  694. * Generate SQL to select all the links categories in the current course and
  695. * session
  696. * @param int $courseId
  697. * @param int $sessionId
  698. * @return array
  699. */
  700. public static function getLinkCategories($courseId, $sessionId)
  701. {
  702. $tblLinkCategory = Database:: get_course_table(TABLE_LINK_CATEGORY);
  703. $tblItemProperty = Database:: get_course_table(TABLE_ITEM_PROPERTY);
  704. $courseId = intval($courseId);
  705. // Condition for the session.
  706. $sessionCondition = api_get_session_condition($sessionId, true, true, 'linkcat.session_id');
  707. // Getting links
  708. $sql = "SELECT *, linkcat.id
  709. FROM $tblLinkCategory linkcat
  710. WHERE
  711. linkcat.c_id = " . $courseId . "
  712. $sessionCondition
  713. ORDER BY linkcat.display_order DESC";
  714. $result = Database::query($sql);
  715. $categories = Database::store_result($result);
  716. $sql = "SELECT *, linkcat.id
  717. FROM $tblLinkCategory linkcat
  718. INNER JOIN $tblItemProperty itemproperties
  719. ON (linkcat.id = itemproperties.ref AND linkcat.c_id = itemproperties.c_id)
  720. WHERE
  721. itemproperties.tool = '" . TOOL_LINK_CATEGORY . "' AND
  722. (itemproperties.visibility = '0' OR itemproperties.visibility = '1')
  723. $sessionCondition AND
  724. linkcat.c_id = " . $courseId . "
  725. ORDER BY linkcat.display_order DESC";
  726. $result = Database::query($sql);
  727. $categoryInItemProperty = array();
  728. if (Database::num_rows($result)) {
  729. while ($row = Database::fetch_array($result, 'ASSOC')) {
  730. $categoryInItemProperty[$row['id']] = $row;
  731. }
  732. }
  733. foreach ($categories as & $category) {
  734. if (!isset($categoryInItemProperty[$category['id']])) {
  735. api_set_default_visibility($category['id'], TOOL_LINK_CATEGORY);
  736. }
  737. }
  738. $sql = "SELECT DISTINCT linkcat.*, visibility
  739. FROM $tblLinkCategory linkcat
  740. INNER JOIN $tblItemProperty itemproperties
  741. ON (linkcat.id = itemproperties.ref AND linkcat.c_id = itemproperties.c_id)
  742. WHERE
  743. itemproperties.tool = '" . TOOL_LINK_CATEGORY . "' AND
  744. (itemproperties.visibility = '0' OR itemproperties.visibility = '1')
  745. $sessionCondition AND
  746. linkcat.c_id = " . $courseId . "
  747. ORDER BY linkcat.display_order DESC
  748. ";
  749. $result = Database::query($sql);
  750. return Database::store_result($result, 'ASSOC');
  751. }
  752. /**
  753. * Displays all the links of a given category.
  754. * @author Patrick Cool <patrick.cool@UGent.be>, Ghent University
  755. */
  756. public static function showlinksofcategory($catid)
  757. {
  758. global $token;
  759. $_user = api_get_user_info();
  760. $course_id = api_get_course_int_id();
  761. $session_id = api_get_session_id();
  762. $catid = intval($catid);
  763. $tbl_link = Database:: get_course_table(TABLE_LINK);
  764. $TABLE_ITEM_PROPERTY = Database:: get_course_table(TABLE_ITEM_PROPERTY);
  765. // Condition for the session.
  766. $condition_session = api_get_session_condition($session_id, true, true, 'link.session_id');
  767. $content = '';
  768. $sql = "SELECT *, link.id FROM $tbl_link link
  769. INNER JOIN $TABLE_ITEM_PROPERTY itemproperties
  770. ON (link.id=itemproperties.ref AND link.c_id = itemproperties.c_id )
  771. WHERE
  772. itemproperties.tool='" . TOOL_LINK . "' AND
  773. link.category_id='" . $catid . "' AND
  774. (itemproperties.visibility='0' OR itemproperties.visibility='1')
  775. $condition_session AND
  776. link.c_id = " . $course_id . " AND
  777. itemproperties.c_id = " . $course_id . "
  778. ORDER BY link.display_order DESC";
  779. $result = Database:: query($sql);
  780. $numberoflinks = Database:: num_rows($result);
  781. if ($numberoflinks > 0) {
  782. $content .= '<div class="link list-group">';
  783. $i = 1;
  784. while ($myrow = Database:: fetch_array($result)) {
  785. // Validation when belongs to a session.
  786. $session_img = api_get_session_image(
  787. $myrow['session_id'],
  788. $_user['status']
  789. );
  790. //$css_class = $i % 2 == 0 ? $css_class = 'row_odd' : $css_class = 'row_even';
  791. $toolbar = '';
  792. $link_validator = '';
  793. if (api_is_allowed_to_edit(null, true)) {
  794. $toolbar .= Display::toolbarButton('',
  795. '#',
  796. 'retweet',
  797. 'default btn-sm',
  798. array(
  799. 'onclick' => "check_url('" . $myrow['id'] . "', '" . addslashes($myrow['url']) . "');",
  800. 'title' => get_lang('CheckURL')
  801. )
  802. );
  803. $link_validator .= Display::span(
  804. '',
  805. array(
  806. 'id' => 'url_id_' . $myrow['id'],
  807. 'class' => 'check-link'
  808. )
  809. );
  810. }
  811. if (api_is_allowed_to_edit(null, true)) {
  812. if ($session_id == $myrow['session_id']) {
  813. $url = api_get_self() . '?' . api_get_cidreq() .
  814. '&action=editlink&category=' . (!empty ($category) ? $category : '') .
  815. '&id=' . $myrow['id'] .
  816. '&category_id=' . $myrow['id'];
  817. $title = get_lang('Edit');
  818. $toolbar .= Display::toolbarButton(
  819. '',
  820. $url,
  821. 'pencil',
  822. 'default btn-sm',
  823. array(
  824. 'title' => $title
  825. )
  826. );
  827. // DISPLAY MOVE UP COMMAND only if it is not the top link.
  828. /* commented at least since 2014-10-11
  829. if ($i != 1) {
  830. echo '<a href="' . api_get_self() . '?' . api_get_cidreq() . '&sec_token='.$token.'&urlview=' . $urlview . '&up=', $myrow[0], '" title="' . get_lang('Up') . '">' . Display :: return_icon('up.png', get_lang('Up'), array (), ICON_SIZE_SMALL) . '', "</a>\n";
  831. } else {
  832. echo Display :: return_icon('up_na.png', get_lang('Up'), array (), ICON_SIZE_SMALL) . '</a>';
  833. }
  834. // DISPLAY MOVE DOWN COMMAND only if it is not the bottom link.
  835. if ($i < $numberoflinks) {
  836. echo '<a href="' . api_get_self() . '?' . api_get_cidreq() . '&sec_token='.$token.'&urlview=' . $urlview . '&down=' . $myrow[0] . '" title="' . get_lang('Down') . '">' . Display :: return_icon('down.png', get_lang('Down'), array (), ICON_SIZE_SMALL) . '', "</a>\n";
  837. } else {
  838. echo Display :: return_icon('down_na.png', get_lang('Down'), array (), ICON_SIZE_SMALL) . '', "</a>\n";
  839. }*/
  840. if ($myrow['visibility'] == '1') {
  841. $url .= 'link.php?' . api_get_cidreq() .
  842. '&sec_token=' . $token .
  843. '&action=invisible&id=' . $myrow['id'] .
  844. '&scope=link&category_id=' . $myrow['category_id'];
  845. $title = get_lang('MakeInvisible');
  846. $toolbar .= Display::toolbarButton(
  847. '',
  848. $url,
  849. 'eye',
  850. 'default btn-sm',
  851. array(
  852. 'title' => $title
  853. )
  854. );
  855. }
  856. if ($myrow['visibility'] == '0') {
  857. $url .= 'link.php?' . api_get_cidreq() .'&sec_token=' . $token .'&action=visible&id=' . $myrow['id'] .'&scope=link&category_id=' . $myrow['category_id'];
  858. $title = get_lang('MakeVisible');
  859. $toolbar .= Display::toolbarButton(
  860. '',
  861. $url,
  862. 'eye-slash',
  863. 'primary btn-sm',
  864. array(
  865. 'title' => $title
  866. )
  867. );
  868. }
  869. $url .= api_get_self() . '?' . api_get_cidreq() .'&sec_token=' . $token .'&action=deletelink&id=' . $myrow['id'] .'&category_id=' . $myrow['category_id'];
  870. $event = "javascript: if(!confirm('" . get_lang('LinkDelconfirm') . "'))return false;";
  871. $title = get_lang('Delete');
  872. $toolbar .= Display::toolbarButton(
  873. '',
  874. $url,
  875. 'trash',
  876. 'default btn-sm',
  877. array(
  878. 'onclick' => $event,
  879. 'title' => $title
  880. )
  881. );
  882. } else {
  883. $title = get_lang('EditionNotAvailableFromSession');
  884. $toolbar .= Display::toolbarButton(
  885. '',
  886. '#',
  887. 'trash-o',
  888. 'default btn-sm',
  889. array(
  890. 'title' => $title
  891. )
  892. );
  893. }
  894. }
  895. $iconLink = Display::return_icon(
  896. 'url.png',
  897. get_lang('Link'),
  898. null,
  899. ICON_SIZE_SMALL
  900. );
  901. if ($myrow['visibility'] == '1') {
  902. $content .= '<div class="list-group-item">';
  903. $content .= '<div class="pull-right"><div class="btn-group">'.$toolbar.'</div></div>';
  904. $content .= '<h4 class="list-group-item-heading">';
  905. $content .= $iconLink;
  906. $url = 'link_goto.php?' . api_get_cidreq() .'&link_id=' . $myrow['id'] .'&link_url=' . urlencode($myrow['url']);
  907. $content .= Display::tag(
  908. 'a',
  909. Security:: remove_XSS($myrow['title']),
  910. array(
  911. 'href' => $url,
  912. 'target' => $myrow['target']
  913. )
  914. );
  915. $content .= $link_validator;
  916. $content .= $session_img;
  917. $content .= '</h4>';
  918. $content .= '<p class="list-group-item-text">' . $myrow['description'] . '</p>';
  919. $content .= '</div>';
  920. } else {
  921. if (api_is_allowed_to_edit(null, true)) {
  922. $content .= '<div class="list-group-item">';
  923. $content .= '<div class="pull-right"><div class="btn-group">'.$toolbar.'</div></div>';
  924. $content .= '<h4 class="list-group-item-heading">';
  925. $content .= $iconLink;
  926. $url = 'link_goto.php?' . api_get_cidreq() .'&link_id=' . $myrow['id'] . "&link_url=" . urlencode($myrow['url']);
  927. $content .= Display::tag(
  928. 'a',
  929. Security:: remove_XSS($myrow['title']),
  930. array(
  931. 'href' => $url,
  932. 'target' => '_blank',
  933. 'class' => 'invisible'
  934. )
  935. );
  936. $content .= $link_validator;
  937. $content .= $session_img;
  938. $content .= '</h4>';
  939. $content .= '<p class="list-group-item-text">' . $myrow['description'] . '</p>';
  940. $content .= '</div>';
  941. }
  942. }
  943. $i++;
  944. }
  945. $content .= '</div>';
  946. }
  947. return $content;
  948. }
  949. /**
  950. * Displays the edit, delete and move icons
  951. * @param int Category ID
  952. * @return void
  953. * @author Patrick Cool <patrick.cool@UGent.be>, Ghent University
  954. */
  955. public static function showCategoryAdminTools($category, $currentCategory, $countCategories)
  956. {
  957. $categoryId = $category['id'];
  958. $token = null;
  959. $tools = '<a href="' . api_get_self() . '?' . api_get_cidreq() . '&sec_token=' . $token . '&action=editcategory&id=' . $categoryId . '&category_id=' . $categoryId . '" title=' . get_lang('Modify') . '">' .
  960. Display:: return_icon(
  961. 'edit.png',
  962. get_lang('Modify'),
  963. array(),
  964. ICON_SIZE_SMALL
  965. ) . '</a>';
  966. // DISPLAY MOVE UP COMMAND only if it is not the top link.
  967. if ($currentCategory != 0) {
  968. $tools .= '<a href="' . api_get_self() . '?' . api_get_cidreq() . '&sec_token=' . $token . '&action=up&up='.$categoryId.'&category_id='.$categoryId.'" title="'.get_lang('Up').'">'.
  969. Display:: return_icon(
  970. 'up.png',
  971. get_lang('Up'),
  972. array(),
  973. ICON_SIZE_SMALL
  974. ) . '</a>';
  975. } else {
  976. $tools .= Display:: return_icon(
  977. 'up_na.png',
  978. get_lang('Up'),
  979. array(),
  980. ICON_SIZE_SMALL
  981. ) . '</a>';
  982. }
  983. // DISPLAY MOVE DOWN COMMAND only if it is not the bottom link.
  984. if ($currentCategory < $countCategories-1) {
  985. $tools .= '<a href="' . api_get_self() . '?' . api_get_cidreq() .'&sec_token=' . $token .'&action=down&down=' . $categoryId .'&category_id=' . $categoryId . '">'.
  986. Display:: return_icon(
  987. 'down.png',
  988. get_lang('Down'),
  989. array(),
  990. ICON_SIZE_SMALL
  991. ) . '</a>';
  992. } else {
  993. $tools .= Display:: return_icon(
  994. 'down_na.png',
  995. get_lang('Down'),
  996. array(),
  997. ICON_SIZE_SMALL
  998. ) . '</a>';
  999. }
  1000. $tools .= '<a href="' . api_get_self() . '?' . api_get_cidreq() .'&sec_token=' . $token .'&action=deletecategory&id='.$categoryId. "&category_id=$categoryId\"
  1001. onclick=\"javascript: if(!confirm('" . get_lang('CategoryDelconfirm') . "')) return false;\">".
  1002. Display:: return_icon(
  1003. 'delete.png',
  1004. get_lang('Delete'),
  1005. array(),
  1006. ICON_SIZE_SMALL
  1007. ) . '</a>';
  1008. return $tools;
  1009. }
  1010. /**
  1011. * move a link or a linkcategory up or down
  1012. * @param int Category ID
  1013. * @param int Course ID
  1014. * @param int Session ID
  1015. * @author Patrick Cool <patrick.cool@UGent.be>, Ghent University
  1016. * @todo support sessions
  1017. */
  1018. public static function movecatlink($action, $catlinkid, $courseId = null, $sessionId = null)
  1019. {
  1020. $tbl_link = Database:: get_course_table(TABLE_LINK);
  1021. $tbl_categories = Database:: get_course_table(TABLE_LINK_CATEGORY);
  1022. if (is_null($courseId)) {
  1023. $courseId = api_get_course_int_id();
  1024. }
  1025. $courseId = intval($courseId);
  1026. if (is_null($sessionId)) {
  1027. $sessionId = api_get_session_id();
  1028. }
  1029. $sessionId = intval($sessionId);
  1030. if ($action == 'down') {
  1031. $thiscatlinkId = intval($catlinkid);
  1032. $sortDirection = 'DESC';
  1033. }
  1034. if ($action == 'up') {
  1035. $thiscatlinkId = intval($catlinkid);
  1036. $sortDirection = 'ASC';
  1037. }
  1038. // We check if it is a category we are moving or a link.
  1039. // If it is a category, a querystring catmove = true is present in the url.
  1040. $catmove = 'true';
  1041. if ($catmove == 'true') {
  1042. $movetable = $tbl_categories;
  1043. $catid = $catlinkid;
  1044. } else {
  1045. $movetable = $tbl_link;
  1046. // Getting the category of the link.
  1047. if (!empty ($thiscatlinkId)) {
  1048. $sql = "SELECT category_id FROM " . $movetable . "
  1049. WHERE c_id = $courseId AND id='$thiscatlinkId'";
  1050. $result = Database:: query($sql);
  1051. $catid = Database:: fetch_array($result);
  1052. }
  1053. }
  1054. // This code is copied and modified from announcements.php.
  1055. if (!empty($sortDirection)) {
  1056. if (!in_array(trim(strtoupper($sortDirection)), array('ASC', 'DESC'))) {
  1057. $sortDirection = 'ASC';
  1058. }
  1059. if ($catmove == 'true') {
  1060. $sql = "SELECT id, display_order FROM $movetable
  1061. WHERE c_id = $courseId
  1062. ORDER BY display_order $sortDirection";
  1063. } else {
  1064. $sql = "SELECT id, display_order FROM $movetable
  1065. WHERE c_id = $courseId AND category_id='" . $catid[0] . "'
  1066. ORDER BY display_order $sortDirection";
  1067. }
  1068. $linkresult = Database:: query($sql);
  1069. $thislinkOrder = 1;
  1070. while ($sortrow = Database:: fetch_array($linkresult)) {
  1071. // STEP 2 : FOUND THE NEXT LINK ID AND ORDER, COMMIT SWAP
  1072. // This part seems unlogic, but it isn't . We first look for the current link with the querystring ID
  1073. // and we know the next iteration of the while loop is the next one. These should be swapped.
  1074. if (isset($thislinkFound) && $thislinkFound) {
  1075. $nextlinkId = $sortrow['id'];
  1076. $nextlinkOrder = $sortrow['display_order'];
  1077. Database:: query(
  1078. "UPDATE " . $movetable . "
  1079. SET display_order = '$nextlinkOrder'
  1080. WHERE c_id = $courseId AND id = '$thiscatlinkId'"
  1081. );
  1082. Database:: query(
  1083. "UPDATE " . $movetable . "
  1084. SET display_order = '$thislinkOrder'
  1085. WHERE c_id = $courseId AND id = '$nextlinkId'"
  1086. );
  1087. break;
  1088. }
  1089. if ($sortrow['id'] == $thiscatlinkId) {
  1090. $thislinkOrder = $sortrow['display_order'];
  1091. $thislinkFound = true;
  1092. }
  1093. }
  1094. }
  1095. Display::addFlash(Display::return_message(get_lang('LinkMoved')));
  1096. }
  1097. /**
  1098. * CSV file import functions
  1099. * @author René Haentjens , Ghent University
  1100. */
  1101. public static function get_cat($catname)
  1102. {
  1103. // Get category id (existing or make new).
  1104. $tbl_categories = Database:: get_course_table(TABLE_LINK_CATEGORY);
  1105. $course_id = api_get_course_int_id();
  1106. $result = Database:: query(
  1107. "SELECT id FROM " . $tbl_categories . "
  1108. WHERE c_id = $course_id AND category_title='" . Database::escape_string(
  1109. $catname
  1110. ) . "'"
  1111. );
  1112. if (Database:: num_rows($result) >= 1 && ($row = Database:: fetch_array(
  1113. $result
  1114. ))
  1115. ) {
  1116. return $row['id']; // Several categories with same name: take the first.
  1117. }
  1118. $result = Database:: query(
  1119. "SELECT MAX(display_order) FROM " . $tbl_categories . " WHERE c_id = $course_id "
  1120. );
  1121. list ($max_order) = Database:: fetch_row($result);
  1122. $params = [
  1123. 'c_id' => $course_id,
  1124. 'category_title' => $catname,
  1125. 'description' => '',
  1126. 'display_order' => $max_order + 1
  1127. ];
  1128. $id = Database::insert($tbl_categories, $params);
  1129. return $id;
  1130. }
  1131. /**
  1132. * CSV file import functions
  1133. * @author René Haentjens , Ghent University
  1134. */
  1135. public static function put_link($url, $cat, $title, $description, $on_homepage, $hidden)
  1136. {
  1137. $_course = api_get_course_info();
  1138. $_user = api_get_user_info();
  1139. $tbl_link = Database:: get_course_table(TABLE_LINK);
  1140. $course_id = api_get_course_int_id();
  1141. $urleq = "url='" . Database:: escape_string($url) . "'";
  1142. $cateq = "category_id=" . intval($cat);
  1143. $result = Database:: query("
  1144. SELECT id FROM $tbl_link
  1145. WHERE c_id = $course_id AND " . $urleq . ' AND ' . $cateq
  1146. );
  1147. if (Database:: num_rows($result) >= 1 && ($row = Database:: fetch_array(
  1148. $result
  1149. ))
  1150. ) {
  1151. Database:: query(
  1152. "UPDATE $tbl_link set title='" . Database:: escape_string(
  1153. $title
  1154. ) . "', description='" . Database:: escape_string(
  1155. $description
  1156. ) . "'
  1157. WHERE c_id = $course_id AND id='" . Database:: escape_string(
  1158. $row['id']
  1159. ) . "'"
  1160. );
  1161. $ipu = 'LinkUpdated';
  1162. $rv = 1; // 1 = upd
  1163. } else {
  1164. // Add new link
  1165. $result = Database:: query(
  1166. "SELECT MAX(display_order) FROM $tbl_link
  1167. WHERE c_id = $course_id AND category_id='" . intval($cat) . "'"
  1168. );
  1169. list ($max_order) = Database:: fetch_row($result);
  1170. Database:: query(
  1171. "INSERT INTO $tbl_link (c_id, url, title, description, category_id, display_order, on_homepage)
  1172. VALUES (" . api_get_course_int_id() . ",
  1173. '" . Database:: escape_string($url) . "',
  1174. '" . Database:: escape_string($title) . "',
  1175. '" . Database:: escape_string($description) . "',
  1176. '" . intval($cat) . "','" . (intval($max_order) + 1) . "',
  1177. '" . intval($on_homepage) .
  1178. "')"
  1179. );
  1180. $id = Database:: insert_id();
  1181. $ipu = 'LinkAdded';
  1182. $rv = 2; // 2 = new
  1183. }
  1184. api_item_property_update(
  1185. $_course,
  1186. TOOL_LINK,
  1187. $id,
  1188. $ipu,
  1189. $_user['user_id']
  1190. );
  1191. if ($hidden && $ipu == 'LinkAdded') {
  1192. api_item_property_update(
  1193. $_course,
  1194. TOOL_LINK,
  1195. $id,
  1196. 'invisible',
  1197. $_user['user_id']
  1198. );
  1199. }
  1200. return $rv;
  1201. }
  1202. /**
  1203. * CSV file import functions
  1204. * @author René Haentjens , Ghent University
  1205. */
  1206. public static function import_link($linkdata)
  1207. {
  1208. // url, category_id, title, description, ...
  1209. // Field names used in the uploaded file
  1210. $known_fields = array(
  1211. 'url',
  1212. 'category',
  1213. 'title',
  1214. 'description',
  1215. 'on_homepage',
  1216. 'hidden'
  1217. );
  1218. $hide_fields = array(
  1219. 'kw',
  1220. 'kwd',
  1221. 'kwds',
  1222. 'keyword',
  1223. 'keywords'
  1224. );
  1225. // All other fields are added to description, as "name:value".
  1226. // Only one hide_field is assumed to be present, <> is removed from value.
  1227. if (!($url = trim($linkdata['url'])) || !($title = trim(
  1228. $linkdata['title']
  1229. ))
  1230. ) {
  1231. return 0; // 0 = fail
  1232. }
  1233. $cat = ($catname = trim($linkdata['category'])) ? Link::get_cat($catname) : 0;
  1234. $regs = array(); // Will be passed to ereg()
  1235. $d = '';
  1236. foreach ($linkdata as $key => $value) {
  1237. if (!in_array($key, $known_fields)) {
  1238. if (in_array($key, $hide_fields) && ereg(
  1239. '^<?([^>]*)>?$',
  1240. $value,
  1241. $regs
  1242. )
  1243. ) { // possibly in <...>
  1244. if (($kwlist = trim($regs[1])) != '') {
  1245. $kw = '<i kw="' . htmlspecialchars($kwlist) . '">';
  1246. } else {
  1247. $kw = '';
  1248. }
  1249. // i.e. assume only one of the $hide_fields will be present
  1250. // and if found, hide the value as expando property of an <i> tag
  1251. } elseif (trim($value)) {
  1252. $d .= ', ' . $key . ':' . $value;
  1253. }
  1254. }
  1255. }
  1256. if (!empty($d)) {
  1257. $d = substr($d, 2) . ' - ';
  1258. }
  1259. return Link::put_link(
  1260. $url,
  1261. $cat,
  1262. $title,
  1263. $kw . ereg_replace(
  1264. '\[((/?(b|big|i|small|sub|sup|u))|br/)\]',
  1265. '<\\1>',
  1266. htmlspecialchars($d . $linkdata['description'])
  1267. ) . ($kw ? '</i>' : ''),
  1268. $linkdata['on_homepage'] ? '1' : '0',
  1269. $linkdata['hidden'] ? '1' : '0'
  1270. );
  1271. // i.e. allow some BBcode tags, e.g. [b]...[/b]
  1272. }
  1273. /**
  1274. * This function checks if the url is a vimeo link
  1275. * @author Julio Montoya
  1276. * @version 1.0
  1277. */
  1278. public static function isVimeoLink($url)
  1279. {
  1280. $isLink = strrpos($url, "vimeo.com");
  1281. return $isLink;
  1282. }
  1283. /**
  1284. * Get vimeo id from URL
  1285. * @param string $url
  1286. * @return bool|mixed
  1287. */
  1288. public static function getVimeoLinkId($url)
  1289. {
  1290. $possibleUrls = array(
  1291. 'http://www.vimeo.com/',
  1292. 'http://vimeo.com/',
  1293. 'https://www.vimeo.com/',
  1294. 'https://vimeo.com/'
  1295. );
  1296. $url = str_replace($possibleUrls, '', $url);
  1297. if (is_numeric($url)) {
  1298. return $url;
  1299. }
  1300. return false;
  1301. }
  1302. /**
  1303. * This function checks if the url is a youtube link
  1304. * @author Jorge Frisancho
  1305. * @author Julio Montoya - Fixing code
  1306. * @version 1.0
  1307. */
  1308. public static function is_youtube_link($url)
  1309. {
  1310. $is_youtube_link = strrpos($url, "youtube") || strrpos(
  1311. $url,
  1312. "youtu.be"
  1313. );
  1314. return $is_youtube_link;
  1315. }
  1316. /**
  1317. * Get youtube id from an URL
  1318. * @param string $url
  1319. * @return string
  1320. */
  1321. public static function get_youtube_video_id($url)
  1322. {
  1323. // This is the length of YouTube's video IDs
  1324. $len = 11;
  1325. // The ID string starts after "v=", which is usually right after
  1326. // "youtube.com/watch?" in the URL
  1327. $pos = strpos($url, "v=");
  1328. $id = '';
  1329. //If false try other options
  1330. if ($pos === false) {
  1331. $url_parsed = parse_url($url);
  1332. //Youtube shortener
  1333. //http://youtu.be/ID
  1334. $pos = strpos($url, "youtu.be");
  1335. if ($pos == false) {
  1336. $id = '';
  1337. } else {
  1338. return substr($url_parsed['path'], 1);
  1339. }
  1340. //if empty try the youtube.com/embed/ID
  1341. if (empty($id)) {
  1342. $pos = strpos($url, "embed");
  1343. if ($pos === false) {
  1344. return '';
  1345. } else {
  1346. return substr($url_parsed['path'], 7);
  1347. }
  1348. }
  1349. } else {
  1350. // Offset the start location to match the beginning of the ID string
  1351. $pos += 2;
  1352. // Get the ID string and return it
  1353. $id = substr($url, $pos, $len);
  1354. return $id;
  1355. }
  1356. }
  1357. /**
  1358. * @param int $course_id
  1359. * @param int $session_id
  1360. * @param int $categoryId
  1361. * @param string $show
  1362. * @param null $token
  1363. */
  1364. public static function listLinksAndCategories($course_id, $session_id, $categoryId, $show = 'none', $token = null)
  1365. {
  1366. $tbl_link = Database::get_course_table(TABLE_LINK);
  1367. $_user = api_get_user_info();
  1368. $categoryId = intval($categoryId);
  1369. /* Action Links */
  1370. echo '<div class="actions">';
  1371. if (api_is_allowed_to_edit(null, true)) {
  1372. echo '<a href="'.api_get_self().'?'.api_get_cidreq().'&action=addlink&category_id='.$categoryId.'">'.
  1373. Display::return_icon('new_link.png', get_lang('LinkAdd'),'',ICON_SIZE_MEDIUM).'</a>';
  1374. echo '<a href="'.api_get_self().'?'.api_get_cidreq().'&action=addcategory&category_id='.$categoryId.'">'.
  1375. Display::return_icon('new_folder.png', get_lang('CategoryAdd'),'',ICON_SIZE_MEDIUM).'</a>';
  1376. }
  1377. $categories = Link::getLinkCategories($course_id, $session_id);
  1378. $count = count($categories);
  1379. if (!empty($count)) {
  1380. echo '<a href="'.api_get_self().'?'.api_get_cidreq().'&action=list&show=none">';
  1381. echo Display::return_icon('forum_listview.png', get_lang('FlatView'), '', ICON_SIZE_MEDIUM) . ' </a>';
  1382. echo '<a href="'.api_get_self().'?'.api_get_cidreq().'&action=list&show=all">';
  1383. echo Display::return_icon('forum_nestedview.png', get_lang('NestedView'), '', ICON_SIZE_MEDIUM) . '</a>';
  1384. }
  1385. echo '</div>';
  1386. // Displaying the links which have no category (thus category = 0 or NULL),
  1387. // if none present this will not be displayed
  1388. $sql = "SELECT * FROM $tbl_link
  1389. WHERE c_id = $course_id AND (category_id=0 OR category_id IS NULL)";
  1390. $result = Database::query($sql);
  1391. $count = Database::num_rows($result);
  1392. if ($count !== 0) {
  1393. echo Display::panel(Link::showlinksofcategory(0), get_lang('General'));
  1394. }
  1395. $counter = 0;
  1396. foreach ($categories as $myrow) {
  1397. // Student don't see invisible categories.
  1398. if (!api_is_allowed_to_edit(null, true)) {
  1399. if ($myrow['visibility'] == 0) {
  1400. continue;
  1401. }
  1402. }
  1403. // Validation when belongs to a session
  1404. $showChildren = $categoryId == $myrow['id'] || $show == 'all';
  1405. $session_img = api_get_session_image($myrow['session_id'], $_user['status']);
  1406. $myrow['description'] = $myrow['description'];
  1407. $strVisibility = '';
  1408. $visibilityClass = null;
  1409. if ($myrow['visibility'] == '1') {
  1410. $strVisibility = '<a href="link.php?' . api_get_cidreq() . '&sec_token='.$token.'&action=invisible&id=' . $myrow['id'] . '&scope=' . TOOL_LINK_CATEGORY . '" title="' . get_lang('Hide') . '">' .
  1411. Display :: return_icon('visible.png', get_lang('Hide'), array (), ICON_SIZE_SMALL) . '</a>';
  1412. } elseif ($myrow['visibility'] == '0') {
  1413. $visibilityClass = 'invisible';
  1414. $strVisibility = ' <a href="link.php?' . api_get_cidreq() . '&sec_token='.$token.'&action=visible&id=' . $myrow['id'] . '&scope=' . TOOL_LINK_CATEGORY . '" title="' . get_lang('Show') . '">' .
  1415. Display :: return_icon('invisible.png', get_lang('Show'), array (), ICON_SIZE_SMALL) . '</a>';
  1416. }
  1417. $header = '';
  1418. if ($showChildren) {
  1419. $header .= '<a class="'.$visibilityClass.'" href="'.api_get_self().'?'.api_get_cidreq().'&category_id=">';
  1420. $header .= Display::return_icon('forum_nestedview.png');
  1421. } else {
  1422. $header .= '<a class="'.$visibilityClass.'" href="'.api_get_self().'?'.api_get_cidreq().'&category_id='.$myrow['id'].'">';
  1423. $header .= Display::return_icon('forum_listview.png');
  1424. }
  1425. $header .= Security::remove_XSS($myrow['category_title']).'</a>';
  1426. $header .= '<div class="pull-right">';
  1427. if (api_is_allowed_to_edit(null, true)) {
  1428. if ($session_id == $myrow['session_id']) {
  1429. $header .= $strVisibility;
  1430. $header .= Link::showCategoryAdminTools($myrow, $counter, count($categories));
  1431. } else {
  1432. $header .= get_lang('EditionNotAvailableFromSession');
  1433. }
  1434. }
  1435. $childrenContent = '';
  1436. if ($showChildren) {
  1437. $childrenContent = Link::showlinksofcategory($myrow['id']);
  1438. }
  1439. echo Display::panel($myrow['description'].$childrenContent, $header);
  1440. $counter++;
  1441. }
  1442. }
  1443. /**
  1444. * @param int $linkId
  1445. * @param $action
  1446. * @param null $urlview
  1447. * @param null $token
  1448. * @return FormValidator
  1449. */
  1450. public static function getLinkForm($linkId, $action, $token = null)
  1451. {
  1452. $course_id = api_get_course_int_id();
  1453. $session_id = api_get_session_id();
  1454. $linkInfo = Link::get_link_info($linkId);
  1455. $categoryId = isset($linkInfo['category_id']) ? $linkInfo['category_id'] : '';
  1456. $lpId = isset($_GET['lp_id']) ? Security::remove_XSS($_GET['lp_id']) : null;
  1457. $form = new FormValidator(
  1458. 'link',
  1459. 'post',
  1460. api_get_self().'?action='.$action.
  1461. '&category_id='.$categoryId.
  1462. '&'.api_get_cidreq().
  1463. '&id='.$linkId.
  1464. '&sec_token='.$token
  1465. );
  1466. if ($action == 'addlink') {
  1467. $form->addHeader(get_lang('LinkAdd'));
  1468. } else {
  1469. $form->addHeader(get_lang('LinkMod'));
  1470. }
  1471. $target_link = "_blank";
  1472. $title = '';
  1473. $category = '';
  1474. $onhomepage = '';
  1475. $description = '';
  1476. if (!empty($linkInfo)) {
  1477. $urllink = $linkInfo['url'];
  1478. $title = $linkInfo['title'];
  1479. $description = $linkInfo['description'];
  1480. $category = $linkInfo['category_id'];
  1481. if ($linkInfo['on_homepage'] != 0) {
  1482. $onhomepage = 1;
  1483. }
  1484. $target_link = $linkInfo['target'];
  1485. }
  1486. $form->addHidden('id', $linkId);
  1487. $form->addText('url', 'URL');
  1488. $form->addRule('url', get_lang('GiveURL'), 'url');
  1489. $form->addText('title', get_lang('LinkName'));
  1490. $form->addTextarea('description', get_lang('Description'));
  1491. $resultcategories = Link::getLinkCategories($course_id, $session_id);
  1492. $options = ['0' => '--'];
  1493. if (!empty($resultcategories)) {
  1494. foreach ($resultcategories as $myrow) {
  1495. $options[$myrow['id']] = $myrow['category_title'];
  1496. }
  1497. }
  1498. $form->addSelect('category_id', get_lang('Category'), $options);
  1499. $form->addCheckBox('on_homepage', null, get_lang('OnHomepage'));
  1500. $targets = array(
  1501. '_self' => get_lang('LinkOpenSelf'),
  1502. '_blank' => get_lang('LinkOpenBlank'),
  1503. '_parent' => get_lang('LinkOpenParent'),
  1504. '_top' => get_lang('LinkOpenTop')
  1505. );
  1506. $form->addSelect(
  1507. 'target',
  1508. array(
  1509. get_lang('LinkTarget'),
  1510. get_lang('AddTargetOfLinkOnHomepage')
  1511. ),
  1512. $targets
  1513. );
  1514. $defaults = array(
  1515. 'url' => empty($urllink) ? 'http://' : Security::remove_XSS($urllink),
  1516. 'title' => Security::remove_XSS($title),
  1517. 'category_id' => $category,
  1518. 'on_homepage' => $onhomepage,
  1519. 'description' => $description,
  1520. 'target' => $target_link
  1521. );
  1522. if (api_get_setting('search_enabled') == 'true') {
  1523. require_once api_get_path(LIBRARY_PATH).'specific_fields_manager.lib.php';
  1524. $specific_fields = get_specific_field_list();
  1525. $form->addCheckBox('index_document', get_lang('SearchFeatureDoIndexLink'), get_lang('Yes'));
  1526. foreach ($specific_fields as $specific_field) {
  1527. $default_values = '';
  1528. if ($action == 'editlink') {
  1529. $filter = array(
  1530. 'field_id' => $specific_field['id'],
  1531. 'ref_id' => intval($_GET['id']),
  1532. 'tool_id' => '\''.TOOL_LINK.'\''
  1533. );
  1534. $values = get_specific_field_values_list($filter, array('value'));
  1535. if (!empty($values)) {
  1536. $arr_str_values = array();
  1537. foreach ($values as $value) {
  1538. $arr_str_values[] = $value['value'];
  1539. }
  1540. $default_values = implode(', ', $arr_str_values);
  1541. }
  1542. }
  1543. $form->addText($specific_field['name'], $specific_field['code']);
  1544. $defaults[$specific_field['name']] = $default_values;
  1545. }
  1546. }
  1547. $form->addHidden('lp_id', $lpId);
  1548. $form->addButtonSave(get_lang('SaveLink'), 'submitLink');
  1549. $form->setDefaults($defaults);
  1550. return $form;
  1551. }
  1552. /**
  1553. * @param int $id
  1554. * @param string $action
  1555. *
  1556. * @return FormValidator
  1557. */
  1558. public static function getCategoryForm($id, $action)
  1559. {
  1560. $form = new FormValidator(
  1561. 'category',
  1562. 'post',
  1563. api_get_self().'?action='.$action.'&'.api_get_cidreq()
  1564. );
  1565. $defaults = [];
  1566. if ($action == 'addcategory') {
  1567. $form->addHeader(get_lang('CategoryAdd'));
  1568. $my_cat_title = get_lang('CategoryAdd');
  1569. } else {
  1570. $form->addHeader(get_lang('CategoryMod'));
  1571. $my_cat_title = get_lang('CategoryMod');
  1572. $defaults = self::getCategory($id);
  1573. }
  1574. $form->addHidden('id', $id);
  1575. $form->addText('category_title', get_lang('CategoryName'));
  1576. $form->addTextarea('description', get_lang('Description'));
  1577. $form->addButtonSave($my_cat_title, 'submitCategory');
  1578. $form->setDefaults($defaults);
  1579. return $form;
  1580. }
  1581. /**
  1582. * @param int $id
  1583. * @return array
  1584. */
  1585. public static function getCategory($id)
  1586. {
  1587. $table = Database::get_course_table(TABLE_LINK_CATEGORY);
  1588. $id = intval($id);
  1589. $courseId = api_get_course_int_id();
  1590. $sql = "SELECT * FROM $table WHERE id = $id AND c_id = $courseId";
  1591. $result = Database::query($sql);
  1592. $category = Database::fetch_array($result, 'ASSOC');
  1593. return $category;
  1594. }
  1595. }