Completed
Push — master ( 0ba1b3...937b8a )
by Vladimir
02:47
created

TrackingManager   A

Complexity

Total Complexity 26

Size/Duplication

Total Lines 306
Duplicated Lines 0 %

Coupling/Cohesion

Components 5
Dependencies 4

Test Coverage

Coverage 64.71%

Importance

Changes 0
Metric Value
wmc 26
lcom 5
cbo 4
dl 0
loc 306
ccs 44
cts 68
cp 0.6471
rs 10
c 0
b 0
f 0

15 Methods

Rating   Name   Duplication   Size   Complexity  
A saveFolderDefinition() 0 5 1
A saveTrackerOptions() 0 4 1
A delArrayFromTracker() 0 13 2
A delObjectFromTracker() 0 8 1
A scanTrackableItems() 0 11 3
A __construct() 0 11 1
A isTracked() 0 4 1
A addArrayToTracker() 0 13 2
A addObjectToTracker() 0 9 3
B getJailedTrackedItems() 0 24 5
handleTrackableItem() 0 1 ?
A enableTracking() 0 4 1
A isHandled() 0 12 3
A createNewItem() 0 4 1
A refreshItem() 0 4 1
1
<?php
2
3
/**
4
 * @copyright 2017 Vladimir Jimenez
5
 * @license   https://github.com/allejo/stakx/blob/master/LICENSE.md MIT
6
 */
7
8
namespace allejo\stakx\Manager;
9
10
use allejo\stakx\Command\BuildableCommand;
11
use allejo\stakx\Document\JailedDocument;
12
use allejo\stakx\Document\PageView;
13
use allejo\stakx\Document\TwigDocumentInterface;
14
use allejo\stakx\FrontMatter\FrontMatterDocument;
15
use allejo\stakx\Service;
16
use allejo\stakx\System\FileExplorer;
17
use Symfony\Component\Finder\SplFileInfo;
18
19
/**
20
 * Class TrackingManager.
21
 */
22
abstract class TrackingManager extends BaseManager
23
{
24
    /**
25
     * @var FileExplorer
26
     */
27
    protected $fileExplorer;
28
29
    /**
30
     * An array corresponding with $folderDefinitions to store metadata regarding a specificc folder.
31
     *
32
     * $folderDefinitionsOption['<folder path>'] = array()
33
     *
34
     * @var string[]
35
     */
36
    protected $folderDefinitionsOptions;
0 ignored issues
show
Comprehensibility Naming introduced by
The variable name $folderDefinitionsOptions exceeds the maximum configured length of 20.

Very long variable names usually make code harder to read. It is therefore recommended not to make variable names too verbose.

Loading history...
37
38
    /**
39
     * An array of folders which tracked items are stored in.
40
     *
41
     * $folderDefinitions[] = '<folder path>'
42
     *
43
     * @var string[]
44
     */
45
    protected $folderDefinitions;
46
47
    /**
48
     * The storage which contains the same information as $trackedItems but organized by relative file path instead of a
49
     * namespace or file name without extension.
50
     *
51
     * $trackedItemsOptions['<relative file path>'] = mixed
52
     *
53
     * @var array
54
     */
55
    protected $trackedItemsFlattened;
0 ignored issues
show
Comprehensibility Naming introduced by
The variable name $trackedItemsFlattened exceeds the maximum configured length of 20.

Very long variable names usually make code harder to read. It is therefore recommended not to make variable names too verbose.

Loading history...
56
57
    /**
58
     * The storage used to cache any information needed for a specific FrontMatterObject or DataItem.
59
     *
60
     * For example, with a DataItem, which is just an array, the file path to the original file can be stored in this
61
     * array to be accessible in the future to refresh the contents without parsing all of the files again.
62
     *
63
     * $trackedItemsOptions['<relative file path>'] = array
64
     *
65
     * @var array
66
     */
67
    protected $trackedItemsOptions;
68
69
    /**
70
     * The storage used for either FrontMatterObjects or DataItems in the respective static classes.
71
     *
72
     * $trackedItems['<namespace>']['<file name w/o extension>'] = mixed
73
     * $trackedItems['<file name w/o extension>'] = mixed
74
     *
75
     * @var array
76
     */
77
    protected $trackedItems;
78
79
    /**
80
     * Set to true when file tracking is enabled.
81
     *
82
     * @var bool
83
     */
84
    protected $tracking;
85
86 42
    public function __construct()
87
    {
88 42
        parent::__construct();
89
90 42
        $this->folderDefinitionsOptions = array();
91 42
        $this->folderDefinitions = array();
92 42
        $this->trackedItemsFlattened = array();
93 42
        $this->trackedItemsOptions = array();
94 42
        $this->trackedItems = array();
95 42
        $this->tracking = false;
96 42
    }
97
98
    /**
99
     * Whether or not to enable tracking of files.
100
     *
101
     * Setting this to false will disable a lot of the overhead and caching done when a project is being watched
102
     *
103
     * @param bool $enabled
104
     */
105
    public function enableTracking($enabled)
106
    {
107
        $this->tracking = $enabled;
108
    }
109
110
    /**
111
     * Check to see if the file belongs inside of one the folders being tracked by this manager.
112
     *
113
     * @param string $filePath
114
     *
115
     * @return bool True if the file is inside a tracked folder
116
     */
117
    public function isHandled($filePath)
118
    {
119
        foreach ($this->folderDefinitions as $folder)
120
        {
121
            if (substr($filePath, 0, strlen($folder)) === $folder)
122
            {
123
                return true;
124
            }
125
        }
126
127
        return false;
128
    }
129
130
    /**
131
     * Check whether a file is tracked.
132
     *
133
     * @param string $filePath The relative path of the file
134
     *
135
     * @return bool
136
     */
137 1
    public function isTracked($filePath)
138
    {
139 1
        return array_key_exists($filePath, $this->trackedItemsFlattened);
140
    }
141
142
    /**
143
     * @param SplFileInfo|string $filePath
144
     *
145
     * @return mixed|null
146
     */
147
    public function createNewItem($filePath)
148
    {
149
        return $this->handleTrackableItem($filePath);
0 ignored issues
show
Bug introduced by
It seems like $filePath defined by parameter $filePath on line 147 can also be of type string; however, allejo\stakx\Manager\Tra...::handleTrackableItem() does only seem to accept object<Symfony\Component\Finder\SplFileInfo>, maybe add an additional type check?

This check looks at variables that have been passed in as parameters and are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

Loading history...
150
    }
151
152
    /**
153
     * Update the contents of a specified file.
154
     *
155
     * @param SplFileInfo|string $filePath The relative path of the file
156
     *
157
     * @return PageView
158
     */
159
    public function refreshItem($filePath)
160
    {
161
        return $this->handleTrackableItem($filePath);
0 ignored issues
show
Bug introduced by
It seems like $filePath defined by parameter $filePath on line 159 can also be of type string; however, allejo\stakx\Manager\Tra...::handleTrackableItem() does only seem to accept object<Symfony\Component\Finder\SplFileInfo>, maybe add an additional type check?

This check looks at variables that have been passed in as parameters and are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

Loading history...
162
    }
163
164
    /**
165
     * Save data to the tracker with a reference to the file it came from.
166
     *
167
     * @param string      $key       The name of the file
168
     * @param mixed       $data      The data to save the
169
     * @param string      $filePath  The relative file path from the root of the website
170
     * @param string|null $namespace The name of the collection this data belongs to, if any
171
     */
172 41
    protected function addArrayToTracker($key, $data, $filePath, $namespace = null)
173
    {
174 41
        if (is_null($namespace))
175
        {
176 1
            $this->trackedItems[$key] = $data;
177 1
            $this->trackedItemsFlattened[$filePath] = &$this->trackedItems[$key];
178
        }
179
        else
180
        {
181 40
            $this->trackedItems[$namespace][$key] = $data;
182 40
            $this->trackedItemsFlattened[$filePath] = &$this->trackedItems[$namespace][$key];
183
        }
184 41
    }
185
186
    /**
187
     * Add a FrontMatterObject based object to the tracker.
188
     *
189
     * @param TwigDocumentInterface $trackedItem
190
     * @param string $key
191
     * @param string|null $namespace
192
     */
193 41
    protected function addObjectToTracker($trackedItem, $key, $namespace = null)
194
    {
195 41
        if (!($trackedItem instanceof FrontMatterDocument) && !($trackedItem instanceof TwigDocumentInterface))
196
        {
197
            throw new \InvalidArgumentException('Only TwigDocumentInterface objects can be added to the tracker');
198
        }
199
200 41
        $this->addArrayToTracker($key, $trackedItem, $trackedItem->getRelativeFilePath(), $namespace);
201 41
    }
202
203
    /**
204
     * Remove all data related to an array that was saved.
205
     *
206
     * @param string      $key
207
     * @param string      $filePath
208
     * @param string|null $namespace
209
     */
210
    protected function delArrayFromTracker($key, $filePath, $namespace = null)
211
    {
212
        if (is_null($namespace))
213
        {
214
            unset($this->trackedItems[$key]);
215
        }
216
        else
217
        {
218
            unset($this->trackedItems[$namespace][$key]);
219
        }
220
221
        unset($this->trackedItemsFlattened[$filePath]);
222
    }
223
224
    /**
225
     * Remove an entry from the tracked items array.
226
     *
227
     * @param mixed       $trackedItem
228
     * @param string|null $namespace
229
     */
230
    protected function delObjectFromTracker($trackedItem, $namespace = null)
231
    {
232
        $this->delArrayFromTracker(
233
            $trackedItem->getFileName(),
234
            $trackedItem->getRelativeFilePath(),
235
            $namespace
236
        );
237
    }
238
239
    /**
240
     * Save a folder that is tracked by this manager and its respective options.
241
     *
242
     * @param string $folderPath
243
     * @param array  $options
244
     */
245 39
    protected function saveFolderDefinition($folderPath, $options = array())
246
    {
247 39
        $this->folderDefinitions[] = $folderPath;
248 39
        $this->folderDefinitionsOptions[$folderPath] = $options;
249 39
    }
250
251
    /**
252
     * Save any options related to an item needed in order to refresh the content.
253
     *
254
     * @param string $filePath
255
     * @param array  $options
256
     */
257 2
    protected function saveTrackerOptions($filePath, $options = array())
258
    {
259 2
        $this->trackedItemsOptions[$filePath] = $options;
260 2
    }
261
262
    /**
263
     * Parse the specified folder for items to track.
264
     *
265
     * @param string $path
266
     * @param mixed  $options  Special options that will be passed to the static::parseTrackableItem() implementation
267
     * @param array  $includes
268
     * @param array  $excludes
269
     */
270 41
    protected function scanTrackableItems($path, $options = array(), $includes = array(), $excludes = array())
271
    {
272 41
        $fileExplorerFlags = array_key_exists('fileExplorer', $options) ? $options['fileExplorer'] : null;
273 41
        $this->fileExplorer = FileExplorer::create($path, $excludes, $includes, $fileExplorerFlags);
274 41
        $fileExplorer = $this->fileExplorer->getExplorer();
275
276 41
        foreach ($fileExplorer as $file)
277
        {
278 41
            $this->handleTrackableItem($file, $options);
279
        }
280 41
    }
281
282
    /**
283
     * Return an array of JailedDocuments created from the tracked items
284
     *
285
     * @return JailedDocument[]
286
     */
287 21
    protected function getJailedTrackedItems()
288
    {
289 21
        $jailItems = array();
290
291
        /**
292
         * @var string $key
293
         * @var TwigDocumentInterface $item
294
         */
295 21
        foreach ($this->trackedItemsFlattened as &$item)
296
        {
297 21
            if (!Service::getParameter(BuildableCommand::USE_DRAFTS) && $item->isDraft()) { continue; }
298
299 21
            if (empty($item->getNamespace()))
300
            {
301 1
                $jailItems[$item->getName()] = $item->createJail();
302
            }
303
            else
304
            {
305 20
                $jailItems[$item->getNamespace()][$item->getName()] = $item->createJail();
306
            }
307
        }
308
309 21
        return $jailItems;
310
    }
311
312
    /**
313
     * Handle a specific file type, parse it into the appropriate object type, and add it to the tracker.
314
     *
315
     * This function should make use of the appropriate functions:
316
     *
317
     *  - TrackingManager::addObjectToTracker()
318
     *  - TrackingManager::addArrayToTracker()
319
     *  - TrackingManager::saveTrackerOptions()
320
     *
321
     * @param SplFileInfo $filePath
322
     * @param mixed       $options
323
     *
324
     * @return mixed|null
325
     */
326
    abstract protected function handleTrackableItem($filePath, $options = array());
327
}
328