Version20151214170800.php 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131
  1. <?php
  2. /* For licensing terms, see /license.txt */
  3. namespace Application\Migrations\Schema\V110;
  4. use Application\Migrations\AbstractMigrationChamilo;
  5. use Doctrine\DBAL\Schema\Schema;
  6. use Doctrine\DBAL\Types\Type;
  7. /**
  8. * Fix track_e_hotspot table and migrate hotspot/values
  9. * In the wake of an issue with the hotspot code not being possible to update without moving from AS2 to AS3 (Flash), we
  10. * have decided to rewrite the hotspot tool in JS.
  11. * Little did we know that we would find out that the coordinates system in use by the Flash version of hotspot was in
  12. * fact a projection into a square form of 360x360, not depending on the original size of the image, and that a square
  13. * was defined by its center's coordinates and its width, with an initial not-null margin on the left and top borders.
  14. * The migration below fixes those parallax issues.
  15. */
  16. class Version20151214170800 extends AbstractMigrationChamilo
  17. {
  18. /**
  19. * @param Schema $schema
  20. */
  21. public function up(Schema $schema)
  22. {
  23. $this->addSql("ALTER TABLE track_e_hotspot ADD c_id INT NULL");
  24. $this->addSql("ALTER TABLE track_e_hotspot MODIFY COLUMN hotspot_coordinate LONGTEXT NOT NULL");
  25. $this->addSql("UPDATE track_e_hotspot SET c_id = (SELECT id FROM course WHERE code = hotspot_course_code)");
  26. $answers = $this->connection->fetchAll("
  27. SELECT a.iid, a.c_id, a.question_id, a.hotspot_coordinates, a.hotspot_type, q.picture, c.directory
  28. FROM c_quiz_answer a
  29. INNER JOIN c_quiz_question q
  30. ON (a.question_id = q.id AND a.c_id = q.c_id)
  31. INNER JOIN course c
  32. ON (a.c_id = c.id AND q.c_id = c.id)
  33. WHERE a.hotspot_type IN ('square', 'circle', 'poly', 'delineation', 'oar')
  34. ");
  35. foreach ($answers as $answer) {
  36. // Recover the real image size to recalculate coordinates
  37. $imagePath = __DIR__ . "/../../../../courses/{$answer['directory']}/document/images/{$answer['picture']}";
  38. if (!file_exists($imagePath)) {
  39. error_log("Migration: Image does not exists: $imagePath");
  40. $imagePath = realpath($imagePath);
  41. error_log("Hotspot realpath: $imagePath");
  42. error_log("api_get_path: SYS_PATH: ".api_get_path(SYS_PATH));
  43. continue;
  44. }
  45. $imageSize = getimagesize($imagePath);
  46. $widthRatio = $imageSize[0] / 360;
  47. $heightRatio = $imageSize[1] / 360;
  48. $oldCoords = $answer['hotspot_coordinates'];
  49. $oldPairedString = explode('|', $oldCoords);
  50. $newPairedString = [];
  51. switch ($answer['hotspot_type']) {
  52. case 'square':
  53. $oldCenter = explode(';', $oldPairedString[0]);
  54. $oldCenterX = intval($oldCenter[0]);
  55. $oldCenterY = intval($oldCenter[1]);
  56. $oldWidth = intval($oldPairedString[1]);
  57. $oldHeight = intval($oldPairedString[2]);
  58. $newX = floor(($oldCenterX - $oldWidth / 2) * $widthRatio) + ceil($widthRatio);
  59. $newY = floor(($oldCenterY - $oldHeight / 2) * $heightRatio) + ceil($heightRatio);
  60. $newWidth = ceil($oldWidth * $widthRatio) + ceil(1 * $heightRatio);
  61. $newHeight = ceil($oldHeight * $heightRatio) + floor(1 * $heightRatio);
  62. $newPairedString[] = implode(';', [$newX, $newY]);
  63. $newPairedString[] = $newWidth;
  64. $newPairedString[] = $newHeight;
  65. break;
  66. case 'circle':
  67. $oldCenter = explode(';', $oldPairedString[0]);
  68. $oldCenterX = intval($oldCenter[0]);
  69. $oldCenterY = intval($oldCenter[1]);
  70. $oldRadiusX = intval($oldPairedString[1]) / 2;
  71. $oldRadiusY = intval($oldPairedString[2]) / 2;
  72. $newCenterX = floor($oldCenterX * $widthRatio) + ceil($widthRatio);
  73. $newCenterY = floor($oldCenterY * $heightRatio) + ceil($heightRatio);
  74. $newRadiusX = floor($oldRadiusX * $widthRatio);
  75. $newRadiusY = floor($oldRadiusY * $heightRatio);
  76. $newPairedString[] = implode(';', [$newCenterX, $newCenterY]);
  77. $newPairedString[] = $newRadiusX;
  78. $newPairedString[] = $newRadiusY;
  79. break;
  80. case 'poly':
  81. //no break;
  82. case 'delineation':
  83. //no break
  84. case 'oar':
  85. $paired = [];
  86. foreach ($oldPairedString as $pairString) {
  87. $pair = explode(';', $pairString);
  88. $x = isset($pair[0]) ? intval($pair[0]) : 0;
  89. $y = isset($pair[1]) ? intval($pair[1]) : 0;
  90. $paired[] = [$x, $y];
  91. }
  92. foreach ($paired as $pair) {
  93. $x = floor($pair[0] * $widthRatio) + ceil($widthRatio);
  94. $y = ceil($pair[1] * $heightRatio);
  95. $newPairedString[] = implode(';', [$x, $y]);
  96. }
  97. break;
  98. }
  99. $stmt = $this->connection->prepare("
  100. UPDATE c_quiz_answer
  101. SET hotspot_coordinates = :coordinates
  102. WHERE iid = :iid AND c_id = :cid
  103. ");
  104. $stmt->bindValue('coordinates', implode('|', $newPairedString), Type::TEXT);
  105. $stmt->bindValue('iid', $answer['iid'], Type::INTEGER);
  106. $stmt->bindValue('cid', $answer['c_id'], Type::INTEGER);
  107. $stmt->execute();
  108. }
  109. }
  110. /**
  111. * @param Schema $schema
  112. */
  113. public function down(Schema $schema)
  114. {
  115. }
  116. }