Repo for the search and displace core module including the interface to select files and search and displace operations to run on them. https://searchanddisplace.com
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

182 lines
5.4 KiB

<?php
namespace App\SearchDisplace;
use App\SearchDisplace\Documents\DocumentFile;
use Illuminate\Support\Facades\Storage;
use App\SearchDisplace\Convertor\Convertor;
use DOMDocument;
class SearchAndDisplaceXML
{
protected $file;
protected $searchers;
protected $storage;
protected $searchOnly;
protected $markedStyleCreated;
public function __construct($file, $searchers, $searchOnly)
{
$this->fileDirectory = $file;
$this->searchers = $searchers;
$this->storage = Storage::disk('local');
$this->searchOnly = $searchOnly;
$this->markedStyleCreated = false;
}
public function execute()
{
$sdXML = $this->applySD();
$pathinfo = pathinfo($sdXML);
$this->convertSearchDisplacedXMLToHTML($sdXML);
DocumentFile::updateImagesPath($pathinfo['dirname'] . '/document_sdapplied.html', $this->fileDirectory);
return $pathinfo['filename'];
}
/**
* Convert (Search displaced) XML to HTML for browser preview
*
* @return void
*/
protected function convertSearchDisplacedXMLToHTML($file)
{
Convertor::convert('html', $file);
}
/**
* Read XML document and send text contents to SD
*
* @return void
*/
protected function applySD()
{
$dom = new \DOMDocument();
$filePath = $this->storage->path("contracts/$this->fileDirectory");
$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") {
foreach($p->childNodes as $child) {
if(isset($child->tagName) && $child->tagName === "text:span") {
$content = trim($child->textContent);
if($content == '') {
continue;
}
$this->replace($content, $child, $dom);
}
}
} else {
$content = trim($p->textContent);
if($content == '') {
continue;
}
$this->replace($content, $p, $dom);
}
}
$dom->save($filePath . "/document_sdapplied.xml");
return $filePath . "/document_sdapplied.xml";
}
/**
* Apply SD on document's paragraph
*
* @param string $content paragraph content
* @param $element DOM element
*
* @return void
*/
protected function replace($content, $element, $dom)
{
$search = new SearchAndDisplace(
stripslashes($content),
[
'searchers' => $this->searchers,
],
$this->searchOnly,
true
);
$changed = $search->execute();
if($changed) {
if($this->searchOnly) {
$content = $element->textContent;
$indexes = $changed;
} else {
$content = $changed['content'];
$indexes = $changed['indexes'];
}
foreach(array_keys($indexes) as $searcher) {
if(empty($indexes[$searcher])) {
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);
}
}
if(!$this->markedStyleCreated) {
$this->createMarkedStyle($dom);
}
$this->markedStyleCreated = true;
}
}
/**
* Create marked style for browser preview
*
*/
private function createMarkedStyle($dom)
{
$style = $dom->createElement("style:style");
$style->setAttribute("style:name", 'mark');
$style->setAttribute("style:family", 'text');
$child = $dom->createElement('style:text-properties');
$child->setAttribute("officeooo:rsid", '0014890a');
$child->setAttribute("fo:background-color", '#ffff00');
$style->appendChild($child);
$dom->getElementsByTagName('automatic-styles')->item(0)->appendChild($style);
}
/**
* 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)
{
// remove marked style from XML
$dom = new DOMDocument();
$dom->load($file);
$style = $dom->getElementsByTagName('automatic-styles')->item(0);
$style->removeChild($style->lastChild);
$dom->save($file);
return Convertor::convert($type, $file, true);
}
}