16b7e227cSYamadaMiz<?php 247595f9cSYamadaMiz 347595f9cSYamadaMizuse dokuwiki\Extension\ActionPlugin; 447595f9cSYamadaMizuse dokuwiki\Extension\EventHandler; 547595f9cSYamadaMizuse dokuwiki\Extension\Event; 647595f9cSYamadaMiz 747595f9cSYamadaMizclass action_plugin_mizarproofchecker extends ActionPlugin 847595f9cSYamadaMiz{ 947595f9cSYamadaMiz /** 1047595f9cSYamadaMiz * Registers a callback function for a given event 1147595f9cSYamadaMiz * 1247595f9cSYamadaMiz * @param EventHandler $controller DokuWiki's event controller object 1347595f9cSYamadaMiz * @return void 1447595f9cSYamadaMiz */ 1547595f9cSYamadaMiz public function register(EventHandler $controller) 1647595f9cSYamadaMiz { 176b7e227cSYamadaMiz $controller->register_hook('AJAX_CALL_UNKNOWN', 'BEFORE', $this, 'handle_ajax_call'); 186b7e227cSYamadaMiz } 196b7e227cSYamadaMiz 2047595f9cSYamadaMiz /** 2147595f9cSYamadaMiz * Handles AJAX requests 2247595f9cSYamadaMiz * 2347595f9cSYamadaMiz * @param Event $event 2447595f9cSYamadaMiz * @param $param 2547595f9cSYamadaMiz */ 2647595f9cSYamadaMiz public function handle_ajax_call(Event $event, $param) 2747595f9cSYamadaMiz { 286b7e227cSYamadaMiz unset($param); // 未使用のパラメータを無効化 2947595f9cSYamadaMiz 3047595f9cSYamadaMiz switch ($event->data) { 3147595f9cSYamadaMiz case 'clear_temp_files': 3247595f9cSYamadaMiz $event->preventDefault(); 3347595f9cSYamadaMiz $event->stopPropagation(); 3447595f9cSYamadaMiz $this->clearTempFiles(); // 追加: 一時ファイル削除の呼び出し 3547595f9cSYamadaMiz break; 3647595f9cSYamadaMiz case 'source_sse': 376b7e227cSYamadaMiz $event->preventDefault(); 386b7e227cSYamadaMiz $event->stopPropagation(); 396b7e227cSYamadaMiz $this->handleSourceSSERequest(); 4047595f9cSYamadaMiz break; 4147595f9cSYamadaMiz case 'source_compile': 426b7e227cSYamadaMiz $event->preventDefault(); 436b7e227cSYamadaMiz $event->stopPropagation(); 446b7e227cSYamadaMiz $this->handleSourceCompileRequest(); 4547595f9cSYamadaMiz break; 4647595f9cSYamadaMiz case 'view_compile': 476b7e227cSYamadaMiz $event->preventDefault(); 486b7e227cSYamadaMiz $event->stopPropagation(); 496b7e227cSYamadaMiz $this->handleViewCompileRequest(); 5047595f9cSYamadaMiz break; 5147595f9cSYamadaMiz case 'view_sse': 526b7e227cSYamadaMiz $event->preventDefault(); 536b7e227cSYamadaMiz $event->stopPropagation(); 546b7e227cSYamadaMiz $this->handleViewSSERequest(); 5547595f9cSYamadaMiz break; 56*9fc5dc4bSYamadaMiz case 'create_combined_file': 57*9fc5dc4bSYamadaMiz $event->preventDefault(); 58*9fc5dc4bSYamadaMiz $event->stopPropagation(); 59*9fc5dc4bSYamadaMiz $this->handle_create_combined_file(); 60*9fc5dc4bSYamadaMiz break; 616b7e227cSYamadaMiz } 626b7e227cSYamadaMiz } 636b7e227cSYamadaMiz 646b7e227cSYamadaMiz // source用のコンパイルリクエスト処理 6547595f9cSYamadaMiz private function handleSourceCompileRequest() 6647595f9cSYamadaMiz { 676b7e227cSYamadaMiz global $INPUT; 686b7e227cSYamadaMiz $pageContent = $INPUT->post->str('content'); 696b7e227cSYamadaMiz $mizarData = $this->extractMizarContent($pageContent); 706b7e227cSYamadaMiz 716b7e227cSYamadaMiz if ($mizarData === null) { 726b7e227cSYamadaMiz $this->sendAjaxResponse(false, 'Mizar content not found'); 736b7e227cSYamadaMiz return; 746b7e227cSYamadaMiz } 756b7e227cSYamadaMiz 766b7e227cSYamadaMiz $filePath = $this->saveMizarContent($mizarData); 776b7e227cSYamadaMiz 786b7e227cSYamadaMiz session_start(); 796b7e227cSYamadaMiz $_SESSION['source_filepath'] = $filePath; 806b7e227cSYamadaMiz 816b7e227cSYamadaMiz $this->sendAjaxResponse(true, 'Mizar content processed successfully'); 826b7e227cSYamadaMiz } 836b7e227cSYamadaMiz 846b7e227cSYamadaMiz // source用のSSEリクエスト処理 8547595f9cSYamadaMiz private function handleSourceSSERequest() 8647595f9cSYamadaMiz { 876b7e227cSYamadaMiz header('Content-Type: text/event-stream'); 886b7e227cSYamadaMiz header('Cache-Control: no-cache'); 896b7e227cSYamadaMiz 906b7e227cSYamadaMiz session_start(); 916b7e227cSYamadaMiz if (!isset($_SESSION['source_filepath'])) { 926b7e227cSYamadaMiz echo "data: Mizar file path not found in session\n\n"; 936b7e227cSYamadaMiz ob_flush(); 946b7e227cSYamadaMiz flush(); 956b7e227cSYamadaMiz return; 966b7e227cSYamadaMiz } 976b7e227cSYamadaMiz 986b7e227cSYamadaMiz $filePath = $_SESSION['source_filepath']; 996b7e227cSYamadaMiz $this->streamSourceOutput($filePath); 1006b7e227cSYamadaMiz 1016b7e227cSYamadaMiz echo "event: end\n"; 1026b7e227cSYamadaMiz echo "data: Compilation complete\n\n"; 1036b7e227cSYamadaMiz ob_flush(); 1046b7e227cSYamadaMiz flush(); 1056b7e227cSYamadaMiz } 1066b7e227cSYamadaMiz 10747595f9cSYamadaMiz // view用のコンパイルリクエスト処理 10847595f9cSYamadaMiz private function handleViewCompileRequest() 10947595f9cSYamadaMiz { 11047595f9cSYamadaMiz global $INPUT; 11147595f9cSYamadaMiz $content = $INPUT->post->str('content'); 11247595f9cSYamadaMiz 11347595f9cSYamadaMiz $filePath = $this->createTempFile($content); 11447595f9cSYamadaMiz 11547595f9cSYamadaMiz session_start(); 11647595f9cSYamadaMiz $_SESSION['view_filepath'] = $filePath; 11747595f9cSYamadaMiz 11847595f9cSYamadaMiz $this->sendAjaxResponse(true, 'Mizar content processed successfully'); 11947595f9cSYamadaMiz } 12047595f9cSYamadaMiz 12147595f9cSYamadaMiz // view用のSSEリクエスト処理 12247595f9cSYamadaMiz private function handleViewSSERequest() 12347595f9cSYamadaMiz { 12447595f9cSYamadaMiz header('Content-Type: text/event-stream'); 12547595f9cSYamadaMiz header('Cache-Control: no-cache'); 12647595f9cSYamadaMiz 12747595f9cSYamadaMiz session_start(); 12847595f9cSYamadaMiz if (!isset($_SESSION['view_filepath'])) { 12947595f9cSYamadaMiz echo "data: Mizar file path not found in session\n\n"; 13047595f9cSYamadaMiz ob_flush(); 13147595f9cSYamadaMiz flush(); 13247595f9cSYamadaMiz return; 13347595f9cSYamadaMiz } 13447595f9cSYamadaMiz 13547595f9cSYamadaMiz $filePath = $_SESSION['view_filepath']; 136*9fc5dc4bSYamadaMiz $this->streamViewCompileOutput($filePath); 13747595f9cSYamadaMiz 13847595f9cSYamadaMiz echo "event: end\n"; 13947595f9cSYamadaMiz echo "data: Compilation complete\n\n"; 14047595f9cSYamadaMiz ob_flush(); 14147595f9cSYamadaMiz flush(); 14247595f9cSYamadaMiz } 14347595f9cSYamadaMiz 14447595f9cSYamadaMiz // Mizarコンテンツの抽出 14547595f9cSYamadaMiz private function extractMizarContent($pageContent) 14647595f9cSYamadaMiz { 1476b7e227cSYamadaMiz $pattern = '/<mizar\s+([^>]+)>(.*?)<\/mizar>/s'; 1486b7e227cSYamadaMiz preg_match_all($pattern, $pageContent, $matches, PREG_SET_ORDER); 1496b7e227cSYamadaMiz 1506b7e227cSYamadaMiz if (empty($matches)) { 15147595f9cSYamadaMiz return null; 1526b7e227cSYamadaMiz } 1536b7e227cSYamadaMiz 15447595f9cSYamadaMiz $fileName = trim($matches[0][1]); 1556b7e227cSYamadaMiz $combinedContent = ''; 1566b7e227cSYamadaMiz 1576b7e227cSYamadaMiz foreach ($matches as $match) { 1586b7e227cSYamadaMiz if (trim($match[1]) !== $fileName) { 1596b7e227cSYamadaMiz return ['error' => 'File name mismatch in <mizar> tags']; 1606b7e227cSYamadaMiz } 1616b7e227cSYamadaMiz $combinedContent .= trim($match[2]) . "\n"; 1626b7e227cSYamadaMiz } 1636b7e227cSYamadaMiz 1646b7e227cSYamadaMiz return ['fileName' => $fileName, 'content' => $combinedContent]; 1656b7e227cSYamadaMiz } 1666b7e227cSYamadaMiz 16747595f9cSYamadaMiz // Mizarコンテンツの保存 16847595f9cSYamadaMiz private function saveMizarContent($mizarData) 16947595f9cSYamadaMiz { 1706b7e227cSYamadaMiz $workPath = rtrim($this->getConf('mizar_work_dir'), '/\\'); 1716b7e227cSYamadaMiz $filePath = $workPath . "/TEXT/" . $mizarData['fileName']; 1726b7e227cSYamadaMiz file_put_contents($filePath, $mizarData['content']); 1736b7e227cSYamadaMiz return $filePath; 1746b7e227cSYamadaMiz } 1756b7e227cSYamadaMiz 17647595f9cSYamadaMiz // source用の出力をストリーム 17747595f9cSYamadaMiz private function streamSourceOutput($filePath) 17847595f9cSYamadaMiz { 1796b7e227cSYamadaMiz $workPath = rtrim($this->getConf('mizar_work_dir'), '/\\'); 1806b7e227cSYamadaMiz chdir($workPath); 1816b7e227cSYamadaMiz 1826b7e227cSYamadaMiz $command = "miz2prel " . escapeshellarg($filePath); 1836b7e227cSYamadaMiz $process = proc_open($command, array(1 => array("pipe", "w")), $pipes); 1846b7e227cSYamadaMiz 1856b7e227cSYamadaMiz if (is_resource($process)) { 1866b7e227cSYamadaMiz while ($line = fgets($pipes[1])) { 1876b7e227cSYamadaMiz echo "data: " . $line . "\n\n"; 1886b7e227cSYamadaMiz ob_flush(); 1896b7e227cSYamadaMiz flush(); 1906b7e227cSYamadaMiz } 1916b7e227cSYamadaMiz fclose($pipes[1]); 192*9fc5dc4bSYamadaMiz 193*9fc5dc4bSYamadaMiz // エラー処理の追加 194*9fc5dc4bSYamadaMiz $errFilename = str_replace('.miz', '.err', $filePath); 195*9fc5dc4bSYamadaMiz if ($this->handleCompilationErrors($errFilename, rtrim($this->getConf('mizar_share_dir'), '/\\') . '/mizar.msg')) { 196*9fc5dc4bSYamadaMiz // エラーがあった場合は処理を終了 197*9fc5dc4bSYamadaMiz proc_close($process); 198*9fc5dc4bSYamadaMiz return; 199*9fc5dc4bSYamadaMiz } 200*9fc5dc4bSYamadaMiz 2016b7e227cSYamadaMiz proc_close($process); 2026b7e227cSYamadaMiz } 2036b7e227cSYamadaMiz } 2046b7e227cSYamadaMiz 20547595f9cSYamadaMiz // view用の一時ファイル作成 20647595f9cSYamadaMiz private function createTempFile($content) 20747595f9cSYamadaMiz { 2086b7e227cSYamadaMiz $workPath = rtrim($this->getConf('mizar_work_dir'), '/\\') . '/TEXT/'; 20947595f9cSYamadaMiz $uniqueName = str_replace('.', '_', uniqid('tmp', true)); 2106b7e227cSYamadaMiz $tempFilename = $workPath . $uniqueName . ".miz"; 2116b7e227cSYamadaMiz file_put_contents($tempFilename, $content); 2126b7e227cSYamadaMiz return $tempFilename; 2136b7e227cSYamadaMiz } 2146b7e227cSYamadaMiz 21547595f9cSYamadaMiz // Clear all temporary files in the TEXT folder 21647595f9cSYamadaMiz private function clearTempFiles() 21747595f9cSYamadaMiz { 21847595f9cSYamadaMiz $workPath = rtrim($this->getConf('mizar_work_dir'), '/\\') . '/TEXT/'; 21947595f9cSYamadaMiz $files = glob($workPath . '*'); // TEXTフォルダ内のすべてのファイルを取得 22047595f9cSYamadaMiz 22147595f9cSYamadaMiz $errors = []; 22247595f9cSYamadaMiz foreach ($files as $file) { 22347595f9cSYamadaMiz if (is_file($file)) { 22447595f9cSYamadaMiz // ファイルが使用中かどうか確認 22547595f9cSYamadaMiz if (!$this->is_file_locked($file)) { 22647595f9cSYamadaMiz $retries = 3; // 最大3回リトライ 22747595f9cSYamadaMiz while ($retries > 0) { 22847595f9cSYamadaMiz if (unlink($file)) { 22947595f9cSYamadaMiz break; // 削除成功 23047595f9cSYamadaMiz } 2315cbf3a53SYamadaMiz $errors[] = "Error deleting $file: " . error_get_last()['message']; 23247595f9cSYamadaMiz $retries--; 23347595f9cSYamadaMiz sleep(1); // 1秒待ってリトライ 23447595f9cSYamadaMiz } 23547595f9cSYamadaMiz if ($retries === 0) { 23647595f9cSYamadaMiz $errors[] = "Failed to delete: $file"; // 削除失敗 23747595f9cSYamadaMiz } 23847595f9cSYamadaMiz } else { 23947595f9cSYamadaMiz $errors[] = "File is locked: $file"; // ファイルがロックされている 24047595f9cSYamadaMiz } 24147595f9cSYamadaMiz } 24247595f9cSYamadaMiz } 24347595f9cSYamadaMiz 24447595f9cSYamadaMiz if (empty($errors)) { 24547595f9cSYamadaMiz $this->sendAjaxResponse(true, 'Temporary files cleared successfully'); 24647595f9cSYamadaMiz } else { 24747595f9cSYamadaMiz $this->sendAjaxResponse(false, 'Some files could not be deleted', $errors); 24847595f9cSYamadaMiz } 24947595f9cSYamadaMiz } 25047595f9cSYamadaMiz 25147595f9cSYamadaMiz // ファイルがロックされているかをチェックする関数 25247595f9cSYamadaMiz private function is_file_locked($file) 25347595f9cSYamadaMiz { 25447595f9cSYamadaMiz $fileHandle = @fopen($file, "r+"); 25547595f9cSYamadaMiz 25647595f9cSYamadaMiz if ($fileHandle === false) { 25747595f9cSYamadaMiz return true; // ファイルが開けない、つまりロックされているかアクセス権がない 25847595f9cSYamadaMiz } 25947595f9cSYamadaMiz 26047595f9cSYamadaMiz $locked = !flock($fileHandle, LOCK_EX | LOCK_NB); // ロックの取得を試みる(非ブロッキングモード) 26147595f9cSYamadaMiz 26247595f9cSYamadaMiz fclose($fileHandle); 26347595f9cSYamadaMiz return $locked; // ロックが取得できなければファイルはロックされている 26447595f9cSYamadaMiz } 26547595f9cSYamadaMiz 266*9fc5dc4bSYamadaMiz // View用コンパイル出力のストリーム 267*9fc5dc4bSYamadaMiz private function streamViewCompileOutput($filePath) 26847595f9cSYamadaMiz { 2696b7e227cSYamadaMiz $workPath = $this->getConf('mizar_work_dir'); 2706b7e227cSYamadaMiz $sharePath = rtrim($this->getConf('mizar_share_dir'), '/\\') . '/'; 2716b7e227cSYamadaMiz 2726b7e227cSYamadaMiz chdir($workPath); 2736b7e227cSYamadaMiz 274*9fc5dc4bSYamadaMiz $errFilename = str_replace('.miz', '.err', $filePath); 2756b7e227cSYamadaMiz $command = "makeenv " . escapeshellarg($filePath); 2766b7e227cSYamadaMiz $process = proc_open($command, array(1 => array("pipe", "w"), 2 => array("pipe", "w")), $pipes); 2776b7e227cSYamadaMiz 2786b7e227cSYamadaMiz if (is_resource($process)) { 2796b7e227cSYamadaMiz while ($line = fgets($pipes[1])) { 2806b7e227cSYamadaMiz echo "data: " . mb_convert_encoding($line, 'UTF-8', 'SJIS') . "\n\n"; 2816b7e227cSYamadaMiz ob_flush(); 2826b7e227cSYamadaMiz flush(); 2836b7e227cSYamadaMiz } 2846b7e227cSYamadaMiz fclose($pipes[1]); 2856b7e227cSYamadaMiz 2866b7e227cSYamadaMiz while ($line = fgets($pipes[2])) { 2876b7e227cSYamadaMiz echo "data: ERROR: " . mb_convert_encoding($line, 'UTF-8', 'SJIS') . "\n\n"; 2886b7e227cSYamadaMiz ob_flush(); 2896b7e227cSYamadaMiz flush(); 2906b7e227cSYamadaMiz } 2916b7e227cSYamadaMiz fclose($pipes[2]); 2926b7e227cSYamadaMiz proc_close($process); 2936b7e227cSYamadaMiz 294*9fc5dc4bSYamadaMiz // エラー処理を別の関数に移動 295*9fc5dc4bSYamadaMiz if ($this->handleCompilationErrors($errFilename, $sharePath . '/mizar.msg')) { 2966b7e227cSYamadaMiz return; 2976b7e227cSYamadaMiz } 2986b7e227cSYamadaMiz 2996b7e227cSYamadaMiz // verifierの実行 3006b7e227cSYamadaMiz $exePath = rtrim($this->getConf('mizar_exe_dir'), '/\\') . '/'; 3016b7e227cSYamadaMiz $verifierPath = escapeshellarg($exePath . "verifier"); 3026b7e227cSYamadaMiz if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') { 3036b7e227cSYamadaMiz $verifierPath .= ".exe"; 3046b7e227cSYamadaMiz } 3056b7e227cSYamadaMiz $verifierCommand = $verifierPath . " -q -l " . escapeshellarg("TEXT/" . basename($filePath)); 3066b7e227cSYamadaMiz 3076b7e227cSYamadaMiz $verifierProcess = proc_open($verifierCommand, array(1 => array("pipe", "w"), 2 => array("pipe", "w")), $verifierPipes); 3086b7e227cSYamadaMiz 3096b7e227cSYamadaMiz if (is_resource($verifierProcess)) { 3106b7e227cSYamadaMiz while ($line = fgets($verifierPipes[1])) { 3116b7e227cSYamadaMiz echo "data: " . mb_convert_encoding($line, 'UTF-8', 'SJIS') . "\n\n"; 3126b7e227cSYamadaMiz ob_flush(); 3136b7e227cSYamadaMiz flush(); 3146b7e227cSYamadaMiz } 3156b7e227cSYamadaMiz fclose($verifierPipes[1]); 3166b7e227cSYamadaMiz 3176b7e227cSYamadaMiz while ($line = fgets($verifierPipes[2])) { 3186b7e227cSYamadaMiz echo "data: ERROR: " . mb_convert_encoding($line, 'UTF-8', 'SJIS') . "\n\n"; 3196b7e227cSYamadaMiz ob_flush(); 3206b7e227cSYamadaMiz flush(); 3216b7e227cSYamadaMiz } 3226b7e227cSYamadaMiz fclose($verifierPipes[2]); 3236b7e227cSYamadaMiz proc_close($verifierProcess); 3246b7e227cSYamadaMiz } else { 3256b7e227cSYamadaMiz echo "data: ERROR: Failed to execute verifier command.\n\n"; 3266b7e227cSYamadaMiz ob_flush(); 3276b7e227cSYamadaMiz flush(); 3286b7e227cSYamadaMiz } 3296b7e227cSYamadaMiz } else { 3306b7e227cSYamadaMiz echo "data: ERROR: Failed to execute makeenv command.\n\n"; 3316b7e227cSYamadaMiz ob_flush(); 3326b7e227cSYamadaMiz flush(); 3336b7e227cSYamadaMiz } 3346b7e227cSYamadaMiz } 3356b7e227cSYamadaMiz 33647595f9cSYamadaMiz private function getMizarErrorMessages($mizarMsgFile) 33747595f9cSYamadaMiz { 3386b7e227cSYamadaMiz $errorMessages = []; 3396b7e227cSYamadaMiz $lines = file($mizarMsgFile, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES); 3406b7e227cSYamadaMiz 3416b7e227cSYamadaMiz $isReadingErrorMsg = false; 3426b7e227cSYamadaMiz $key = 0; 3436b7e227cSYamadaMiz 3446b7e227cSYamadaMiz foreach ($lines as $line) { 3456b7e227cSYamadaMiz if (preg_match('/# (\d+)/', $line, $matches)) { 3466b7e227cSYamadaMiz $isReadingErrorMsg = true; 3476b7e227cSYamadaMiz $key = intval($matches[1]); 3486b7e227cSYamadaMiz } elseif ($isReadingErrorMsg) { 3496b7e227cSYamadaMiz $errorMessages[$key] = $line; 3506b7e227cSYamadaMiz $isReadingErrorMsg = false; 3516b7e227cSYamadaMiz } 3526b7e227cSYamadaMiz } 3536b7e227cSYamadaMiz 3546b7e227cSYamadaMiz return $errorMessages; 3556b7e227cSYamadaMiz } 3566b7e227cSYamadaMiz 35747595f9cSYamadaMiz private function sendAjaxResponse($success, $message, $data = '') 35847595f9cSYamadaMiz { 3596b7e227cSYamadaMiz header('Content-Type: application/json'); 3606b7e227cSYamadaMiz echo json_encode(['success' => $success, 'message' => $message, 'data' => $data]); 3616b7e227cSYamadaMiz exit; 3626b7e227cSYamadaMiz } 363*9fc5dc4bSYamadaMiz 364*9fc5dc4bSYamadaMiz private function handleCompilationErrors($errFilename, $mizarMsgFilePath) 365*9fc5dc4bSYamadaMiz { 366*9fc5dc4bSYamadaMiz if (file_exists($errFilename)) { 367*9fc5dc4bSYamadaMiz $errors = []; 368*9fc5dc4bSYamadaMiz $errorLines = file($errFilename, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES); 369*9fc5dc4bSYamadaMiz if (empty($errorLines)) { 370*9fc5dc4bSYamadaMiz } 371*9fc5dc4bSYamadaMiz foreach ($errorLines as $errorLine) { 372*9fc5dc4bSYamadaMiz if (preg_match('/(\d+)\s+(\d+)\s+(\d+)/', $errorLine, $matches)) { 373*9fc5dc4bSYamadaMiz $errorCode = intval($matches[3]); 374*9fc5dc4bSYamadaMiz $errors[] = [ 375*9fc5dc4bSYamadaMiz 'code' => $errorCode, 376*9fc5dc4bSYamadaMiz 'line' => intval($matches[1]), 377*9fc5dc4bSYamadaMiz 'column' => intval($matches[2]), 378*9fc5dc4bSYamadaMiz 'message' => $this->getMizarErrorMessages($mizarMsgFilePath)[$errorCode] ?? 'Unknown error' 379*9fc5dc4bSYamadaMiz ]; 380*9fc5dc4bSYamadaMiz } 381*9fc5dc4bSYamadaMiz } 382*9fc5dc4bSYamadaMiz if (!empty($errors)) { 383*9fc5dc4bSYamadaMiz echo "event: compileErrors\n"; 384*9fc5dc4bSYamadaMiz echo "data: " . json_encode($errors) . "\n\n"; 385*9fc5dc4bSYamadaMiz ob_flush(); 386*9fc5dc4bSYamadaMiz flush(); 387*9fc5dc4bSYamadaMiz return true; 388*9fc5dc4bSYamadaMiz } 389*9fc5dc4bSYamadaMiz } 390*9fc5dc4bSYamadaMiz return false; 391*9fc5dc4bSYamadaMiz } 392*9fc5dc4bSYamadaMiz 393*9fc5dc4bSYamadaMiz private function handle_create_combined_file() 394*9fc5dc4bSYamadaMiz { 395*9fc5dc4bSYamadaMiz global $INPUT; 396*9fc5dc4bSYamadaMiz 397*9fc5dc4bSYamadaMiz // 投稿されたコンテンツを取得 398*9fc5dc4bSYamadaMiz $combinedContent = $INPUT->post->str('content'); 399*9fc5dc4bSYamadaMiz $filename = $INPUT->post->str('filename', 'combined_file.miz'); // ファイル名を取得、デフォルト名も設定 400*9fc5dc4bSYamadaMiz 401*9fc5dc4bSYamadaMiz // ファイルパスを指定 402*9fc5dc4bSYamadaMiz $workPath = rtrim($this->getConf('mizar_work_dir'), '/\\') . '/TEXT/'; 403*9fc5dc4bSYamadaMiz $filePath = $workPath . $filename; 404*9fc5dc4bSYamadaMiz 405*9fc5dc4bSYamadaMiz // ファイルを書き込み 406*9fc5dc4bSYamadaMiz if (file_put_contents($filePath, $combinedContent) !== false) { 407*9fc5dc4bSYamadaMiz // コピー先ディレクトリのパスを指定 408*9fc5dc4bSYamadaMiz $copyDir = DOKU_INC . 'lib/plugins/mizarproofchecker/TEXT/'; 409*9fc5dc4bSYamadaMiz 410*9fc5dc4bSYamadaMiz // コピー先ディレクトリが存在しない場合は作成する 411*9fc5dc4bSYamadaMiz if (!is_dir($copyDir)) { 412*9fc5dc4bSYamadaMiz mkdir($copyDir, 0777, true); 413*9fc5dc4bSYamadaMiz } 414*9fc5dc4bSYamadaMiz 415*9fc5dc4bSYamadaMiz // ファイルをコピー 416*9fc5dc4bSYamadaMiz if (copy($filePath, $copyDir . basename($filePath))) { 417*9fc5dc4bSYamadaMiz $fileUrl = DOKU_BASE . 'lib/plugins/mizarproofchecker/TEXT/' . urlencode($filename); 418*9fc5dc4bSYamadaMiz $this->sendAjaxResponse(true, 'File created successfully', ['fileUrl' => $fileUrl]); 419*9fc5dc4bSYamadaMiz error_log("Generated file URL: " . $fileUrl); 420*9fc5dc4bSYamadaMiz } else { 421*9fc5dc4bSYamadaMiz $this->sendAjaxResponse(false, 'Failed to copy file'); 422*9fc5dc4bSYamadaMiz } 423*9fc5dc4bSYamadaMiz } else { 424*9fc5dc4bSYamadaMiz $this->sendAjaxResponse(false, 'Failed to create file'); 425*9fc5dc4bSYamadaMiz } 426*9fc5dc4bSYamadaMiz } 4276b7e227cSYamadaMiz}