sequence.ajax.php 16 KB

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