PageRenderTime 25ms CodeModel.GetById 16ms RepoModel.GetById 0ms app.codeStats 0ms

/php/complex_display/component/survey_menu.class.php

https://bitbucket.org/chamilo/chamilo-survey/
PHP | 692 lines | 459 code | 132 blank | 101 comment | 50 complexity | d6cf6e02df1d531c7f34b712ed1799ed MD5 | raw file
  1. <?php
  2. namespace repository\content_object\survey;
  3. use common\libraries\Utilities;
  4. use common\libraries\Path;
  5. use common\libraries\EqualityCondition;
  6. use common\libraries\ObjectTableOrder;
  7. use common\libraries\OptionsMenuRenderer;
  8. use common\libraries\TreeMenuRenderer;
  9. use common\libraries\Translation;
  10. use common\libraries\Theme;
  11. use repository\content_object\survey_page\SurveyPage;
  12. use repository\content_object\survey_description\ComplexSurveyDescription;
  13. use repository\RepositoryDataManager;
  14. use HTML_Menu;
  15. use HTML_Menu_ArrayRenderer;
  16. class SurveyMenu extends HTML_Menu
  17. {
  18. const TREE_NAME = __CLASS__;
  19. const MENU_ITEM_TYPE = 'type';
  20. const TYPE_SURVYEY = 'survey';
  21. const TYPE_CONTEXT = 'survey_context';
  22. const TYPE_PAGE = 'survey_page';
  23. const TYPE_QUESTION = 'survey_question';
  24. const ID = 'id';
  25. const PARENT_ID = 'parent_id';
  26. const CONTEXT_ID = 'context_id';
  27. const PAGE_ID = 'page_id';
  28. const QUESTION_ID = 'question_id';
  29. private $urlFmt;
  30. /**
  31. * @var Survey
  32. */
  33. private $survey;
  34. private $survey_id;
  35. private $user_id;
  36. private $publication_id;
  37. private $context_path_relations;
  38. private $parent_ids;
  39. private $page_contexts;
  40. private $questions_contexts;
  41. private $finished_questions;
  42. private $question_count;
  43. private $visible_question_count;
  44. private $parent;
  45. private $page_nrs;
  46. private $page_nr = 1;
  47. private $question_nrs;
  48. private $question_nr = 1;
  49. private $sub_question_nr = 1;
  50. private $page_answers;
  51. private $new_context_id;
  52. private $first_page_url = false;
  53. private $context_urls;
  54. function __construct($parent, $current_context_path, $url_format, $survey)
  55. {
  56. $this->parent = $parent;
  57. $this->survey = $survey;
  58. $this->survey_id = $this->survey->get_id();
  59. $this->user_id = $parent->get_parameter(SurveyDisplaySurveyViewerComponent :: PARAM_INVITEE_ID);
  60. $this->publication_id = $parent->get_parameter(SurveyDisplaySurveyViewerComponent :: PARAM_PUBLICATION_ID);
  61. $this->urlFmt = $url_format;
  62. $menu = $this->get_menu();
  63. parent :: __construct($menu);
  64. $this->forceCurrentUrl($this->get_url($current_context_path));
  65. }
  66. function get_menu()
  67. {
  68. $this->create_context_path_relations();
  69. $this->visible_question_count = 0;
  70. // dump($this->context_path_relations);
  71. // $this->get_menu_items();
  72. return $this->get_menu_items();
  73. // dump($this->question_nrs);
  74. // exit;
  75. }
  76. function create_context_path_relations()
  77. {
  78. $context_paths = $this->survey->get_context_paths();
  79. $this->context_path_relations = array();
  80. $has_context = $this->survey->has_context();
  81. $page_count = 0;
  82. foreach ($context_paths as $index => $context_path)
  83. {
  84. if ($has_context)
  85. {
  86. $context_path_ids = explode('|', $context_path);
  87. $parent_path = $context_path_ids[0] . '|' . $context_path_ids[1];
  88. $path_ids = explode('_', $context_path_ids[2]);
  89. }
  90. else
  91. {
  92. $path_ids = explode('_', $context_path);
  93. }
  94. $id_count = count($path_ids);
  95. //questions
  96. $context = array();
  97. $question_id = $path_ids[$id_count - 1];
  98. $context[self :: QUESTION_ID] = $question_id;
  99. array_pop($path_ids);
  100. if ($has_context)
  101. {
  102. $question_parent_context = $parent_path . '|' . $path_ids[0];
  103. }
  104. else
  105. {
  106. $question_parent_context = implode('_', $path_ids);
  107. }
  108. $context[self :: PARENT_ID] = $question_parent_context;
  109. $context[self :: ID] = $context_path;
  110. $context[self :: MENU_ITEM_TYPE] = self :: TYPE_QUESTION;
  111. $this->context_path_relations[$context_path] = $context;
  112. if (! $this->questions_contexts[$context_path])
  113. {
  114. $this->question_count ++;
  115. // $this->questions_contexts[$question_parent_context] = $this->question_count;
  116. $this->questions_contexts[$context_path] = $this->question_count;
  117. }
  118. //pages
  119. $context = array();
  120. $page_id = $path_ids[$id_count - 2];
  121. $context[self :: PAGE_ID] = $page_id;
  122. array_pop($path_ids);
  123. if ($has_context)
  124. {
  125. $page_parent_context = $parent_path;
  126. }
  127. else
  128. {
  129. $page_parent_context = implode('_', $path_ids);
  130. }
  131. $context[self :: PARENT_ID] = $page_parent_context;
  132. $context[self :: ID] = $question_parent_context;
  133. $context[self :: MENU_ITEM_TYPE] = self :: TYPE_PAGE;
  134. $this->context_path_relations[$question_parent_context] = $context;
  135. if (! $this->page_contexts[$question_parent_context])
  136. {
  137. $page_count ++;
  138. $this->page_contexts[$question_parent_context] = $page_count;
  139. }
  140. $parent_ids[] = $page_parent_context;
  141. }
  142. $parent_ids = array_unique($parent_ids);
  143. $level_count = $this->survey->count_levels();
  144. $levels = $level_count + 1;
  145. $level = $levels;
  146. while ($level >= 1)
  147. {
  148. foreach ($parent_ids as $index => $context_path)
  149. {
  150. if ($has_context)
  151. {
  152. $context_path_ids = explode('|', $context_path);
  153. $path_ids = explode('_', $context_path_ids[1]);
  154. $id_count = count($path_ids) + 1;
  155. $count = count($path_ids);
  156. }
  157. else
  158. {
  159. $path_ids = explode('_', $context_path);
  160. $id_count = count($path_ids);
  161. }
  162. if ($id_count == $level)
  163. {
  164. $context = array();
  165. $context[self :: ID] = $context_path;
  166. if ($has_context)
  167. {
  168. $context[self :: CONTEXT_ID] = $path_ids[$count - 1];
  169. }
  170. else
  171. {
  172. $context[self :: CONTEXT_ID] = $path_ids[$id_count - 1];
  173. }
  174. if ($level == 1)
  175. {
  176. $parent_id = 0;
  177. $context[self :: MENU_ITEM_TYPE] = self :: TYPE_SURVYEY;
  178. }
  179. else
  180. {
  181. array_pop($path_ids);
  182. if (count($path_ids) > 0)
  183. {
  184. if ($has_context)
  185. {
  186. $parent_id = $context_path_ids[0] . '|' . implode('_', $path_ids);
  187. }
  188. else
  189. {
  190. $parent_id = implode('_', $path_ids);
  191. }
  192. }
  193. else
  194. {
  195. if ($has_context)
  196. {
  197. $parent_id = $context_path_ids[0];
  198. }
  199. else
  200. {
  201. $parent_id = implode('_', $path_ids);
  202. }
  203. }
  204. //
  205. $parent_ids[] = $parent_id;
  206. $context[self :: MENU_ITEM_TYPE] = self :: TYPE_CONTEXT;
  207. }
  208. $context[self :: PARENT_ID] = $parent_id;
  209. $this->context_path_relations[$context_path] = $context;
  210. unset($parent_ids[$index]);
  211. }
  212. }
  213. $level --;
  214. }
  215. if ($has_context)
  216. {
  217. $context = array();
  218. $context[self :: ID] = $this->survey_id;
  219. $context[self :: CONTEXT_ID] = $this->survey_id;
  220. $context[self :: MENU_ITEM_TYPE] = self :: TYPE_SURVYEY;
  221. $context[self :: PARENT_ID] = 0;
  222. $this->context_path_relations[$this->survey_id] = $context;
  223. }
  224. // dump($this->context_path_relations);
  225. // $index = 0;
  226. // foreach ($this->context_path_relations as $this->context_path_relation)
  227. // {
  228. // if($this->context_path_relation['type'] = self :: TYPE_CONTEXT){
  229. // $index++;
  230. //// dump($this->context_path_relation);
  231. // }
  232. // }
  233. // dump($index);
  234. // exit();
  235. }
  236. /**
  237. * Returns the menu items.
  238. * @return array An array with all menu items. The structure of this array
  239. * is the structure needed by PEAR::HTML_Menu, on which this
  240. * class is based.
  241. */
  242. private function get_menu_items($parent_id = 0, $path = null, $current_url = null, $page_id)
  243. {
  244. $menu = array();
  245. // $this->page_answers = array();
  246. $level_count = $this->survey->count_levels();
  247. if (! $current_url)
  248. {
  249. $current_url = $this->get_url($path);
  250. }
  251. // dump($this->context_path_relations);
  252. foreach ($this->context_path_relations as $context_path => $context_path_relation)
  253. {
  254. $parent_id = '' . $parent_id;
  255. if ($context_path_relation[self :: PARENT_ID] == $parent_id)
  256. {
  257. $path_ids = explode('_', $context_path);
  258. $id_count = count($path_ids);
  259. $type = $context_path_relation[self :: MENU_ITEM_TYPE];
  260. if ($type == self :: TYPE_PAGE)
  261. {
  262. $page_id = $context_path_relation[self :: PAGE_ID];
  263. $this->page_nrs[$context_path] = $this->page_nr;
  264. $this->page_nr ++;
  265. $this->sub_question_nr=1;
  266. unset($this->page_answers);
  267. }
  268. if ($type == self :: TYPE_QUESTION)
  269. {
  270. }
  271. $menu_item = array();
  272. $visible = true;
  273. switch ($type)
  274. {
  275. case self :: TYPE_SURVYEY :
  276. $title = $this->survey->get_title();
  277. $title = Survey :: parse($this->get_survey()->get_invitee_id(), $context_path, $title);
  278. $menu_item['class'] = self :: TYPE_SURVYEY;
  279. $menu_item['url'] = $current_url;
  280. break;
  281. case self :: TYPE_CONTEXT :
  282. $context = SurveyContextDataManager :: get_instance()->retrieve_survey_context_by_id($context_path_relation[self :: CONTEXT_ID]);
  283. $title = $context->get_name();
  284. $menu_item['class'] = self :: TYPE_CONTEXT;
  285. $this->new_context_id = $context->get_id();
  286. if ($this->first_page_url)
  287. {
  288. }
  289. $this->first_page_url = true;
  290. // dump('incontext');
  291. $in_context = true;
  292. // dump($context_path_relation);
  293. // $menu_item['url'] = $this->context_urls[$context_path_relation[self :: CONTEXT_ID]];
  294. break;
  295. case self :: TYPE_PAGE :
  296. $survey_page = $this->survey->get_page_by_id($context_path_relation[self :: PAGE_ID]);
  297. $this->set_page_visible_question_answers($survey_page, $context_path);
  298. $title = $survey_page->get_title();
  299. $title = Survey :: parse($this->get_survey()->get_invitee_id(), $context_path, $title);
  300. $title = $this->page_nrs[$context_path].' '.$title;
  301. // $title = 'page ' . $this->page_contexts[$context_path] . ' title: ' . $title;
  302. $menu_item['class'] = self :: TYPE_PAGE . '_tree';
  303. $current_url = $this->get_url($context_path);
  304. $menu_item['url'] = $current_url;
  305. if ($this->first_page_url)
  306. {
  307. $this->first_page_url = false;
  308. $in_firstpage = true;
  309. $c_ids = explode('|', $context_path);
  310. // dump($context_path_relation);
  311. array_pop($c_ids);
  312. $c_id = implode('|', $c_ids);
  313. $c_parent_id = $context_path_relation[self :: PARENT_ID];
  314. $this->context_urls[$c_parent_id] = $current_url;
  315. $p_c_ids = explode('|', $c_parent_id);
  316. $path_c_ids = explode('_', $p_c_ids[1]);
  317. // dump($c_ids);
  318. array_pop($path_c_ids);
  319. $p_p_c_id = $p_c_ids[0] . '|' . implode('_', $path_c_ids);
  320. $p_c_id = implode('|', $c_ids);
  321. // dump($p_c_id);
  322. if (! array_key_exists($p_p_c_id, $this->context_urls))
  323. {
  324. // dump('notexist');
  325. $this->context_urls[$p_p_c_id] = $current_url;
  326. }
  327. // dump($this->context_urls);
  328. }
  329. // dump('inpage');
  330. // dump($this->new_context_id);
  331. // dump($context_path);
  332. // dump($menu);
  333. // exit;
  334. break;
  335. case self :: TYPE_QUESTION :
  336. $complex_question_id = $context_path_relation[self :: QUESTION_ID];
  337. $complex_question = RepositoryDataManager :: get_instance()->retrieve_complex_content_object_item($complex_question_id);
  338. $answer = $this->parent->get_answer($complex_question_id, $context_path);
  339. $is_description = $complex_question instanceof ComplexSurveyDescription;
  340. if (! $complex_question->is_visible())
  341. {
  342. $this->question_nrs[$context_path] = ($this->question_nr-1).'.'.$this->sub_question_nr;
  343. $this->sub_question_nr ++;
  344. // dump($complex_question_id);
  345. if (! $answer)
  346. {
  347. // dump('invisible');
  348. //
  349. // dump('questionpath');
  350. // dump($context_path);
  351. // $context_path_ids = explode('|' ,$context_path);
  352. // $last_index = count($context_path_ids)-1;
  353. // $ids = explode('_', $context_path_ids[$last_index]);
  354. // $page_id = $ids[0];
  355. // dump($page_id); dump($complex_question_id);
  356. if (! $this->is_question_visible($complex_question_id, $page_id))
  357. {
  358. $visible = false;
  359. }
  360. }
  361. }else{
  362. $this->question_nrs[$context_path] = $this->question_nr;
  363. $this->question_nr ++;
  364. }
  365. if ($answer)
  366. {
  367. $this->page_answers[$complex_question_id] = $answer;
  368. }
  369. // if ($visible)
  370. // {
  371. // dump('visible');
  372. // dump($complex_question_id);
  373. $question = RepositoryDataManager :: get_instance()->retrieve_content_object($complex_question->get_ref());
  374. $title = $question->get_title();
  375. $title = Survey :: parse($this->get_survey()->get_invitee_id(), $context_path, $title);
  376. $title = $this->question_nrs[$context_path].' '.$title;
  377. // $answer = $this->parent->get_answer($complex_question_id, $context_path);
  378. if ($answer)
  379. {
  380. $menu_item['class'] = $question->get_type_name() . '_checked';
  381. // $title = Theme :: get_common_image('status_ok_mini') . ' ' . $title;
  382. $this->finished_questions[] = $context_path;
  383. }
  384. else
  385. {
  386. $menu_item['class'] = $question->get_type_name();
  387. }
  388. $menu_item['url'] = $current_url . '#' . $complex_question_id;
  389. // }
  390. break;
  391. default :
  392. ;
  393. break;
  394. }
  395. if ($visible)
  396. {
  397. if ($type == self :: TYPE_QUESTION)
  398. {
  399. if (! $is_description)
  400. {
  401. $this->visible_question_count ++;
  402. }
  403. }
  404. $title = Utilities :: truncate_string($title, 50);
  405. $menu_item['title'] = $title;
  406. $menu_item[OptionsMenuRenderer :: KEY_ID] = $context_path;
  407. // dump('contextpathid');
  408. // dump($context_path_relation[self :: ID]);
  409. // $menu_item['title'] = $complex_question_id . " " . $title;
  410. // if($page_id){
  411. $sub_menu_items = $this->get_menu_items($context_path_relation[self :: ID], $context_path, $current_url, $page_id);
  412. // }
  413. if (count($sub_menu_items) > 0)
  414. {
  415. $menu_item['sub'] = $sub_menu_items;
  416. }
  417. // dump($this->context_urls);
  418. if ($in_context)
  419. {
  420. // dump('incontextmenu');
  421. // dump($context_path_relation);
  422. if (! $this->context_urls[$context_path_relation[self :: ID]])
  423. {
  424. // dump($this->context_urls);
  425. // dump($menu_item);
  426. }
  427. $menu_item['url'] = $this->context_urls[$context_path_relation[self :: ID]];
  428. // dump($menu_item);
  429. }
  430. // if($in_firstpage){
  431. // dump('infirstpagmenu');
  432. // dump($menu_item);
  433. // }
  434. // $menu_item[OptionsMenuRenderer :: KEY_ID] = $context_path;
  435. $menu[$context_path] = $menu_item;
  436. }
  437. }
  438. else
  439. {
  440. continue;
  441. }
  442. }
  443. // dump($this->page_contexts);
  444. // dump($menu);
  445. // exit;
  446. return $menu;
  447. }
  448. function get_url($context_path)
  449. {
  450. $test = sprintf($this->urlFmt, $this->publication_id, $this->survey_id, $context_path);
  451. // $test = $test . '&display_action=survey_viewer&_qf_page_' . $context_path . '_display=true';
  452. $test = $test . '&display_action=survey_viewer';
  453. return htmlentities($test);
  454. }
  455. function get_progress()
  456. {
  457. // dump(count($this->finished_questions));
  458. // dump($this->question_count);
  459. // dump($this->visible_question_count);
  460. return (count($this->finished_questions) / ($this->visible_question_count)) * 100;
  461. }
  462. function get_page_nr($page_context_path)
  463. {
  464. return $this->page_nrs[$page_context_path];
  465. }
  466. // function get_question_nr($question_context_path)
  467. // {
  468. // return $this->question_nrs[$question_context_path];
  469. // }
  470. function get_question_nrs()
  471. {
  472. return $this->question_nrs;
  473. }
  474. function get_page_nrs()
  475. {
  476. return $this->page_nrs;
  477. }
  478. function is_question_visible($guestion_id_tocheck, $page_id)
  479. {
  480. $survey_page = RepositoryDataManager :: get_instance()->retrieve_content_object($page_id);
  481. // dump($page_id);
  482. $configs = $survey_page->get_config();
  483. // dump($this->page_answers);
  484. // dump($configs);
  485. foreach ($configs as $config)
  486. {
  487. foreach ($this->page_answers as $question_id => $answer_to_match)
  488. {
  489. $from_question_id = $config[SurveyPage :: FROM_VISIBLE_QUESTION_ID];
  490. if ($question_id == $from_question_id)
  491. {
  492. $answer = $config[SurveyPage :: ANSWERMATCHES];
  493. $answers_to_match = array();
  494. foreach ($answer as $key => $value)
  495. {
  496. $oids = explode('_', $key);
  497. if (count($oids) == 2)
  498. {
  499. $answers_to_match[] = $oids[1];
  500. }
  501. elseif (count($oids) == 3)
  502. {
  503. $option = $oids[1];
  504. $answers_to_match[$option] = $value;
  505. }
  506. }
  507. $diff = array_diff($answers_to_match, $answer_to_match);
  508. // dump($guestion_id_tocheck);
  509. if (count($diff) == 0)
  510. {
  511. if (in_array($guestion_id_tocheck, $config[SurveyPage :: TO_VISIBLE_QUESTIONS_IDS]))
  512. {
  513. return true;
  514. }
  515. }
  516. }
  517. }
  518. }
  519. return false;
  520. }
  521. private function set_page_visible_question_answers(SurveyPage $page, $context_path)
  522. {
  523. // dump($context_path);
  524. $complex_questions = $page->get_questions(true);
  525. while ($complex_question = $complex_questions->next_result())
  526. {
  527. // dump($complex_question->get_id());
  528. if ($complex_question->is_visible())
  529. {
  530. $complex_question_id = $complex_question->get_id();
  531. // dump('visible');
  532. // dump('qcp ' . $context_path . '_' . $complex_question_id);
  533. $answer = $this->parent->get_answer($complex_question_id, $context_path . '_' . $complex_question_id);
  534. // dump($answer);
  535. if ($answer)
  536. {
  537. $this->page_answers[$complex_question_id] = $answer;
  538. }
  539. }
  540. }
  541. }
  542. /**
  543. * Renders the menu as a tree
  544. * @return string The HTML formatted tree
  545. */
  546. function render_as_tree()
  547. {
  548. $renderer = new TreeMenuRenderer($this->get_tree_name());
  549. $this->render($renderer, 'sitemap');
  550. return $renderer->toHTML();
  551. }
  552. function get_survey()
  553. {
  554. return $this->survey;
  555. }
  556. static function get_tree_name()
  557. {
  558. return Utilities :: get_classname_from_namespace(self :: TREE_NAME, true);
  559. }
  560. }