AutoGostController.php 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308
  1. <?php
  2. // Контроллер автогоста
  3. class AutoGostController extends Controller {
  4. // Загрузка изображений
  5. public static function uploadImage() {
  6. if (is_uploaded_file($_FILES['file']['tmp_name'])) {
  7. $mime_type = mime_content_type($_FILES['file']['tmp_name']);
  8. $filepath = tempnam(rootdir."/img/autogost", "rgnupload");
  9. if ($mime_type == "image/png") {
  10. // Конвертирование png в gif
  11. $png_image = imagecreatefrompng($_FILES['file']['tmp_name']);
  12. $gif_image = imagecreatetruecolor(imagesx($png_image), imagesy($png_image));
  13. imagecopy($gif_image, $png_image, 0, 0, 0, 0, imagesx($png_image), imagesy($png_image));
  14. imagegif($gif_image, $filepath);
  15. } else {
  16. // Просто перемещение файла
  17. $filepath = tempnam(rootdir."/img/autogost", "rgnupload");
  18. move_uploaded_file($_FILES['file']['tmp_name'], $filepath);
  19. }
  20. $output = ["ok"=>true, "filename"=>basename($filepath)];
  21. } else {
  22. $output = ["ok"=>false];
  23. }
  24. echo json_encode($output);
  25. }
  26. // Список отчётов по дисциплине
  27. public static function listReports($subject_id) {
  28. $reports = ReportModel::where("subject_id", $subject_id);
  29. $subject = SubjectModel::getById($subject_id);
  30. $view = new AutoGostReportsView([
  31. "page_title" => "Автогост: архив ".$subject['name'],
  32. "crumbs" => ["Главная" => "/", "Автогост: дисциплины" => "/autogost/archive", $subject['name'] => ""],
  33. "reports" => $reports,
  34. "subject" => $subject
  35. ]);
  36. $view->view();
  37. }
  38. // Архив отчётов
  39. public static function archive() {
  40. $subjects = SubjectModel::all();
  41. $view = new AutoGostArchiveView([
  42. "page_title" => "Автогост: архив",
  43. "crumbs" => ["Главная" => "/", "Автогост: дисциплины" => "/"],
  44. "subjects" => $subjects
  45. ]);
  46. $view->view();
  47. }
  48. // Редактирование отчёта
  49. public static function edit($report_id) {
  50. $report = ReportModel::getById($report_id);
  51. $subject = SubjectModel::getById($report['subject_id']);
  52. $filename = "Автогост - ".$subject['name']." #".$report['work_number']." - Королёв";
  53. $view = new AutoGostEditView([
  54. "page_title" => $filename,
  55. "crumbs" => ["Главная"=>"/", "Автогост: дисциплины" => "/autogost/archive/", $subject['name'] => "/autogost/archive/".$subject['id'], "Редактирование"=>"/"],
  56. "markup" => $report['markup'],
  57. "filename" => $filename,
  58. "report_id" => $report_id
  59. ]);
  60. $view->view();
  61. }
  62. // Валидация создания отчёта
  63. private static function validateCreation() {
  64. if (empty($_POST["number"])) {
  65. // Запрос на создание
  66. return 'Не указан номер работы';
  67. }
  68. return true;
  69. }
  70. // Создание отчёта
  71. public static function newReport() {
  72. $subjects = SubjectModel::all();
  73. $worktypes = WorkTypeModel::all();
  74. if (!empty($_POST)) {
  75. $response = self::validateCreation();
  76. if ($response === true) {
  77. // Валидация успешна
  78. // Создаём запись
  79. $work_type = WorkTypeModel::getById($_POST['work_type']);
  80. $report_id = ReportModel::create(
  81. $_POST["subject_id"],
  82. $_POST['work_type'],
  83. $_POST['number'],
  84. $_POST['notice'],
  85. "!-\n!\n#{$work_type['name_nom']} №{$_POST['number']}\n"
  86. );
  87. // Перенаправляем на предпросмотр этого отчёта
  88. header("Location: /autogost/edit/".$report_id);
  89. return;
  90. } else {
  91. // Валидация провалена
  92. $error_text = $response;
  93. }
  94. } else {
  95. $error_text = null;
  96. }
  97. $view = new AutoGostNewReportView([
  98. "page_title" => "Автогост: создание отчёта",
  99. 'subjects' => $subjects,
  100. 'worktypes' => $worktypes,
  101. 'error_text' => $error_text,
  102. "crumbs" => ["Главная"=>"/", "Автогост: создание отчёта" => "/"]
  103. ]);
  104. $view->view();
  105. }
  106. // Получение HTML
  107. public static function getHtml() {
  108. $report = ReportModel::getById($_POST['report_id']);
  109. $subject = SubjectModel::getById($report["subject_id"]);
  110. $work_type = WorkTypeModel::getById($report["work_type"]);
  111. $teacher = TeacherModel::getById($subject["teacher_id"]);
  112. $markup = $_POST['markup'];
  113. $lines = explode("\n", $markup);
  114. // Определение количества страниц
  115. $pages_count = 0;
  116. foreach ($lines as $l) {
  117. if (self::isPageMarker($l)) {
  118. $has_pages = true;
  119. if (self::isCountablePage($l)) {
  120. $pages_count++;
  121. }
  122. }
  123. }
  124. // Основные переменные
  125. $current_line_index = -1;
  126. $end_line_index = count($lines);
  127. $output = "";
  128. // Нумераторы
  129. $current_page_number = 1; // Страницы
  130. $current_image_number = 1; // Изображения
  131. $current_table_number = 1; // Таблицы
  132. $current_application_number = 1; // Приложения
  133. $current_table_row = 0; // Строка текущей таблицы
  134. // Флаги
  135. $is_generating_table = false; // Генерируем ли сейчас таблицу
  136. // Генерируем (X)HTML!
  137. while ($current_line_index < $end_line_index - 1) {
  138. // Ищем маркер страницы. Пропускам всё, что не маркер
  139. $current_line_index++;
  140. if (!self::isPageMarker($lines[$current_line_index])) {
  141. continue;
  142. }
  143. $current_page_marker = $lines[$current_line_index];
  144. $current_line_index++;
  145. // Генерация контента страницы
  146. $page_content = "";
  147. if ($is_generating_table == true) {
  148. // Если мы генерируем таблицу, а сейчас начинается новая страница, то на предыдущей странице мы уже начинали
  149. // генерировать и произошёл разрыв таблицы.
  150. $page_content .= "<p class='tt'>Продолжение таблицы {$current_table_number}</p>
  151. <table class='t{$current_table_number}'>";
  152. }
  153. while ($current_line_index < $end_line_index) {
  154. if (self::isPageMarker($lines[$current_line_index])) {
  155. // Эта строка - маркер страницы!
  156. // Заканчиваем генерировать эту страницу и переходим к другой
  157. $current_line_index--;
  158. break;
  159. }
  160. $str = $lines[$current_line_index];
  161. // Интерпретация строки
  162. if ($str == "") {
  163. // Пустая строка
  164. $line_content = "";
  165. } else if ($str == "\\") {
  166. // Перенос строки
  167. $line_content = '<br/>';
  168. } else if ($str[0] == "#") {
  169. // Выровененный по центру текст
  170. $line_content = "<p class='title'>".trim(substr($str, 1))."</p>";
  171. } else if ($str[0] == "?") {
  172. // Изображение
  173. list($image_path, $image_title) = explode(":", substr($str, 1));
  174. $picture_title = "Рисунок {$current_image_number} - {$image_title}";
  175. $line_content = "<br/><img src='/img/autogost/$image_path' title='$picture_title'><p class='title'>$picture_title</p><br/>";
  176. $current_image_number++;
  177. } else if (substr($str, 0, 6) === "@table") {
  178. // Начало таблицы
  179. $table_class = "t" . strval($current_table_number);
  180. $parts = explode(":", substr($str, 1));
  181. $style = "<style>";
  182. for ($i = 1; $i < count($parts); $i++) {
  183. list($width, $align) = explode("_", $parts[$i]);
  184. $style .= ".{$table_class} td:nth-child({$i}),.{$table_class} th:nth-child({$i}){width:{$width}px;text-align:{$align}}";
  185. }
  186. $line_content .= "</style><p class='tt'>Таблица $current_table_number - {$parts[0]}</p><table class='$table_class'>";
  187. $is_generating_table = true;
  188. } else if ($str[0] === "|") {
  189. // Продолжение таблицы
  190. // Если это начало таблицы, то используем тэг th, иначе td
  191. if ($current_table_row == 0) {
  192. $tag_name = "th";
  193. } else {
  194. $tag_name = "td";
  195. }
  196. $line_content = "<tr>";
  197. $parts = explode("|", $str);
  198. for ($i = 1; $i < count($parts) - 1; $i++) {
  199. $part = trim($parts[$i]);
  200. $line_content .= "<{$tag_name}>$part</{$tag_name}>";
  201. }
  202. $line_content .= "</tr>";
  203. $current_table_row += 1;
  204. // Смотрим в будущее и ищем разрыв таблицы или конец всего отчёта
  205. if ($current_line_index < $end_line_index - 1) {
  206. if (self::isPageMarker($lines[$current_line_index + 1])) {
  207. // Таблица разделена на 2 страницы
  208. $line_content .= "</table>";
  209. }
  210. } else {
  211. // Это конец отчёта! Нарушение разметки, но так уж и быть, поправим по-тихому
  212. $line_content .= "</table>";
  213. }
  214. } else if ($str === "@endtable") {
  215. // Конец таблицы
  216. $line_content = "</table><br/>";
  217. $is_generating_table = false;
  218. $current_table_number++;
  219. $current_table_row = 0;
  220. } else {
  221. // Обычный текст
  222. $line_content = "<p>".$str."</p>";
  223. }
  224. $page_content .= $line_content;
  225. $current_line_index++;
  226. }
  227. // Всё то, что нагенерировали засовываем в страницу
  228. $page_wrapped = new AutoGostPageView([
  229. 'work_code' => $subject['code'].$_ENV['autogost_code'],
  230. 'teacher_full' => $teacher["surname"]." ".mb_substr($teacher['name'],0,1).'. '.mb_substr($teacher['patronymic'],0,1).'.',
  231. 'author_surname' => $_ENV['autogost_surname'],
  232. 'author_full' => $_ENV['autogost_full'],
  233. 'subject' => $subject,
  234. 'work_type' => $work_type,
  235. 'pages_count' => $pages_count,
  236. 'author_group' => $_ENV['autogost_group'],
  237. 'work_number' => $report['work_number'],
  238. 'teacher_surname' => $teacher['surname'],
  239. 'current_page_number' => $current_page_number,
  240. 'current_page_marker' => $current_page_marker,
  241. 'page_content' => $page_content
  242. ]);
  243. $output .= $page_wrapped->render();
  244. if (self::isCountablePage($current_page_marker) != "!-") {
  245. $current_page_number++;
  246. }
  247. }
  248. // $output возвращаем
  249. echo $output;
  250. }
  251. // Возвращает true если строка - это маркер страниц
  252. private static function isPageMarker($line) {
  253. return preg_match("/^(?:!|!!|!0|!-|!--)$/", $line);
  254. }
  255. // Возвращает true если строка - маркер страницы, которую можно включать в объём всех страниц
  256. private static function isCountablePage($line) {
  257. return preg_match("/^(?:!|!!|!0|!-)$/", $line);
  258. }
  259. }