Completed
Push — master ( 2319eb...3c4d84 )
by Vladimir
02:22
created

TrackingManager::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 10
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 8
CRAP Score 1

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 10
rs 9.4285
ccs 8
cts 8
cp 1
cc 1
eloc 7
nc 1
nop 0
crap 1

1 Method

Rating   Name   Duplication   Size   Complexity  
A TrackingManager::createNewItem() 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\CollectableItem;
12
use allejo\stakx\Document\JailedDocument;
13
use allejo\stakx\Document\ReadableDocument;
14
use allejo\stakx\Document\TemplateReadyDocument;
15
use allejo\stakx\Filesystem\File;
16
use allejo\stakx\Filesystem\FilesystemLoader as fs;
17
use allejo\stakx\Service;
18
use allejo\stakx\Filesystem\FileExplorer;
19
20
/**
21
 * Class TrackingManager.
22
 */
23
abstract class TrackingManager extends BaseManager
24
{
25
    /**
26
     * @var FileExplorer
27
     */
28
    protected $fileExplorer = null;
29
30
    /**
31
     * An array corresponding with $folderDefinitions to store metadata regarding a specificc folder.
32
     *
33
     * $folderDefinitionsOption['<folder path>'] = array()
34
     *
35
     * @var string[]
36
     */
37
    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...
38
39
    /**
40
     * An array of folders which tracked items are stored in.
41
     *
42
     * $folderDefinitions[] = '<folder path>'
43
     *
44
     * @var string[]
45
     */
46
    protected $folderDefinitions = [];
47
48
    /**
49
     * The storage which contains the same information as $trackedItems but organized by relative file path instead of a
50
     * namespace or file name without extension.
51
     *
52
     * $trackedItemsOptions['<relative file path>'] = mixed
53
     *
54
     * @var array
55
     */
56
    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...
57
58
    /**
59
     * The storage used to cache any information needed for a specific FrontMatterObject or DataItem.
60
     *
61
     * For example, with a DataItem, which is just an array, the file path to the original file can be stored in this
62
     * array to be accessible in the future to refresh the contents without parsing all of the files again.
63
     *
64
     * $trackedItemsOptions['<relative file path>'] = array
65
     *
66
     * @var array
67
     */
68
    protected $trackedItemsOptions = [];
69
70
    /**
71
     * The storage used for ReadableDocument in the respective static classes.
72
     *
73
     * $trackedItems['<namespace>']['<file name w/o extension>'] = mixed
74
     * $trackedItems['<file name w/o extension>'] = mixed
75
     *
76
     * @var array
77
     */
78
    protected $trackedItems = [];
79
80
    /**
81
     * @param File|string $filePath
82
     *
83
     * @return mixed|null
84
     */
85
    public function createNewItem($filePath)
86
    {
87
        return $this->handleTrackableItem($filePath);
0 ignored issues
show
Bug introduced by
It seems like $filePath defined by parameter $filePath on line 85 can also be of type string; however, allejo\stakx\Manager\Tra...::handleTrackableItem() does only seem to accept object<allejo\stakx\Filesystem\File>, 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...
88
    }
89
90
    /**
91
     * Check whether a file is already being tracked.
92
     *
93
     * @param string $filePath The relative path of the file
94
     *
95
     * @return bool
96
     */
97 1
    public function isTracked($filePath)
98
    {
99 1
        return array_key_exists((string)$filePath, $this->trackedItemsFlattened);
100
    }
101
102
    /**
103
     * Check to see if a given file path matches this tracker's definition and would be tracked.
104
     *
105
     * This function should be used to check whether or not to add a file to this tracker after the initial scan has
106
     * already happened.
107
     *
108
     * @param string $filePath
109
     *
110
     * @return bool True if the file is inside a tracked folder
111
     */
112
    public function shouldBeTracked($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
     * Update the contents of a specified file.
127
     *
128
     * @param File|string $filePath The relative path of the file
129
     *
130
     * @return mixed|null
131
     */
132
    public function refreshItem($filePath)
133
    {
134
        return $this->handleTrackableItem($filePath);
0 ignored issues
show
Bug introduced by
It seems like $filePath defined by parameter $filePath on line 132 can also be of type string; however, allejo\stakx\Manager\Tra...::handleTrackableItem() does only seem to accept object<allejo\stakx\Filesystem\File>, 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...
135
    }
136
137
    ///
138
    // Internal object handling
139
    ///
140
141
    protected function addFileToTracker(File &$file)
142
    {
143
        $this->trackedItemsFlattened[$file->getRelativeFilePath()] = &$file;
144
    }
145
146
    protected function delFileFromTracker(File &$file)
147
    {
148
        unset($this->trackedItemsFlattened[$file->getRelativeFilePath()]);
149
    }
150
151
    /**
152
     * Add a ReadableDocument to the tracker.
153
     *
154
     * @param ReadableDocument $trackedItem
155
     * @param string|null       $namespace
156
     */
157 40
    protected function addObjectToTracker(ReadableDocument &$trackedItem, $namespace = null)
158
    {
159 40
        if ($namespace == null)
0 ignored issues
show
Bug introduced by
It seems like you are loosely comparing $namespace of type string|null against null; this is ambiguous if the string can be empty. Consider using a strict comparison === instead.
Loading history...
160
        {
161 1
            $this->trackedItems[$trackedItem->getIndexName()] = &$trackedItem;
162
        }
163
        else
164
        {
165 39
            $this->trackedItems[$namespace][$trackedItem->getIndexName()] = &$trackedItem;
166
        }
167
168 40
        $this->trackedItemsFlattened[$trackedItem->getIndexName()] = &$trackedItem;
169 40
    }
170
171
    /**
172
     * Remove an entry from the tracked items array.
173
     *
174
     * @param ReadableDocument $trackedItem
175
     * @param string|null       $namespace
176
     */
177
    protected function delObjectFromTracker(ReadableDocument &$trackedItem, $namespace = null)
178
    {
179
        if ($namespace == null)
0 ignored issues
show
Bug introduced by
It seems like you are loosely comparing $namespace of type string|null against null; this is ambiguous if the string can be empty. Consider using a strict comparison === instead.
Loading history...
180
        {
181
            unset($this->trackedItems[$trackedItem->getIndexName()]);
182
        }
183
        else
184
        {
185
            unset($this->trackedItems[$namespace][$trackedItem->getIndexName()]);
186
        }
187
188
        unset($this->trackedItemsFlattened[$trackedItem->getIndexName()]);
189
    }
190
191
    ///
192
    // Extra options stored for future use
193
    ///
194
195
    /**
196
     * Save a folder that is tracked by this manager and its respective options.
197
     *
198
     * @param string $folderPath
199
     * @param array  $options
200
     */
201 38
    protected function saveFolderDefinition($folderPath, array $options = array())
202
    {
203 38
        $this->folderDefinitions[] = $folderPath;
204 38
        $this->folderDefinitionsOptions[(string)$folderPath] = $options;
205 38
    }
206
207
    /**
208
     * Save any options related to an item needed in order to refresh the content.
209
     *
210
     * @param string $filePath
211
     * @param array  $options
212
     */
213 2
    protected function saveTrackerOptions($filePath, array $options = array())
214
    {
215 2
        $this->trackedItemsOptions[$filePath] = $options;
216 2
    }
217
218
    /**
219
     * Delete any options that were saved corresponding to an item.
220
     *
221
     * @param string $filePath
222
     */
223
    protected function forgetTrackerOptions($filePath)
224
    {
225
        unset($this->trackedItemsOptions[$filePath]);
226
    }
227
228
    ///
229
    // Handling of trackable items
230
    ///
231
232
    /**
233
     * Parse the specified folder for items to track.
234
     *
235
     * @param string $path
236
     * @param array  $options  Special options that will be passed to the static::parseTrackableItem() implementation
237
     * @param array  $includes
238
     * @param array  $excludes
239
     */
240 40
    protected function scanTrackableItems($path, array $options = array(), array $includes = array(), array $excludes = array())
241
    {
242 40
        $this->folderDefinitions[] = fs::getRelativePath($path);
243
244 40
        $excludes = empty($excludes) ? self::$documentIgnoreList : $excludes;
0 ignored issues
show
Coding Style introduced by
Consider using a different name than the parameter $excludes. This often makes code more readable.
Loading history...
245
246 40
        $fileExplorerFlags = array_key_exists('fileExplorer', $options) ? $options['fileExplorer'] : null;
247 40
        $this->fileExplorer = FileExplorer::create($path, $excludes, $includes, $fileExplorerFlags);
248 40
        $fileExplorer = $this->fileExplorer->getExplorer();
249
250 40
        foreach ($fileExplorer as $file)
251
        {
252 40
            $this->handleTrackableItem($file, $options);
253
        }
254 40
    }
255
256
    /**
257
     * Handle a specific file type, parse it into the appropriate object type, and add it to the tracker.
258
     *
259
     * This function should make use of the appropriate functions:
260
     *
261
     *  - TrackingManager::addObjectToTracker()
262
     *  - TrackingManager::addFileToTracker()
263
     *  - TrackingManager::saveTrackerOptions()
264
     *
265
     * @param File  $filePath
266
     * @param array $options
267
     *
268
     * @return mixed|null
269
     */
270
    abstract protected function handleTrackableItem(File $filePath, array $options = array());
271
272
    ///
273
    // Utility functions
274
    ///
275
276
    /**
277
     * Return an array of JailedDocuments created from the tracked items
278
     *
279
     * @param array    $elements
280
     * @param \Closure $name
0 ignored issues
show
Documentation introduced by
Should the type for parameter $name not be null|\Closure?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
281
     *
282
     * @return JailedDocument[]|JailedDocument[][]
283
     */
284 21
    protected static function getJailedTrackedItems(array &$elements, \Closure $name = null)
285
    {
286 21
        $jailItems = array();
287
288
        /**
289
         * @var string                           $key
290
         * @var CollectableItem|ReadableDocument $item
291
         */
292 21
        foreach ($elements as &$item)
293
        {
294 21
            if ($item instanceof TemplateReadyDocument)
295
            {
296 21
                if (!Service::getParameter(BuildableCommand::USE_DRAFTS) && $item->isDraft())
297
                {
298 1
                    continue;
299
                }
300
            }
301
302 21
            $keyName = ($name === null) ? $item->getRelativeFilePath() : $name($item);
303
304 21
            if (empty($item->getNamespace()))
305
            {
306 1
                $jailItems[$keyName] = $item->createJail();
307
            }
308
            else
309
            {
310 21
                $jailItems[$item->getNamespace()][$keyName] = $item->createJail();
311
            }
312
        }
313
314 21
        return $jailItems;
315
    }
316
}
317