Version20151214170800.php 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128
  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. continue;
  41. }
  42. $imageSize = getimagesize($imagePath);
  43. $widthRatio = $imageSize[0] / 360;
  44. $heightRatio = $imageSize[1] / 360;
  45. $oldCoords = $answer['hotspot_coordinates'];
  46. $oldPairedString = explode('|', $oldCoords);
  47. $newPairedString = [];
  48. switch ($answer['hotspot_type']) {
  49. case 'square':
  50. $oldCenter = explode(';', $oldPairedString[0]);
  51. $oldCenterX = intval($oldCenter[0]);
  52. $oldCenterY = intval($oldCenter[1]);
  53. $oldWidth = intval($oldPairedString[1]);
  54. $oldHeight = intval($oldPairedString[2]);
  55. $newX = floor(($oldCenterX - $oldWidth / 2) * $widthRatio) + ceil($widthRatio);
  56. $newY = floor(($oldCenterY - $oldHeight / 2) * $heightRatio) + ceil($heightRatio);
  57. $newWidth = ceil($oldWidth * $widthRatio) + ceil(1 * $heightRatio);
  58. $newHeight = ceil($oldHeight * $heightRatio) + floor(1 * $heightRatio);
  59. $newPairedString[] = implode(';', [$newX, $newY]);
  60. $newPairedString[] = $newWidth;
  61. $newPairedString[] = $newHeight;
  62. break;
  63. case 'circle':
  64. $oldCenter = explode(';', $oldPairedString[0]);
  65. $oldCenterX = intval($oldCenter[0]);
  66. $oldCenterY = intval($oldCenter[1]);
  67. $oldRadiusX = intval($oldPairedString[1]) / 2;
  68. $oldRadiusY = intval($oldPairedString[2]) / 2;
  69. $newCenterX = floor($oldCenterX * $widthRatio) + ceil($widthRatio);
  70. $newCenterY = floor($oldCenterY * $heightRatio) + ceil($heightRatio);
  71. $newRadiusX = floor($oldRadiusX * $widthRatio);
  72. $newRadiusY = floor($oldRadiusY * $heightRatio);
  73. $newPairedString[] = implode(';', [$newCenterX, $newCenterY]);
  74. $newPairedString[] = $newRadiusX;
  75. $newPairedString[] = $newRadiusY;
  76. break;
  77. case 'poly':
  78. //no break;
  79. case 'delineation':
  80. //no break
  81. case 'oar':
  82. $paired = [];
  83. foreach ($oldPairedString as $pairString) {
  84. $pair = explode(';', $pairString);
  85. $x = isset($pair[0]) ? intval($pair[0]) : 0;
  86. $y = isset($pair[1]) ? intval($pair[1]) : 0;
  87. $paired[] = [$x, $y];
  88. }
  89. foreach ($paired as $pair) {
  90. $x = floor($pair[0] * $widthRatio) + ceil($widthRatio);
  91. $y = ceil($pair[1] * $heightRatio);
  92. $newPairedString[] = implode(';', [$x, $y]);
  93. }
  94. break;
  95. }
  96. $stmt = $this->connection->prepare("
  97. UPDATE c_quiz_answer
  98. SET hotspot_coordinates = :coordinates
  99. WHERE iid = :iid AND c_id = :cid
  100. ");
  101. $stmt->bindValue('coordinates', implode('|', $newPairedString), Type::TEXT);
  102. $stmt->bindValue('iid', $answer['iid'], Type::INTEGER);
  103. $stmt->bindValue('cid', $answer['c_id'], Type::INTEGER);
  104. $stmt->execute();
  105. }
  106. }
  107. /**
  108. * @param Schema $schema
  109. */
  110. public function down(Schema $schema)
  111. {
  112. }
  113. }