Passed
Push — master ( 4c04ba...ab5041 )
by Arne
02:45
created

SourceFile::getSource()   B

Complexity

Conditions 6
Paths 8

Size

Total Lines 43
Code Lines 24

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 42

Importance

Changes 0
Metric Value
eloc 24
dl 0
loc 43
ccs 0
cts 32
cp 0
rs 8.9137
c 0
b 0
f 0
cc 6
nc 8
nop 0
crap 42
1
<?php declare(strict_types = 1);
2
namespace TheSeer\phpDox\Collector;
3
4
use TheSeer\fDOM\fDOMDocument;
5
use TheSeer\fDOM\fDOMElement;
6
use TheSeer\phpDox\Collector\Backend\SourceFileException;
7
use TheSeer\phpDox\FileInfo;
8
9
class SourceFile extends FileInfo {
10
    /**
11
     * PHPDOX Namespace
12
     */
13
    public const XMLNS = 'http://xml.phpdox.net/src';
14
15
    /**
16
     * @var string
17
     */
18
    private $src;
19
20
    /**
21
     * @var FileInfo
22
     */
23
    private $srcDir;
24
25
    /**
26
     * @var
27
     */
28
    private $encoding;
29
30
    public function __construct($file_name, FileInfo $srcDir = null, $encoding = 'auto') {
31
        parent::__construct($file_name);
32
        $this->srcDir   = $srcDir;
33
        $this->encoding = $encoding;
34
    }
35
36
    /**
37
     * @throws Backend\SourceFileException
38
     */
39
    public function getSource(): string {
40
        if ($this->src !== null) {
41
            return $this->src;
42
        }
43
44
        $source = \file_get_contents($this->getPathname());
45
46
        if ($source === '') {
47
            $this->src = '';
48
49
            return '';
50
        }
51
52
        if ($this->encoding == 'auto') {
53
            $info           = new \finfo();
54
            $this->encoding = $info->file((string)$this, \FILEINFO_MIME_ENCODING);
55
        }
56
57
        try {
58
            $source = \iconv($this->encoding, 'UTF-8//TRANSLIT', $source);
59
        } catch (\ErrorException $e) {
60
            throw new SourceFileException('Encoding error - conversion to UTF-8 failed', SourceFileException::BadEncoding, $e);
61
        }
62
63
        // Replace xml relevant control characters by surrogates
64
        $this->src = \preg_replace_callback(
65
            '/(?![\x{000d}\x{000a}\x{0009}])\p{C}/u',
66
            function (array $matches) {
67
                $unicodeChar = '\u' . (2400 + \ord($matches[0]));
68
69
                return \json_decode('"' . $unicodeChar . '"');
70
            },
71
            $source
72
        );
73
74
        if ($this->src === null) {
75
            throw new SourceFileException(
76
                sprintf('Error %d while executing regular expression callback', \preg_last_error()),
77
                SourceFileException::RegexError
78
            );
79
        }
80
81
        return $this->src;
82
    }
83
84
    /**
85
     * @throws Backend\SourceFileException
86
     */
87
    public function getTokens(): fDOMDocument {
88
        $tokenizer = new Tokenizer();
89
        $dom       = $tokenizer->toXML($this->getSource());
90
        $root      = $dom->documentElement;
91
        $root->insertBefore($this->asNode($dom->documentElement), $root->firstChild);
92
93
        return $dom;
94
    }
95
96
    /**
97
     * @param fDOMDocument $ctx
98
     */
99
    public function asNode(fDOMElement $ctx): fDOMElement {
100
        $fileNode = $ctx->ownerDocument->createElementNS(self::XMLNS, 'file');
101
        $fileNode->setAttribute('path', $this->getPath());
102
        $fileNode->setAttribute('file', $this->getBasename());
103
        $fileNode->setAttribute('realpath', $this->getRealPath());
104
        $fileNode->setAttribute('size', $this->getSize());
105
        $fileNode->setAttribute('time', \date('c', $this->getMTime()));
106
        $fileNode->setAttribute('unixtime', $this->getMTime());
107
        $fileNode->setAttribute('sha1', \sha1_file($this->getRealPath()));
108
109
        if ($this->srcDir instanceof FileInfo) {
0 ignored issues
show
introduced by Arne Blankerts
$this->srcDir is always a sub-type of TheSeer\phpDox\FileInfo.
Loading history...
110
            $fileNode->setAttribute('relative', $this->getRelative($this->srcDir, false));
111
        }
112
113
        return $fileNode;
114
    }
115
}
116