Browse Source

Fixes to S&D XML processing

master
Radu Liviu Carjan 2 years ago
parent
commit
9c7d8df866
  1. 4
      app/Http/Controllers/SearchAndDisplaceController.php
  2. 21
      app/SearchDisplace/Convertor/Convertor.php
  3. 105
      app/SearchDisplace/SearchAndDisplaceXML.php
  4. 4
      package-lock.json

4
app/Http/Controllers/SearchAndDisplaceController.php

@ -12,9 +12,9 @@ class SearchAndDisplaceController extends Controller
public function __construct()
{
$this->storage = Storage::disk('local');
$this->storage = Storage::disk('local');
}
public function show($id)
{
$handler = new DocumentFile();

21
app/SearchDisplace/Convertor/Convertor.php

@ -3,6 +3,7 @@
namespace App\SearchDisplace\Convertor;
use Symfony\Component\Process\Process;
use Symfony\Component\Process\Exception\ProcessFailedException;
/**
* Convert documents from formats supported by Libre Office
@ -13,7 +14,7 @@ class Convertor {
* @param $to desired file format
* @param $document absolute file path
* @param $tmp - if true file will be saved to tmp directory for download
*
*
* @return string $path to converted file
*/
public static function convert($to, $document, $tmp = false)
@ -27,9 +28,25 @@ class Convertor {
$folder = storage_path('app/tmp/');
}
$process = new Process(['soffice', '--convert-to', $to, $original, '--outdir', $folder]);
$process = new Process(
[
'soffice',
'--convert-to',
$to,
$original,
'--outdir',
$folder
], base_path(),
[
'HOME' => base_path()
]
);
$process->run();
if (!$process->isSuccessful()) {
throw new ProcessFailedException($process);
}
return $path['filename'] . '.' . $to;
}
}

105
app/SearchDisplace/SearchAndDisplaceXML.php

@ -6,6 +6,8 @@ use App\SearchDisplace\Documents\DocumentFile;
use Illuminate\Support\Facades\Storage;
use App\SearchDisplace\Convertor\Convertor;
use DOMDocument;
use DOMNode;
use DOMText;
class SearchAndDisplaceXML
{
@ -19,8 +21,8 @@ class SearchAndDisplaceXML
{
$this->fileDirectory = $file;
$this->searchers = $searchers;
$this->storage = Storage::disk('local');
$this->searchOnly = $searchOnly;
$this->storage = Storage::disk('local');
$this->searchOnly = $searchOnly;
$this->markedStyleCreated = false;
}
@ -35,10 +37,10 @@ class SearchAndDisplaceXML
return $pathinfo['filename'];
}
/**
* Convert (Search displaced) XML to HTML for browser preview
*
*
* @return void
*/
protected function convertSearchDisplacedXMLToHTML($file)
@ -48,7 +50,7 @@ class SearchAndDisplaceXML
/**
* Read XML document and send text contents to SD
*
*
* @return void
*/
protected function applySD()
@ -58,24 +60,24 @@ class SearchAndDisplaceXML
$dom->load($filePath . "/document.xml");
foreach($dom->getElementsByTagName('p') as $p) {
if(count($p->childNodes) > 0 && isset($p->parentNode->tagName) && $p->parentNode->tagName !== "table:table-cell") {
if(
!$p instanceof DOMText &&
count($p->childNodes) > 0 &&
isset($p->parentNode->tagName) &&
$p->parentNode->tagName !== "table:table-cell"
) {
$replacements = [];
foreach($p->childNodes as $child) {
if(isset($child->tagName) && $child->tagName === "text:span") {
$content = trim($child->textContent);
if($content == '') {
continue;
}
if (in_array($child, $replacements)) {
continue;
}
$this->replace($content, $child, $dom);
if (!$child instanceof DOMText) {
continue;
}
}
} else {
$content = trim($p->textContent);
if($content == '') {
continue;
}
$this->replace($content, $p, $dom);
$replacements = array_merge($replacements, $this->replace($child, $dom));
}
}
}
@ -86,14 +88,17 @@ class SearchAndDisplaceXML
/**
* Apply SD on document's paragraph
*
* @param string $content paragraph content
* @param $element DOM element
*
* @return void
*
* @param DOMNode $element DOM element
* @param DOMDocument $dom The document
*
* @return array
*/
protected function replace($content, $element, $dom)
protected function replace(DOMText &$element, DOMDocument &$dom)
{
/** @var string $content */
$content = $element->textContent ?? $element->nodeValue;
$search = new SearchAndDisplace(
stripslashes($content),
[
@ -105,6 +110,8 @@ class SearchAndDisplaceXML
$changed = $search->execute();
$replacementNodes = [];
if($changed) {
if($this->searchOnly) {
$content = $element->textContent;
@ -114,23 +121,35 @@ class SearchAndDisplaceXML
$indexes = $changed['indexes'];
}
foreach(array_keys($indexes) as $searcher) {
if(empty($indexes[$searcher])) {
foreach($indexes as $searcher => $changes) {
if(empty($changes)) {
continue;
}
foreach($indexes[$searcher] as $change) {
$first = substr($content, 0, $change['start']);
$changed = substr($content, $change['start'], $change['end'] - $change['start'] + 1);
$last = substr($content, $change['end'] + 1);
$element->textContent = $first;
$changed = $dom->createElement("text:span", $changed);
$last = $dom->createElement("text:span", $last);
//text:style-name="mark"
$changed->setAttribute('text:style-name', 'mark');
$element->appendChild($changed);
$element->appendChild($last);
foreach($changes as $change) {
$firstContent = substr($content, 0, $change['start']);
$changedContent = substr($content, $change['start'], $change['end'] - $change['start'] + 1);
$lastContent = substr($content, $change['end'] + 1);
// $firstNode = $dom->createElement("text:span", $firstContent);
$element->textContent = $firstContent;
$changedNode = $dom->createElement("text:span", $changedContent);
$changedNode->setAttribute('text:style-name', 'mark');
$lastNode = $dom->createElement("text:span", $lastContent);
// Add the changed and last nodes after the current (element) node
// $element->parentNode->insertBefore($firstNode, $element->nextSibling);
# element->parentNode->insertBefore(... $element->nextSibling) inserts a new node before the node AFTER this one
# So we need to add the `last` node first, and then the `changed` node BEFORE the last.
$element->parentNode->insertBefore($lastNode, $element->nextSibling);
$element->parentNode->insertBefore($changedNode, $element->nextSibling);
$replacementNodes[] = $changedNode;
$replacementNodes[] = $lastNode;
}
}
@ -139,11 +158,13 @@ class SearchAndDisplaceXML
}
$this->markedStyleCreated = true;
}
return $replacementNodes;
}
/**
* Create marked style for browser preview
*
*
*/
private function createMarkedStyle($dom)
{
@ -162,10 +183,10 @@ class SearchAndDisplaceXML
/**
* Remove marked style used in browser and convert XML file to original file type
*
*
* @param $type file type
* @param $file absolute file path
*
*
* @return string $path
*/
public static function prepareForDownload($type, $file)

4
package-lock.json

@ -1,12 +1,12 @@
{
"name": "search-and-displace-core",
"version": "1",
"version": "1.0.0",
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
"name": "search-and-displace-core",
"version": "1",
"version": "1.0.0",
"dependencies": {
"@types/jquery": "^3.5.14",
"@types/marked": "^2.0.3",

Loading…
Cancel
Save