sequence.ajax.php 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414
  1. <?php
  2. /* For licensing terms, see /license.txt */
  3. use ChamiloSession as Session;
  4. use Chamilo\CoreBundle\Entity\Sequence;
  5. use Chamilo\CoreBundle\Entity\SequenceResource;
  6. use Fhaculty\Graph\Graph;
  7. use Fhaculty\Graph\Vertex;
  8. use Graphp\GraphViz\GraphViz;
  9. /**
  10. * Responses to AJAX calls
  11. */
  12. require_once __DIR__.'/../global.inc.php';
  13. $action = isset($_REQUEST['a']) ? $_REQUEST['a'] : null;
  14. $id = isset($_REQUEST['id']) ? $_REQUEST['id'] : null;
  15. $type = isset($_REQUEST['type']) ? $_REQUEST['type'] : null;
  16. $sequenceId = isset($_REQUEST['sequence_id']) ? $_REQUEST['sequence_id'] : 0;
  17. $em = Database::getManager();
  18. $repository = $em->getRepository('ChamiloCoreBundle:SequenceResource');
  19. switch ($action) {
  20. case 'graph':
  21. api_block_anonymous_users();
  22. api_protect_admin_script();
  23. switch ($type) {
  24. case 'session':
  25. $type = SequenceResource::SESSION_TYPE;
  26. /** @var Sequence $sequence */
  27. $sequence = $em->getRepository('ChamiloCoreBundle:Sequence')->find($sequenceId);
  28. if (empty($sequence)) {
  29. exit;
  30. }
  31. if ($sequence->hasGraph()) {
  32. $graph = $sequence->getUnSerializeGraph();
  33. $graph->setAttribute('graphviz.node.fontname', 'arial');
  34. $graphviz = new GraphViz();
  35. $graphImage = '';
  36. try {
  37. $graphImage = $graphviz->createImageHtml($graph);
  38. } catch (UnexpectedValueException $e) {
  39. error_log($e->getMessage().' - Graph could not be rendered in resources sequence because GraphViz command "dot" could not be executed - Make sure graphviz is installed.');
  40. $graphImage = '<p class="text-center"><small>'.get_lang('MissingChartLibraryPleaseCheckLog').'</small></p>';
  41. }
  42. echo $graphImage;
  43. }
  44. break;
  45. }
  46. break;
  47. case 'get_icon':
  48. api_block_anonymous_users();
  49. api_protect_admin_script();
  50. $link = '';
  51. switch ($type) {
  52. case 'session':
  53. $type = SequenceResource::SESSION_TYPE;
  54. $showDelete = isset($_REQUEST['show_delete']) ? $_REQUEST['show_delete'] : false;
  55. $image = Display::return_icon('item-sequence.png', null, null, ICON_SIZE_LARGE);
  56. $sessionInfo = api_get_session_info($id);
  57. if (!empty($sessionInfo)) {
  58. $linkDelete = $linkUndo = '';
  59. if ($showDelete) {
  60. $linkDelete = Display::toolbarButton(
  61. get_lang('Delete'),
  62. '#',
  63. 'trash',
  64. 'default',
  65. [
  66. 'class' => 'delete_vertex btn btn-block btn-xs',
  67. 'data-id' => $id
  68. ]
  69. );
  70. $linkUndo = Display::toolbarButton(
  71. get_lang('Undo'),
  72. '#',
  73. 'undo',
  74. 'default',
  75. [
  76. 'class' => 'undo_delete btn btn-block btn-xs',
  77. 'style' => 'display: none;',
  78. 'data-id' => $id
  79. ]
  80. );
  81. }
  82. $link = '<div class="parent" data-id="'.$id.'">';
  83. $link .= '<div class="big-icon">';
  84. $link .= $image;
  85. $link .= '<div class="sequence-course">'.$sessionInfo['name'].'</div>';
  86. $link .= '<a href="#" class="sequence-id">'.$id.'</a>';
  87. $link .= $linkDelete;
  88. $link .= $linkUndo;
  89. $link .= '</div></div>';
  90. }
  91. break;
  92. }
  93. echo $link;
  94. break;
  95. case 'delete_vertex':
  96. api_block_anonymous_users();
  97. api_protect_admin_script();
  98. $vertexId = isset($_REQUEST['vertex_id']) ? $_REQUEST['vertex_id'] : null;
  99. $type = SequenceResource::SESSION_TYPE;
  100. /** @var Sequence $sequence */
  101. $sequence = $em->getRepository('ChamiloCoreBundle:Sequence')->find($sequenceId);
  102. if (empty($sequence)) {
  103. exit;
  104. }
  105. /** @var SequenceResource $sequenceResource */
  106. $sequenceResource = $repository->findOneBy(
  107. ['resourceId' => $id, 'type' => $type, 'sequence' => $sequence]
  108. );
  109. if (empty($sequenceResource)) {
  110. exit;
  111. }
  112. if ($sequenceResource->getSequence()->hasGraph()) {
  113. $graph = $sequenceResource->getSequence()->getUnSerializeGraph();
  114. if ($graph->hasVertex($vertexId)) {
  115. $edgeIterator = $graph->getEdges()->getIterator();
  116. $edgeToDelete = null;
  117. foreach ($edgeIterator as $edge) {
  118. if ($edge->getVertexStart()->getId() == $vertexId && $edge->getVertexEnd()->getId() == $id) {
  119. $edgeToDelete = $edge;
  120. $vertexFromTo = null;
  121. $vertexToFrom = null;
  122. foreach ($edgeIterator as $edges) {
  123. if (intval($edges->getVertexEnd()->getId()) === intval($id)) {
  124. $vertexFromTo = $edges;
  125. }
  126. if (intval($edges->getVertexStart()->getId()) === intval($vertexId)) {
  127. $vertexToFrom = $edges;
  128. }
  129. }
  130. if ($vertexFromTo && !$vertexToFrom) {
  131. Session::write('sr_vertex', true);
  132. $vertex = $graph->getVertex($id);
  133. $vertex->destroy();
  134. $em->remove($sequenceResource);
  135. }
  136. if ($vertexToFrom && $vertexFromTo) {
  137. $vertex = $graph->getVertex($vertexId);
  138. $edgeToDelete->destroy();
  139. }
  140. if ($vertexToFrom && !$vertexFromTo) {
  141. $vertex = $graph->getVertex($vertexId);
  142. $vertex->destroy();
  143. $sequenceResourceToDelete = $repository->findOneBy(
  144. [
  145. 'resourceId' => $vertexId,
  146. 'type' => $type,
  147. 'sequence' => $sequence
  148. ]
  149. );
  150. $em->remove($sequenceResourceToDelete);
  151. }
  152. if (!$vertexToFrom && !$vertexFromTo) {
  153. Session::write('sr_vertex', true);
  154. $vertexTo = $graph->getVertex($id);
  155. $vertexFrom = $graph->getVertex($vertexId);
  156. if ($vertexTo->getVerticesEdgeFrom()->count() > 1) {
  157. $vertexFrom->destroy();
  158. $sequenceResourceToDelete = $repository->findOneBy(
  159. [
  160. 'resourceId' => $vertexId,
  161. 'type' => $type,
  162. 'sequence' => $sequence
  163. ]
  164. );
  165. $em->remove($sequenceResourceToDelete);
  166. } else {
  167. $vertexTo->destroy();
  168. $vertexFrom->destroy();
  169. $sequenceResourceToDelete = $repository->findOneBy(
  170. [
  171. 'resourceId' => $vertexId,
  172. 'type' => $type,
  173. 'sequence' => $sequence
  174. ]
  175. );
  176. $em->remove($sequenceResource);
  177. $em->remove($sequenceResourceToDelete);
  178. }
  179. }
  180. }
  181. }
  182. $sequence->setGraphAndSerialize($graph);
  183. $em->merge($sequence);
  184. $em->flush();
  185. }
  186. }
  187. break;
  188. case 'load_resource':
  189. api_block_anonymous_users();
  190. api_protect_admin_script();
  191. // children or parent
  192. $loadResourceType = isset($_REQUEST['load_resource_type']) ? $_REQUEST['load_resource_type'] : null;
  193. $sequenceId = isset($_REQUEST['sequence_id']) ? $_REQUEST['sequence_id'] : 0;
  194. $type = SequenceResource::SESSION_TYPE;
  195. /** @var Sequence $sequence */
  196. $sequence = $em->getRepository('ChamiloCoreBundle:Sequence')->find($sequenceId);
  197. if (empty($sequence)) {
  198. exit;
  199. }
  200. /** @var SequenceResource $sequenceResource */
  201. $sequenceResource = $repository->findOneBy(
  202. ['resourceId' => $id, 'type' => $type, 'sequence' => $sequence]
  203. );
  204. if (empty($sequenceResource)) {
  205. exit;
  206. }
  207. if ($sequenceResource->hasGraph()) {
  208. $graph = $sequenceResource->getSequence()->getUnSerializeGraph();
  209. /** @var Vertex $mainVertice */
  210. if ($graph->hasVertex($id)) {
  211. $mainVertex = $graph->getVertex($id);
  212. if (!empty($mainVertex)) {
  213. $vertexList = null;
  214. switch ($loadResourceType) {
  215. case 'parent':
  216. $vertexList = $mainVertex->getVerticesEdgeFrom();
  217. break;
  218. case 'children':
  219. $vertexList = $mainVertex->getVerticesEdgeTo();
  220. break;
  221. }
  222. $list = [];
  223. if (!empty($vertexList)) {
  224. foreach ($vertexList as $vertex) {
  225. $list[] = $vertex->getId();
  226. }
  227. }
  228. if (!empty($list)) {
  229. echo implode(',', $list);
  230. }
  231. }
  232. }
  233. }
  234. break;
  235. case 'save_resource':
  236. api_block_anonymous_users();
  237. api_protect_admin_script();
  238. $parents = isset($_REQUEST['parents']) ? $_REQUEST['parents'] : '';
  239. $sequenceId = isset($_REQUEST['sequence_id']) ? $_REQUEST['sequence_id'] : 0;
  240. $type = isset($_REQUEST['type']) ? $_REQUEST['type'] : '';
  241. if (empty($parents) || empty($sequenceId) || empty($type)) {
  242. exit;
  243. }
  244. /** @var Sequence $sequence */
  245. $sequence = $em->getRepository('ChamiloCoreBundle:Sequence')->find($sequenceId);
  246. if (empty($sequence)) {
  247. exit;
  248. }
  249. $vertexFromSession = Session::read('sr_vertex');
  250. if ($vertexFromSession) {
  251. Session::erase('sr_vertex');
  252. echo Display::return_message(get_lang('Saved'), 'success');
  253. break;
  254. }
  255. $parents = str_replace($id, '', $parents);
  256. $parents = explode(',', $parents);
  257. $parents = array_filter($parents);
  258. if ($sequence->hasGraph()) {
  259. $graph = $sequence->getUnSerializeGraph();
  260. } else {
  261. $graph = new Graph();
  262. }
  263. switch ($type) {
  264. case 'session':
  265. $type = SequenceResource::SESSION_TYPE;
  266. $sessionInfo = api_get_session_info($id);
  267. $name = $sessionInfo['name'];
  268. if ($graph->hasVertex($id)) {
  269. $main = $graph->getVertex($id);
  270. } else {
  271. $main = $graph->createVertex($id);
  272. }
  273. foreach ($parents as $parentId) {
  274. if ($graph->hasVertex($parentId)) {
  275. $parent = $graph->getVertex($parentId);
  276. if (!$parent->hasEdgeTo($main)) {
  277. $parent->createEdgeTo($main);
  278. }
  279. } else {
  280. $parent = $graph->createVertex($parentId);
  281. $parent->createEdgeTo($main);
  282. }
  283. }
  284. foreach ($parents as $parentId) {
  285. $sequenceResourceParent = $repository->findOneBy(
  286. ['resourceId' => $parentId, 'type' => $type, 'sequence' => $sequence]
  287. );
  288. if (empty($sequenceResourceParent)) {
  289. $sequenceResourceParent = new SequenceResource();
  290. $sequenceResourceParent
  291. ->setSequence($sequence)
  292. ->setType(SequenceResource::SESSION_TYPE)
  293. ->setResourceId($parentId);
  294. $em->persist($sequenceResourceParent);
  295. }
  296. }
  297. //$graphviz = new GraphViz();
  298. //echo $graphviz->createImageHtml($graph);
  299. /** @var SequenceResource $sequenceResource */
  300. $sequenceResource = $repository->findOneBy(
  301. ['resourceId' => $id, 'type' => $type, 'sequence' => $sequence]
  302. );
  303. if (empty($sequenceResource)) {
  304. // Create
  305. $sequence->setGraphAndSerialize($graph);
  306. $sequenceResource = new SequenceResource();
  307. $sequenceResource
  308. ->setSequence($sequence)
  309. ->setType(SequenceResource::SESSION_TYPE)
  310. ->setResourceId($id);
  311. } else {
  312. // Update
  313. $sequenceResource->getSequence()->setGraphAndSerialize($graph);
  314. }
  315. $em->persist($sequenceResource);
  316. $em->flush();
  317. echo Display::return_message(get_lang('Saved'), 'success');
  318. break;
  319. }
  320. break;
  321. case 'get_requirements':
  322. $userId = api_get_user_id();
  323. switch ($type) {
  324. case SequenceResource::SESSION_TYPE:
  325. $session = api_get_session_info($id);
  326. $sequences = $repository->getRequirements(
  327. $session['id'],
  328. $type
  329. );
  330. if (count($sequences) === 0) {
  331. break;
  332. }
  333. $sequenceList = SequenceResourceManager::checkRequirementsForUser($sequences, $type, $userId);
  334. $allowSubscription = SequenceResourceManager::checkSequenceAreCompleted($sequenceList);
  335. $courseController = new CoursesController();
  336. $view = new Template(null, false, false, false, false, false);
  337. $view->assign('sequences', $sequenceList);
  338. $view->assign('allow_subscription', $allowSubscription);
  339. if ($allowSubscription) {
  340. $view->assign(
  341. 'subscribe_button',
  342. $courseController->getRegisteredInSessionButton(
  343. $session['id'],
  344. $session['name'],
  345. false
  346. )
  347. );
  348. }
  349. $template = $view->get_template(
  350. 'sequence_resource/session_requirements.tpl'
  351. );
  352. $view->display($template);
  353. break;
  354. }
  355. break;
  356. }