Completed
Pull Request — master (#45)
by Vladimir
02:30
created

TrackingManager::addObjectToTracker()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 9
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 5
CRAP Score 2.0185

Importance

Changes 0
Metric Value
cc 2
eloc 4
c 0
b 0
f 0
nc 2
nop 3
dl 0
loc 9
rs 9.6666
ccs 5
cts 6
cp 0.8333
crap 2.0185
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\FrontMatter\Document;
11
use allejo\stakx\System\FileExplorer;
12
use Symfony\Component\Finder\SplFileInfo;
13
14
/**
15
 * Class TrackingManager.
16
 */
17
abstract class TrackingManager extends BaseManager
0 ignored issues
show
Coding Style introduced by
TrackingManager does not seem to conform to the naming convention (^Abstract|Factory$).

This check examines a number of code elements and verifies that they conform to the given naming conventions.

You can set conventions for local variables, abstract classes, utility classes, constant, properties, methods, parameters, interfaces, classes, exceptions and special methods.

Loading history...
18
{
19
    /**
20
     * @var FileExplorer
21
     */
22
    protected $fileExplorer;
23
24
    /**
25
     * An array corresponding with $folderDefinitions to store metadata regarding a specificc folder.
26
     *
27
     * $folderDefinitionsOption['<folder path>'] = array()
28
     *
29
     * @var string[]
30
     */
31
    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...
32
33
    /**
34
     * An array of folders which tracked items are stored in.
35
     *
36
     * $folderDefinitions[] = '<folder path>'
37
     *
38
     * @var string[]
39
     */
40
    protected $folderDefinitions;
41
42
    /**
43
     * The storage which contains the same information as $trackedItems but organized by relative file path instead of a
44
     * namespace or file name without extension.
45
     *
46
     * $trackedItemsOptions['<relative file path>'] = mixed
47
     *
48
     * @var array
49
     */
50
    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...
51
52
    /**
53
     * The storage used to cache any information needed for a specific FrontMatterObject or DataItem.
54
     *
55
     * For example, with a DataItem, which is just an array, the file path to the original file can be stored in this
56
     * array to be accessible in the future to refresh the contents without parsing all of the files again.
57
     *
58
     * $trackedItemsOptions['<relative file path>'] = array
59
     *
60
     * @var array
61
     */
62
    protected $trackedItemsOptions;
63
64
    /**
65
     * The storage used for either FrontMatterObjects or DataItems in the respective static classes.
66
     *
67
     * $trackedItems['<namespace>']['<file name w/o extension>'] = mixed
68
     * $trackedItems['<file name w/o extension>'] = mixed
69
     *
70
     * @var array
71
     */
72
    protected $trackedItems;
73
74
    /**
75
     * Set to true when file tracking is enabled.
76
     *
77
     * @var bool
78
     */
79
    protected $tracking;
80
81 39
    public function __construct()
82
    {
83 39
        parent::__construct();
84
85 39
        $this->folderDefinitionsOptions = array();
86 39
        $this->folderDefinitions = array();
87 39
        $this->trackedItemsFlattened = array();
88 39
        $this->trackedItemsOptions = array();
89 39
        $this->trackedItems = array();
90 39
        $this->tracking = false;
91 39
    }
92
93
    /**
94
     * Whether or not to enable tracking of files.
95
     *
96
     * Setting this to false will disable a lot of the overhead and caching done when a project is being watched
97
     *
98
     * @param bool $enabled
99
     */
100
    public function enableTracking($enabled)
101
    {
102
        $this->tracking = $enabled;
103
    }
104
105
    /**
106
     * Check to see if the file belongs inside of one the folders being tracked by this manager.
107
     *
108
     * @param string $filePath
109
     *
110
     * @return bool True if the file is inside a tracked folder
111
     */
112
    public function isHandled($filePath)
113
    {
114
        foreach ($this->folderDefinitions as $folder)
115
        {
116
            if (substr($filePath, 0, strlen($folder)) === $folder)
117
            {
118
                return true;
119
            }
120
        }
121
122
        return false;
123
    }
124
125
    /**
126
     * Check whether a file is tracked.
127
     *
128
     * @param string $filePath The relative path of the file
129
     *
130
     * @return bool
131
     */
132 1
    public function isTracked($filePath)
133
    {
134 1
        return array_key_exists($filePath, $this->trackedItemsFlattened);
135
    }
136
137
    /**
138
     * @param SplFileInfo|string $filePath
139
     *
140
     * @return mixed|null
141
     */
142
    public function createNewItem($filePath)
143
    {
144
        return $this->handleTrackableItem($filePath);
0 ignored issues
show
Bug introduced by
It seems like $filePath defined by parameter $filePath on line 142 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...
145
    }
146
147
    /**
148
     * Update the contents of a specified file.
149
     *
150
     * @param SplFileInfo|string $filePath The relative path of the file
151
     *
152
     * @return mixed|null
153
     */
154
    public function refreshItem($filePath)
155
    {
156
        return $this->handleTrackableItem(
157
            $filePath,
0 ignored issues
show
Bug introduced by
It seems like $filePath defined by parameter $filePath on line 154 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...
158
            $this->trackedItemsOptions[$filePath]
159
        );
160
    }
161
162
    /**
163
     * Save data to the tracker with a reference to the file it came from.
164
     *
165
     * @param string      $key       The name of the file
166
     * @param mixed       $data      The data to save the
167
     * @param string      $filePath  The relative file path from the root of the website
168
     * @param string|null $namespace The name of the collection this data belongs to, if any
169
     */
170 38
    protected function addArrayToTracker($key, $data, $filePath, $namespace = null)
171
    {
172 38
        if (is_null($namespace))
173 38
        {
174
            $this->trackedItems[$key] = $data;
175
            $this->trackedItemsFlattened[$filePath] = &$this->trackedItems[$key];
176
        }
177
        else
178
        {
179 38
            $this->trackedItems[$namespace][$key] = $data;
180 38
            $this->trackedItemsFlattened[$filePath] = &$this->trackedItems[$namespace][$key];
181
        }
182 38
    }
183
184
    /**
185
     * Add a FrontMatterObject based object to the tracker.
186
     *
187
     * @param Document    $trackedItem
188
     * @param string      $key
189
     * @param string|null $namespace
190
     */
191 38
    protected function addObjectToTracker($trackedItem, $key, $namespace = null)
192
    {
193 38
        if (!($trackedItem instanceof Document))
194 38
        {
195
            throw new \InvalidArgumentException('Only objects can be added to the tracker');
196
        }
197
198 38
        $this->addArrayToTracker($key, $trackedItem, $trackedItem->getRelativeFilePath(), $namespace);
199 38
    }
200
201
    /**
202
     * Remove all data related to an array that was saved.
203
     *
204
     * @param string      $key
205
     * @param string      $filePath
206
     * @param string|null $namespace
207
     */
208
    protected function delArrayFromTracker($key, $filePath, $namespace = null)
209
    {
210
        if (is_null($namespace))
211
        {
212
            unset($this->trackedItems[$key]);
213
        }
214
        else
215
        {
216
            unset($this->trackedItems[$namespace][$key]);
217
        }
218
219
        unset($this->trackedItemsFlattened[$filePath]);
220
    }
221
222
    /**
223
     * Remove an entry from the tracked items array.
224
     *
225
     * @param mixed       $trackedItem
226
     * @param string|null $namespace
227
     */
228
    protected function delObjectFromTracker($trackedItem, $namespace = null)
229
    {
230
        $this->delArrayFromTracker(
231
            $trackedItem->getFileName(),
232
            $trackedItem->getRelativeFilePath(),
233
            $namespace
234
        );
235
    }
236
237
    /**
238
     * Save a folder that is tracked by this manager and its respective options.
239
     *
240
     * @param string $folderPath
241
     * @param array  $options
242
     */
243 36
    protected function saveFolderDefinition($folderPath, $options = array())
244
    {
245 36
        $this->folderDefinitions[] = $folderPath;
246 36
        $this->folderDefinitionsOptions[$folderPath] = $options;
247 36
    }
248
249
    /**
250
     * Save any options related to an item needed in order to refresh the content.
251
     *
252
     * @param string $filePath
253
     * @param array  $options
254
     */
255
    protected function saveTrackerOptions($filePath, $options = array())
256
    {
257
        $this->trackedItemsOptions[$filePath] = $options;
258
    }
259
260
    /**
261
     * Parse the specified folder for items to track.
262
     *
263
     * @param string $path
264
     * @param mixed  $options  Special options that will be passed to the static::parseTrackableItem() implementation
265
     * @param array  $includes
266
     * @param array  $excludes
267
     */
268 38
    protected function scanTrackableItems($path, $options = array(), $includes = array(), $excludes = array())
269
    {
270 38
        $fileExplorerFlags = array_key_exists('fileExplorer', $options) ? $options['fileExplorer'] : null;
271 38
        $this->fileExplorer = FileExplorer::create($path, $excludes, $includes, $fileExplorerFlags);
272 38
        $fileExplorer = $this->fileExplorer->getExplorer();
273
274 38
        foreach ($fileExplorer as $file)
275
        {
276 38
            $this->handleTrackableItem($file, $options);
277 38
        }
278 38
    }
279
280
    /**
281
     * Handle a specific file type, parse it into the appropriate object type, and add it to the tracker.
282
     *
283
     * This function should make use of the appropriate functions:
284
     *
285
     *  - TrackingManager::addObjectToTracker()
286
     *  - TrackingManager::addArrayToTracker()
287
     *  - TrackingManager::saveTrackerOptions()
288
     *
289
     * @param SplFileInfo $filePath
290
     * @param mixed       $options
291
     *
292
     * @return mixed|null
293
     */
294
    abstract protected function handleTrackableItem($filePath, $options = array());
295
}
296