Passed
Pull Request — master (#6)
by
unknown
02:54
created

DocumentImporterField::importFromPOST()   F

Complexity

Conditions 33
Paths > 20000

Size

Total Lines 190
Code Lines 114

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
dl 0
loc 190
rs 2
c 1
b 0
f 0
cc 33
eloc 114
nc 169345
nop 4

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
namespace SilverStripe\DocumentConverter;
4
5
use DOMAttr;
6
use DOMDocument;
7
use DOMElement;
8
use DOMXPath;
9
use Page;
0 ignored issues
show
Bug introduced by
The type Page was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
10
use SilverStripe\AssetAdmin\Forms\UploadField;
0 ignored issues
show
Bug introduced by
The type SilverStripe\AssetAdmin\Forms\UploadField was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
11
use SilverStripe\Assets\File;
12
use SilverStripe\Assets\FileNameFilter;
13
use SilverStripe\Assets\Folder;
14
use SilverStripe\Assets\Image;
15
use SilverStripe\Assets\Upload;
16
use SilverStripe\Core\Config\Config;
17
use SilverStripe\Core\Convert;
18
use SilverStripe\Core\Injector\Injector;
19
use SilverStripe\Control\Director;
20
use SilverStripe\Control\HTTPRequest;
21
use SilverStripe\Control\HTTPResponse;
22
use SilverStripe\Forms\HTMLEditor\HtmlEditorConfig;
23
use SilverStripe\ORM\DataObject;
24
use SilverStripe\Versioned\Versioned;
25
use Tidy;
26
27
28
/**
29
 * DocumentImporterField is built on top of UploadField to access a document
30
 * conversion capabilities. The original field is stripped down to allow only
31
 * uploads from the user's computer, and triggers the conversion when the upload
32
 * is completed.
33
 *
34
 * The file upload has additional parameters injected. They are set by the user
35
 * through the fields provided on the DocumentImportField:
36
 *
37
 * * SplitHeader: if enabled, scans the document looking for H1 or H2 headers and
38
 *   puts each subsection into separate page. The first part of the document until
39
 *   the first header occurence is added to the current page.
40
 * * KeepSource: prevents the removal of the uploaded document, and stores its ID
41
 *   in the has_one relationship on the parent page (see the
42
 *   DocumentImportField::__construct for how to configure the name of this has_one)
43
 * * ChosenFolderID: directory to be used for storing the original document and the
44
 *   image files that come along with the document.
45
 * * PublishPages: whether the current and the chapter pages should be published.
46
 * * IncludeTOC: builds a table of contents and puts it into the parent page. This
47
 *   could potentially replace the document content from before the first heading.
48
 *   Also, if the KeepSource is enabled, it will inject the document link into this
49
 *   page.
50
 *
51
 *  Caveat: there is some coupling between the above parameters.
52
 */
53
class DocumentImporterField extends UploadField {
54
55
	private static $allowed_actions = ['upload'];
0 ignored issues
show
introduced by
The private property $allowed_actions is not used, and could be removed.
Loading history...
56
57
	private static $importer_class = DocumentConverter::class;
0 ignored issues
show
introduced by
The private property $importer_class is not used, and could be removed.
Loading history...
58
59
	/**
60
	 * Process the document immediately upon upload.
61
	 */
62
	public function upload(HTTPRequest $request) {
63
		if($this->isDisabled() || $this->isReadonly()) return $this->httpError(403);
64
65
		// Protect against CSRF on destructive action
66
		$token = $this->getForm()->getSecurityToken();
67
		if(!$token->checkRequest($request)) return $this->httpError(400);
68
69
		$name = $this->getName();
70
		$tmpfile = $request->postVar($name);
71
72
		// Check if the file has been uploaded into the temporary storage.
73
		if (!$tmpfile) {
74
			$return = array('error' => _t('SilverStripe\\AssetAdmin\\Forms\\UploadField.FIELDNOTSET', 'File information not found'));
75
		} else {
76
			$return = array(
77
				'name' => $tmpfile['name'],
78
				'size' => $tmpfile['size'],
79
				'type' => $tmpfile['type'],
80
				'error' => $tmpfile['error']
81
			);
82
		}
83
84
		if (!$return['error']) {
85
			// Get options for this import.
86
			$splitHeader = (int)$request->postVar('SplitHeader');
87
			$keepSource = (bool)$request->postVar('KeepSource');
88
			$chosenFolderID = (int)$request->postVar('ChosenFolderID');
89
			$publishPages = (bool)$request->postVar('PublishPages');
90
			$includeTOC = (bool)$request->postVar('IncludeTOC');
91
92
			// Process the document and write the page.
93
			$preservedDocument = null;
94
			if ($keepSource) $preservedDocument = $this->preserveSourceDocument($tmpfile, $chosenFolderID);
95
96
			$importResult = $this->importFromPOST($tmpfile, $splitHeader, $publishPages, $chosenFolderID);
0 ignored issues
show
Bug introduced by
$splitHeader of type integer is incompatible with the type boolean expected by parameter $splitHeader of SilverStripe\DocumentCon...Field::importFromPOST(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

96
			$importResult = $this->importFromPOST($tmpfile, /** @scrutinizer ignore-type */ $splitHeader, $publishPages, $chosenFolderID);
Loading history...
97
			if (is_array($importResult) && isset($importResult['error'])) {
98
				$return['error'] = $importResult['error'];
99
			} else if ($includeTOC) {
100
				$this->writeTOC($publishPages, $keepSource ? $preservedDocument : null);
101
			}
102
		}
103
104
		$response = HTTPResponse::create(Convert::raw2json(array($return)));
0 ignored issues
show
Bug introduced by
SilverStripe\Core\Conver...aw2json(array($return)) of type string is incompatible with the type array expected by parameter $args of SilverStripe\Control\HTTPResponse::create(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

104
		$response = HTTPResponse::create(/** @scrutinizer ignore-type */ Convert::raw2json(array($return)));
Loading history...
105
		$response->addHeader('Content-Type', 'text/plain');
106
		return $response;
107
	}
108
109
	/**
110
	 * Preserves the source file by copying it to a specified folder.
111
	 *
112
	 * @param $tmpfile Temporary file data structure.
0 ignored issues
show
Bug introduced by
The type SilverStripe\DocumentConverter\Temporary was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
113
	 * @param int $chosenFolderID Target folder.
114
	 * @return File Stored file.
115
	 */
116
	protected function preserveSourceDocument($tmpfile, $chosenFolderID = null) {
117
		$upload = Upload::create();
118
119
		$file = File::create();
120
		$upload->loadIntoFile($tmpfile, $file, $chosenFolderID);
121
122
		$page = $this->form->getRecord();
123
		$page->ImportedFromFileID = $file->ID;
124
		$page->write();
125
126
		return $file;
127
	}
128
129
	/**
130
	 * Builds and writes the table of contents for the document.
131
	 *
132
	 * @param bool $publishPage Should the parent page be published.
133
	 * @param File $preservedDocument Set if the link to the original document should be added.
134
	 */
135
	protected function writeTOC($publishPages = false, $preservedDocument = null) {
136
		$page = $this->form->getRecord();
137
		$content = '<ul>';
138
139
		if($page) {
140
			if($page->Children()->Count() > 0) {
141
				foreach($page->Children() as $child) {
142
					$content .= '<li><a href="' . $child->Link() . '">' . $child->Title . '</a></li>';
143
				}
144
				$page->Content = $content . '</ul>';
145
			}  else {
146
				$doc = new DOMDocument();
0 ignored issues
show
Bug introduced by
The call to DOMDocument::__construct() has too few arguments starting with version. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

146
				$doc = /** @scrutinizer ignore-call */ new DOMDocument();

This check compares calls to functions or methods with their respective definitions. If the call has less arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above.

Loading history...
147
				$doc->loadHTML($page->Content);
148
				$body = $doc->getElementsByTagName('body')->item(0);
149
				$node = $body->firstChild;
150
				$h1 = $h2 = 1;
151
				while($node) {
152
					if($node instanceof DOMElement && $node->tagName == 'h1') {
153
						$content .= '<li><a href="#h1.' . $h1 . '">'. trim(preg_replace('/\n|\r/', '', Convert::html2raw($node->textContent))) . '</a></li>';
154
						$node->setAttributeNode(new DOMAttr("id", "h1.".$h1));
155
						$h1++;
156
					} elseif($node instanceof DOMElement && $node->tagName == 'h2') {
157
						$content .= '<li class="menu-h2"><a href="#h2.' . $h2 . '">'. trim(preg_replace('/\n|\r/', '', Convert::html2raw($node->textContent))) . '</a></li>';
158
						$node->setAttributeNode(new DOMAttr("id", "h2.".$h2));
159
						$h2++;
160
					}
161
					$node = $node->nextSibling;
162
				}
163
				$page->Content = $content . '</ul>' . $doc->saveHTML();
164
			}
165
166
			// Add in the link to the original document, if provided.
167
			if($preservedDocument) {
168
				$page->Content = '<a href="' . $preservedDocument->Link() . '" title="download original document">download original document (' .
169
									$preservedDocument->getSize() . ')</a>' . $page->Content;
0 ignored issues
show
Bug introduced by
Are you sure $preservedDocument->getSize() of type false|string can be used in concatenation? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

169
									/** @scrutinizer ignore-type */ $preservedDocument->getSize() . ')</a>' . $page->Content;
Loading history...
170
			}
171
172
			// Store the result
173
			$page->write();
174
			if($publishPages) $page->doPublish();
175
		}
176
	}
177
178
	protected function getBodyText($doc, $node) {
179
		// Build a new doc
180
		$htmldoc = new DOMDocument();
0 ignored issues
show
Bug introduced by
The call to DOMDocument::__construct() has too few arguments starting with version. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

180
		$htmldoc = /** @scrutinizer ignore-call */ new DOMDocument();

This check compares calls to functions or methods with their respective definitions. If the call has less arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above.

Loading history...
181
		// Create the html element
182
		$html = $htmldoc->createElement('html');
183
		$htmldoc->appendChild($html);
184
		// Append the body node
185
		$html->appendChild($htmldoc->importNode($node, true));
186
187
		// Get the text as html, remove the entry and exit root tags and return
188
		$text = $htmldoc->saveHTML();
189
		$text = preg_replace('/^.*<body>/', '', $text);
190
		$text = preg_replace('/<\/body>.*$/', '', $text);
191
192
		return $text;
193
	}
194
195
	/**
196
	 * Used only when writing the document that has been split by headers.
197
	 * Can write both to the chapter pages as well as the master page.
198
	 *
199
	 * @param string $subtitle Title of the chapter - if missing, it will write to the master page.
200
	 * @param $subdoc
201
	 * @param $subnode
202
	 * @param int $sort Order of the chapter page.
203
	 * @param $publishPages Whether to publish the resulting child/master pages.
0 ignored issues
show
Bug introduced by
The type SilverStripe\DocumentConverter\Whether was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
204
	 */
205
	protected function writeContent($subtitle, $subdoc, $subnode, $sort = null, $publishPages = false) {
206
		$record = $this->form->getRecord();
207
208
		if($subtitle) {
209
			// Write the chapter page to a subpage.
210
			$page = DataObject::get_one('Page', sprintf('"Title" = \'%s\' AND "ParentID" = %d', $subtitle, $record->ID));
211
			if(!$page) {
212
				$page = Page::create();
213
				$page->ParentID = $record->ID;
214
				$page->Title = $subtitle;
215
			}
216
217
			unset($this->unusedChildren[$page->ID]);
218
			file_put_contents(ASSETS_PATH . '/index-' . $sort . '.html', $this->getBodyText($subdoc, $subnode));
219
220
			if ($sort) $page->Sort = $sort;
0 ignored issues
show
Bug Best Practice introduced by
The expression $sort of type null|integer is loosely compared to true; this is ambiguous if the integer can be 0. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For integer values, zero is a special case, in particular the following results might be unexpected:

0   == false // true
0   == null  // true
123 == false // false
123 == null  // false

// It is often better to use strict comparison
0 === false // false
0 === null  // false
Loading history...
221
			$page->Content = $this->getBodyText($subdoc, $subnode);
222
			$page->write();
223
			if($publishPages) $page->doPublish();
224
		} else {
225
			// Write to the master page.
226
			$record->Content = $this->getBodyText($subdoc, $subnode);
227
			$record->write();
228
229
			if($publishPages) $record->doPublish();
230
		}
231
232
	}
233
234
	/**
235
	 * Imports a document at a certain path onto the current page and writes it.
236
	 * CAUTION: Overwrites any existing content on the page!
237
	 *
238
	 * @param array $tmpFile Array as received from PHP's POST upload.
239
	 * @param bool $splitHeader Heading level to split by.
240
	 * @param bool $publishPages Whether the underlying pages should be published after import.
241
	 * @param int $chosenFolderID ID of the working folder - here the converted file and images will be stored.
242
	 */
243
	public function importFromPOST($tmpFile, $splitHeader = false, $publishPages = false, $chosenFolderID = null) {
244
245
		$fileDescriptor = array(
246
			'name' => $tmpFile['name'],
247
			'path' => $tmpFile['tmp_name'],
248
			'mimeType' => $tmpFile['type']
249
		);
250
251
		$sourcePage = $this->form->getRecord();
252
		$importerClass = Config::inst()->get(__CLASS__, 'importer_class');
253
		$importer = Injector::inst()->create($importerClass, $fileDescriptor, $chosenFolderID);
254
		$content = $importer->import();
255
256
		if (is_array($content) && isset($content['error'])) {
257
			return $content;
258
		}
259
260
		// Clean up with tidy (requires tidy module)
261
		$tidy = new Tidy();
262
		$tidy->parseString($content, array('output-xhtml' => true), 'utf8');
263
		$tidy->cleanRepair();
264
265
		$fragment = [];
266
		foreach($tidy->body()->child as $child) {
267
			$fragment[] = $child->value;
268
		}
269
270
		$htmlValue = Injector::inst()->create('HTMLValue', implode("\n", $fragment));
271
272
		// Sanitise
273
		$santiser = Injector::inst()->create('HtmlEditorSanitiser', HtmlEditorConfig::get_active());
274
		$santiser->sanitise($htmlValue);
275
276
		// Load in the HTML
277
		$doc = $htmlValue->getDocument();
278
		$xpath = new DOMXPath($doc);
279
280
		// make sure any images are added as Image records with a relative link to assets
281
		$chosenFolder = ($this->chosenFolderID) ? DataObject::get_by_id(Folder::class, $this->chosenFolderID) : null;
282
		$folderName = ($chosenFolder) ? '/' . $chosenFolder->Name : '';
283
		$imgs = $xpath->query('//img');
284
		for($i = 0; $i < $imgs->length; $i++) {
285
			$img = $imgs->item($i);
286
			$originalPath = 'assets/' . $folderName . '/' . $img->getAttribute('src');
287
			$name = FileNameFilter::create()->filter(basename($originalPath));
288
289
			$image = Image::get()->filter(array('Name' => $name, 'ParentID' => (int) $chosenFolderID))->first();
290
			if(!($image && $image->exists())) {
291
				$image = Image::create();
292
				$image->ParentID = (int) $chosenFolderID;
293
				$image->Name = $name;
294
				$image->write();
295
			}
296
297
			// make sure it's put in place correctly so Image record knows where it is.
298
			// e.g. in the case of underscores being renamed to dashes.
299
			@rename(Director::getAbsFile($originalPath), Director::getAbsFile($image->getFilename()));
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition for rename(). This can introduce security issues, and is generally not recommended. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unhandled  annotation

299
			/** @scrutinizer ignore-unhandled */ @rename(Director::getAbsFile($originalPath), Director::getAbsFile($image->getFilename()));

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
300
301
			$img->setAttribute('src', $image->getFilename());
302
		}
303
304
		$remove_rules = array(
305
			'//h1[.//font[not(@face)]]' => 'p', // Change any headers that contain font tags (other than font face tags) into p elements
306
			'//font' // Remove any font tags
307
		);
308
309
		foreach($remove_rules as $rule => $parenttag) {
310
			if(is_numeric($rule)) {
311
				$rule = $parenttag;
312
				$parenttag = null;
313
			}
314
315
			$nodes = array();
316
			foreach($xpath->query($rule) as $node) $nodes[] = $node;
317
318
			foreach($nodes as $node) {
319
				$parent = $node->parentNode;
320
321
				if($parenttag) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $parenttag of type null|string is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
322
					$parent = $doc->createElement($parenttag);
323
					$node->nextSibling ? $node->parentNode->insertBefore($parent, $node->nextSibling) : $node->parentNode->appendChild($parent);
324
				}
325
326
				while($node->firstChild) $parent->appendChild($node->firstChild);
327
				$node->parentNode->removeChild($node);
328
			}
329
		}
330
331
		// Strip style, class, lang attributes.
332
		$els = $doc->getElementsByTagName('*');
333
		for ($i = 0; $i < $els->length; $i++) {
334
			$el = $els->item($i);
335
			$el->removeAttribute('class');
336
			$el->removeAttribute('style');
337
			$el->removeAttribute('lang');
338
		}
339
340
		$els = $doc->getElementsByTagName('*');
0 ignored issues
show
Unused Code introduced by
The assignment to $els is dead and can be removed.
Loading history...
341
342
		// Remove a bunch of unwanted elements
343
		$clean = array(
344
			'//p[not(descendant-or-self::text() | descendant-or-self::img)]', // Empty paragraphs
345
			'//*[self::h1 | self::h2 | self::h3 | self::h4 | self::h5 | self::h6][not(descendant-or-self::text() | descendant-or-self::img)]', // Empty headers
346
			'//a[not(@href)]', // Anchors
347
			'//br' // BR tags
348
		);
349
350
		foreach($clean as $query) {
351
			// First get all the nodes. Need to build array, as they'll disappear from the nodelist while we're deleteing them, causing the indexing
352
			// to screw up.
353
			$nodes = array();
354
			foreach($xpath->query($query) as $node) $nodes[] = $node;
355
356
			// Then remove them all
357
			foreach ($nodes as $node) { if ($node->parentNode) $node->parentNode->removeChild($node); }
358
		}
359
360
		// Now split the document into portions by H1
361
		$body = $doc->getElementsByTagName('body')->item(0);
362
363
		$this->unusedChildren = array();
0 ignored issues
show
Bug Best Practice introduced by
The property unusedChildren does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
364
		foreach($sourcePage->Children() as $child) {
365
			$this->unusedChildren[$child->ID] = $child;
366
		}
367
368
		$documentImporterFieldError;
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $documentImporterFieldError does not exist. Did you maybe mean $documentImporterFieldErrorHandler?
Loading history...
369
370
		$documentImporterFieldErrorHandler = function ($errno, $errstr, $errfile, $errline) use ( $documentImporterFieldError ) {
0 ignored issues
show
Unused Code introduced by
The parameter $errfile is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

370
		$documentImporterFieldErrorHandler = function ($errno, $errstr, /** @scrutinizer ignore-unused */ $errfile, $errline) use ( $documentImporterFieldError ) {

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $errline is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

370
		$documentImporterFieldErrorHandler = function ($errno, $errstr, $errfile, /** @scrutinizer ignore-unused */ $errline) use ( $documentImporterFieldError ) {

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The import $documentImporterFieldError is not used and could be removed.

This check looks for imports that have been defined, but are not used in the scope.

Loading history...
Unused Code introduced by
The parameter $errstr is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

370
		$documentImporterFieldErrorHandler = function ($errno, /** @scrutinizer ignore-unused */ $errstr, $errfile, $errline) use ( $documentImporterFieldError ) {

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $errno is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

370
		$documentImporterFieldErrorHandler = function (/** @scrutinizer ignore-unused */ $errno, $errstr, $errfile, $errline) use ( $documentImporterFieldError ) {

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
371
			$documentImporterFieldError = _t(
0 ignored issues
show
Unused Code introduced by
The assignment to $documentImporterFieldError is dead and can be removed.
Loading history...
372
				'SilverStripe\\DocumentConverter\\DocumentConverter.PROCESSFAILED',
373
				'Could not process document, please double-check you uploaded a .doc or .docx format.',
374
				'Document Converter processes Word documents into HTML.'
375
			);
376
377
			// Do not cascade the error through other handlers
378
			return true;
379
		};
380
381
		set_error_handler($documentImporterFieldErrorHandler);
382
383
		$subtitle = null;
384
		$subdoc = new DOMDocument();
0 ignored issues
show
Bug introduced by
The call to DOMDocument::__construct() has too few arguments starting with version. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

384
		$subdoc = /** @scrutinizer ignore-call */ new DOMDocument();

This check compares calls to functions or methods with their respective definitions. If the call has less arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above.

Loading history...
385
		$subnode = $subdoc->createElement('body');
386
		$node = $body->firstChild;
387
		$sort = 1;
388
		if($splitHeader == 1 || $splitHeader == 2) {
389
			while($node && !$documentImporterFieldError) {
390
				if($node instanceof DOMElement && $node->tagName == 'h' . $splitHeader) {
391
					if($subnode->hasChildNodes()) {
392
						$this->writeContent($subtitle, $subdoc, $subnode, $sort, $publishPages);
393
						$sort++;
394
					}
395
396
					$subdoc = new DOMDocument();
397
					$subnode = $subdoc->createElement('body');
398
					$subtitle = trim(preg_replace('/\n|\r/', '', Convert::html2raw($node->textContent)));
399
				} else {
400
					$subnode->appendChild($subdoc->importNode($node, true));
401
				}
402
403
				$node = $node->nextSibling;
404
			}
405
		} else {
406
			$this->writeContent($subtitle, $subdoc, $body, null, $publishPages);
407
		}
408
409
		if($subnode->hasChildNodes() && !$documentImporterFieldError) {
410
			$this->writeContent($subtitle, $subdoc, $subnode, null, $publishPages);
411
		}
412
413
		restore_error_handler();
414
		if ($documentImporterFieldError) {
415
			return array('error' => $documentImporterFieldError);
416
		}
417
418
		foreach($this->unusedChildren as $child) {
419
			$origStage = Versioned::current_stage();
0 ignored issues
show
Bug introduced by
The method current_stage() does not exist on SilverStripe\Versioned\Versioned. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

419
			/** @scrutinizer ignore-call */ 
420
   $origStage = Versioned::current_stage();

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
420
421
			Versioned::reading_stage('Stage');
0 ignored issues
show
Bug introduced by
The method reading_stage() does not exist on SilverStripe\Versioned\Versioned. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

421
			Versioned::/** @scrutinizer ignore-call */ 
422
              reading_stage('Stage');

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
422
			$clone = clone $child;
423
			$clone->delete();
424
425
			Versioned::reading_stage('Live');
426
			$clone = clone $child;
427
			$clone->delete();
428
429
			Versioned::reading_stage($origStage);
430
		}
431
432
		$sourcePage->write();
433
	}
434
}
435