From fce31deabd5063305ad500f583991cca74f41375 Mon Sep 17 00:00:00 2001 From: Alex Puiu Date: Thu, 24 Feb 2022 11:49:51 +0200 Subject: [PATCH] Create document using LibreOffice --- app/Http/Controllers/FileController.php | 58 ++++++++++++------- .../js/components/ProcessFile/ProcessFile.ts | 12 +++- resources/js/services/ApiService.ts | 5 +- routes/web.php | 8 +++ 4 files changed, 60 insertions(+), 23 deletions(-) diff --git a/app/Http/Controllers/FileController.php b/app/Http/Controllers/FileController.php index 169919b..4d08c04 100644 --- a/app/Http/Controllers/FileController.php +++ b/app/Http/Controllers/FileController.php @@ -7,8 +7,8 @@ use Illuminate\Http\JsonResponse; use Illuminate\Support\Facades\Storage; use Illuminate\Http\UploadedFile; use GuzzleHttp\Exception\BadResponseException; +use App\SearchDisplace\SearchAndDisplace; use Symfony\Component\Process\Process; -use Symfony\Component\Process\Exception\ProcessFailedException; class FileController extends Controller { @@ -41,6 +41,15 @@ class FileController extends Controller 'name' => $file->getClientOriginalName() ]); + $originalFile = $fileId . "/{$fileId}." . $file->extension(); + + Storage::disk('local')->put("contracts/{$originalFile}", file_get_contents($file)); // keep the original file + + $process = new Process(['soffice', '--convert-to', 'xml', storage_path('app/contracts/' . $originalFile), '--outdir', storage_path('app/contracts/') . $fileId]); + $process->run(); + + Storage::delete("contracts/{$originalFile}"); + return response()->json([ 'id' => $fileId, 'file_name' => $file->getClientOriginalName(), @@ -62,26 +71,38 @@ class FileController extends Controller */ public function convert(): JsonResponse { - $mdFileContent = request()->input('content'); $fileId = request()->input('file_id'); + $searchers = request()->input('searchers'); - Storage::disk('local')->put('tmp/' . $fileId . '.md', $mdFileContent); - $tmpFilePath = Storage::path('tmp/' . $fileId); - - $process = new Process(['pandoc', '-f', 'markdown_strict', $tmpFilePath . '.md', '-t', 'html']); - $process->run(); - if (!$process->isSuccessful()) { - throw new ProcessFailedException($process); + $xml = storage_path() . "/app/contracts/{$fileId}/{$fileId}.xml"; + $dom = new \DOMDocument(); + $dom->load($xml); + foreach($dom->getElementsByTagName('p') as $key => $text) { + $is_image = false; + if($text->childNodes) { + foreach($text->childNodes as $child) { + if(isset($child->tagName) && $child->tagName == 'draw:frame') { + $is_image = true; + } + } + } + if(!$is_image) { + $searchAndDisplace = new SearchAndDisplace( + stripslashes($text->textContent), + [ + 'searchers' => $searchers, + ] + ); + + $response = $searchAndDisplace->execute(); + $text->textContent = $response['content']; + } } - $output = str_replace('./contracts-images', config('app.url') . '/contracts-images', $process->getOutput()); - Storage::disk('local')->put('tmp/' . $fileId . '.html', $output); - - $process = new Process([ 'pandoc', '-f', 'html', $tmpFilePath . '.html', '-t', 'odt', '-o', $tmpFilePath . '.odt']); + $dom->save($xml); + + $process = new Process(['soffice', '--convert-to', 'odt', $xml, '--outdir', storage_path('app/tmp/')]); $process->run(); - if (!$process->isSuccessful()) { - throw new ProcessFailedException($process); - } return response()->json([ 'path' => 'tmp/' . $fileId . '.odt' @@ -107,10 +128,7 @@ class FileController extends Controller public function delete(string $id): JsonResponse { $success = Storage::delete([ - "tmp/{$id}.md", - "tmp/{$id}.odt", - "tmp/{$id}.html", - "contracts/{$id}.md", + "tmp/{$id}.odt" ]); return response()->json(['success' => $success]); } diff --git a/resources/js/components/ProcessFile/ProcessFile.ts b/resources/js/components/ProcessFile/ProcessFile.ts index cfa9838..c8f8ab9 100644 --- a/resources/js/components/ProcessFile/ProcessFile.ts +++ b/resources/js/components/ProcessFile/ProcessFile.ts @@ -418,7 +418,17 @@ export default class ProcessFile extends Vue { * Download the document in ODT format */ private async downloadOdt() { - let response = await this.$api.convertFile(this.processedFileContent, this.file.id); + let searchers: Array<{ key: string; type: string; value: string; }> = []; + + Object.values(this.selectedSearchers).forEach((searcher: any) => { + searchers.push({ + key: searcher.id, + type: this.searchersOptions[searcher.id].type, + value: this.searchersOptions[searcher.id].value || '', + }); + }); + + let response = await this.$api.convertFile(this.processedFileContent, this.file.id, searchers); window.open(`${window.location.origin}/file/download/` + response.path); } diff --git a/resources/js/services/ApiService.ts b/resources/js/services/ApiService.ts index adfe1f3..07ea8be 100644 --- a/resources/js/services/ApiService.ts +++ b/resources/js/services/ApiService.ts @@ -145,13 +145,14 @@ export default class ApiService { * * @returns */ - public async convertFile(content: string, fileId: string) { + public async convertFile(content: string, fileId: string, searchers: Array<{ key: string; type: string; value: string; }>) { try { let response = await axios.post( this.apiRoutes.fileDownload, { 'file_id': fileId, - 'content': content + 'content': content, + 'searchers': searchers } ); diff --git a/routes/web.php b/routes/web.php index a12a3ed..6c290e7 100644 --- a/routes/web.php +++ b/routes/web.php @@ -15,6 +15,14 @@ use Illuminate\Support\Facades\Route; */ Route::get('/', 'HomeController@index'); +// Route::get('/', function() { +// $dom = new DOMDocument(); +// $dom->load(storage_path() . '/doc.xml'); + +// $dom->getElementsByTagName('p')->item(0)->nodeValue = 'changed'; + +// $dom->save(storage_path() . '/changed.xml'); +// }); Route::get('/file/download/{path}', [ FileController::class,