Completed
Push — master ( c2b5cc...89bfcf )
by Vladimir
03:33
created

TrackingManager::handleTrackableItem()

Size

Total Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
nc 1
dl 0
loc 1
ccs 0
cts 0
cp 0
c 0
b 0
f 0
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
        $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...
273
274 41
        $fileExplorerFlags = array_key_exists('fileExplorer', $options) ? $options['fileExplorer'] : null;
275 41
        $this->fileExplorer = FileExplorer::create($path, $excludes, $includes, $fileExplorerFlags);
276 41
        $fileExplorer = $this->fileExplorer->getExplorer();
277
278 41
        foreach ($fileExplorer as $file)
279
        {
280 41
            $this->handleTrackableItem($file, $options);
281
        }
282 41
    }
283
284
    /**
285
     * Return an array of JailedDocuments created from the tracked items
286
     *
287
     * @return JailedDocument[]
288
     */
289 21
    protected function getJailedTrackedItems()
290
    {
291 21
        $jailItems = array();
292
293
        /**
294
         * @var string $key
295
         * @var TwigDocumentInterface $item
296
         */
297 21
        foreach ($this->trackedItemsFlattened as &$item)
298
        {
299 21
            if (!Service::getParameter(BuildableCommand::USE_DRAFTS) && $item->isDraft()) { continue; }
300
301 21
            if (empty($item->getNamespace()))
302
            {
303 1
                $jailItems[$item->getName()] = $item->createJail();
304
            }
305
            else
306
            {
307 21
                $jailItems[$item->getNamespace()][$item->getName()] = $item->createJail();
308
            }
309
        }
310
311 21
        return $jailItems;
312
    }
313
314
    /**
315
     * Handle a specific file type, parse it into the appropriate object type, and add it to the tracker.
316
     *
317
     * This function should make use of the appropriate functions:
318
     *
319
     *  - TrackingManager::addObjectToTracker()
320
     *  - TrackingManager::addArrayToTracker()
321
     *  - TrackingManager::saveTrackerOptions()
322
     *
323
     * @param SplFileInfo $filePath
324
     * @param mixed       $options
325
     *
326
     * @return mixed|null
327
     */
328
    abstract protected function handleTrackableItem($filePath, $options = array());
329
}
330