Scanner::scan()   A
last analyzed

Complexity

Conditions 2
Paths 2

Size

Total Lines 18
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 11
CRAP Score 2
Metric Value
dl 0
loc 18
ccs 11
cts 11
cp 1
rs 9.4285
cc 2
eloc 10
nc 2
nop 2
crap 2
1
<?php namespace KamranAhmed\Smasher;
2
3
use KamranAhmed\Smasher\Contracts\ResponseContract;
4
use KamranAhmed\Smasher\Exceptions\InvalidContentException;
5
use KamranAhmed\Smasher\Exceptions\NoContentException;
6
7
/**
8
 * Spider
9
 *
10
 * Responsible for crawling the paths and gathering information
11
 */
12
class Scanner
13
{
14
    /**
15
     * @var \KamranAhmed\Smasher\Path The path to operate on
16
     */
17
    protected $path;
18
19
    /**
20
     * @var \KamranAhmed\Smasher\Contracts\ResponseContract Format for the response
21
     */
22
    protected $response;
23
24
    /**
25
     * @var string Encoded response which will be returned
26
     */
27
    protected $result;
28
29
    /**
30
     * Scanner constructor.
31
     *
32
     * @param \KamranAhmed\Smasher\Contracts\ResponseContract $response
33
     */
34 8
    public function __construct(ResponseContract $response)
35
    {
36 8
        $this->path     = new Path();
37 8
        $this->response = $response;
38 8
        $this->result   = '';
39 8
    }
40
41
    /**
42
     * Scans the provided path and returns the encoded response. Also if
43
     * resultPath is provided then the response will be stored in the resultPath
44
     *
45
     * @param        $path          The path to scan
46
     * @param string $resultPath    The path at which the resultant file will be created
47
     *
48
     * @throws \KamranAhmed\Smasher\Exceptions\InvalidPathException
49
     * @throws \KamranAhmed\Smasher\Exceptions\UnreadablePathException
50
     *
51
     * @return string
52
     */
53 3
    public function scan($path, $resultPath = '')
54
    {
55 3
        $this->path->setPath($path);
56 3
        $this->path->validate();
57
58 2
        $result = [];
59 2
        $this->probe($path, $result);
60
61 2
        $this->result = $this->response->encode($result);
62
63
        // If the result path is provided, data will be saved as well
64 2
        if (!empty($resultPath)) {
65 1
            $this->path->setPath($resultPath);
66 1
            $this->path->saveFileContent($this->result);
67 1
        }
68
69 2
        return $this->result;
70
    }
71
72
    /**
73
     * Probes the path and keeps populating the array with the results
74
     *
75
     * @param        $path
76
     * @param        $parentItem
77
     * @param string $fullPath
78
     */
79 3
    protected function probe($path, &$parentItem, $fullPath = '')
80
    {
81 3
        if (empty($fullPath)) {
82 3
            $fullPath = $path;
83 3
        }
84
85 3
        $pathParts = explode('/', $path);
86 3
        $path      = $pathParts[count($pathParts) - 1];
87
88 3
        $this->path->setPath($fullPath);
89 3
        $parentItem[$path] = $this->path->getDetail();
90
91 3
        if ($this->path->getType() === 'dir') {
92
            // Recursively iterate the directory and find the inner contents
93 3
            $handle = opendir($fullPath);
94
95 3
            while ($content = readdir($handle)) {
96 3
                if ($content == '.' || $content == '..') {
97 3
                    continue;
98
                }
99
100 3
                $this->probe($content, $parentItem[$path], $fullPath . '/' . $content);
101 3
            };
102 3
        }
103 3
    }
104
105
    /**
106
     * Uses the source file to populate the path provided
107
     *
108
     * @param $outputDir    The directory at which the content from file is to be populated
109
     * @param $sourceFile   The file to use for populating
110
     */
111 1
    public function populate($outputDir, $sourceFile)
112
    {
113 1
        $this->populatePath($outputDir, $sourceFile);
114 1
    }
115
116
    /**
117
     * Uses the smashed/response file to recursively populate the path
118
     *
119
     * @param       $outputDir   Where to populate the output
120
     * @param       $sourceFile  Path to the source file
121
     * @param array $content     The array to use instead of the source file
122
     * @param bool  $isRecursive Whether it is the recursive call
123
     *
124
     * @throws \KamranAhmed\Smasher\Exceptions\InvalidContentException
125
     * @throws \KamranAhmed\Smasher\Exceptions\NoContentException
126
     */
127 1
    private function populatePath($outputDir, $sourceFile, $content = [], $isRecursive = false)
128
    {
129 1
        if ($isRecursive === false) {
130 1
            $content = $this->getScannedContent($sourceFile);
131 1
        }
132
133 1
        if (!is_dir($outputDir)) {
134
            $this->path->setPath($outputDir);
135
            $this->path->createItem();
136
        }
137
138 1
        foreach ($content as $label => $detail) {
139
140
            // if it is a property
141 1
            if ($label[0] === '@') {
142 1
                continue;
143
            }
144
145 1
            $toCreate = $outputDir . '/' . $label;
146
147 1
            if (!file_exists($toCreate)) {
148 1
                $this->path->setPath($toCreate);
149 1
                $this->path->createItem($detail);
150 1
            }
151
152 1
            if (empty($detail['@type']) || ($detail['@type'] == 'dir')) {
153 1
                $this->populatePath($toCreate, '', $detail, true);
154 1
            }
155 1
        }
156 1
    }
157
158
    /**
159
     * Gets the scanned content from passed file
160
     *
161
     * @param $path
162
     *
163
     * @throws \KamranAhmed\Smasher\Exceptions\InvalidContentException
164
     * @throws \KamranAhmed\Smasher\Exceptions\NoContentException
165
     * @throws \KamranAhmed\Smasher\Exceptions\UnreadablePathException
166
     *
167
     * @return array
168
     */
169 4
    protected function getScannedContent($path)
170
    {
171 4
        $this->path->setPath($path);
172 4
        $this->path->validate();
173
174 4
        $content = $this->path->getFileContent();
175
176 4
        if (empty($content)) {
177 1
            throw new NoContentException("The file ' . $path . ' has no content", 1);
178
        }
179
180 3
        $result = $this->response->decode($content);
181
182 3
        if (!is_array($result)) {
183 1
            throw new InvalidContentException("The content in file " . $path . " could not be processed", 1);
184
        }
185
186 2
        return $result;
187
    }
188
}
189