Passed
Push — master ( 48d02b...1e0cee )
by Austin
03:14
created

SecurityTxtHelper::hasWriter()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 3
rs 10
c 0
b 0
f 0
cc 1
eloc 1
nc 1
nop 0
1
<?php
2
/**
3
 * src/SecurityTxtHelper.php.
4
 *
5
 * @author      Austin Heap <[email protected]>
6
 * @version     v0.3.2
7
 */
8
declare(strict_types = 1);
9
10
namespace AustinHeap\Security\Txt;
11
12
use Exception;
13
use Log;
14
15
/**
16
 * SecurityTxtHelper.
17
 *
18
 * @link        https://github.com/austinheap/laravel-security-txt
19
 * @link        https://packagist.org/packages/austinheap/laravel-security-txt
20
 * @link        https://austinheap.github.io/laravel-security-txt/classes/AustinHeap.Security.Txt.SecurityTxtHelper.html
21
 */
22
class SecurityTxtHelper
23
{
24
    /**
25
     * Internal version number.
26
     *
27
     * @var string
28
     */
29
    const VERSION = '0.3.0';
30
31
    /**
32
     * Enable the package.
33
     *
34
     * @var bool
35
     */
36
    protected $enabled = null;
37
38
    /**
39
     * Internal SecurityTxt object.
40
     *
41
     * @var \AustinHeap\Security\Txt\Writer
42
     */
43
    protected $writer = null;
44
45
    /**
46
     * Internal array of log entries.
47
     *
48
     * @var array
49
     */
50
    protected $logEntries = [];
51
52
    /**
53
     * Enable built-in cache.
54
     *
55
     * @var bool
56
     */
57
    protected $cache = false;
58
59
    /**
60
     * Minutes to cache output.
61
     *
62
     * @var int
63
     */
64
    protected $cacheTime = null;
65
66
    /**
67
     * Cache key to use.
68
     *
69
     * @var string
70
     */
71
    protected $cacheKey = 'cache:AustinHeap\Security\Txt\SecurityTxt';
72
73
    /**
74
     * Create a new SecurityTxtHelper instance.
75
     *
76
     * @return SecurityTxtHelper
77
     */
78
    public function __construct()
79
    {
80
        $this->buildWriter();
81
82
        return $this;
83
    }
84
85
    /**
86
     * Returns the default config key => php-security-txt mappings.
87
     *
88
     * @return array
89
     */
90
    public static function buildWriterDefaultKeys()
91
    {
92
        return [
93
            'security-txt.enabled'         => ['validator' => 'is_bool', 'setter' => 'setEnabled', 'self' => true],
94
            'security-txt.debug'           => ['validator' => 'is_bool', 'setter' => 'setDebug'],
95
            'security-txt.cache'           => ['validator' => 'is_bool', 'setter' => 'setCache', 'self' => true],
96
            'security-txt.cache-time'      => ['validator' => 'is_numeric', 'setter' => 'setCacheTime', 'self' => true],
97
            'security-txt.cache-key'       => ['validator' => 'is_string', 'setter' => 'setCacheKey', 'self' => true],
98
            'security-txt.comments'        => ['validator' => 'is_bool', 'setter' => 'setComments'],
99
            'security-txt.contacts'        => ['validator' => 'is_array', 'setter' => 'addContacts'],
100
            'security-txt.encryption'      => ['validator' => 'is_string', 'setter' => 'setEncryption'],
101
            'security-txt.disclosure'      => ['validator' => 'is_string', 'setter' => 'setDisclosure'],
102
            'security-txt.acknowledgement' => ['validator' => 'is_string', 'setter' => 'setAcknowledgement'],
103
        ];
104
    }
105
106
    /**
107
     * Builds the internal SecurityTxt Writer.
108
     *
109
     * @param array $keys
110
     *
111
     * @return SecurityTxtHelper
112
     */
113
    public function buildWriter(array $keys = null): self
114
    {
115
        $this->writer = new Writer();
116
117
        $keys = is_array($keys) ? $keys : self::buildWriterDefaultKeys();
118
119
        foreach ($keys as $key => $mapping) {
120
            if (is_null(config($key, null))) {
121
                $this->addLogEntry('"' . __CLASS__ . '" cannot process null value for key "' . $key . '".', 'debug');
122
                continue;
123
            }
124
125 View Code Duplication
            if (!function_exists($mapping['validator'])) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
126
                $this->addLogEntry('"' . __CLASS__ . '" cannot find "validator" function named "' . $mapping['validator'] . '".',
127
                                   'warning');
128
                continue;
129
            }
130
131 View Code Duplication
            if (!$mapping['validator'](config($key))) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
132
                $this->addLogEntry('"' . __CLASS__ . '" failed the "validator" function named "' . $mapping['validator'] . '".',
133
                                   'warning');
134
                continue;
135
            }
136
137
            if (array_key_exists('self', $mapping) &&
138
                is_bool($mapping['self']) &&
139
                $mapping['self'] === true) {
140 View Code Duplication
                if (!method_exists($this, $mapping['setter'])) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
141
                    $this->addLogEntry('"' . __CLASS__ . '" cannot find mapping "setter" method on object "' . get_class($this) . '" named "' . $mapping['setter'] . '".',
142
                                       'error');
143
                    continue;
144
                }
145
146
                $this->{$mapping['setter']}(config($key));
147
            } else {
148 View Code Duplication
                if (!method_exists($this->writer, $mapping['setter'])) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
149
                    $this->addLogEntry('"' . __CLASS__ . '" cannot find mapping "setter" method on object "' . get_class($this->writer) . '" named "' . $mapping['setter'] . '".',
150
                                       'error');
151
                    continue;
152
                }
153
154
                $this->writer->{$mapping['setter']}(config($key));
155
            }
156
        }
157
158
        return $this;
159
    }
160
161
    /**
162
     * Add log entry.
163
     *
164
     * @param  string $text
165
     * @param  string $level
166
     *
167
     * @return SecurityTxtHelper
168
     */
169
    public function addLogEntry(string $text, string $level = 'debug'): self
170
    {
171
        Log::$level($text);
172
173
        $this->logEntries[] = ['text' => $text, 'level' => $level];
174
175
        return $this;
176
    }
177
178
    /**
179
     * Add log entries.
180
     *
181
     * @return array
182
     */
183
    public function getLogEntries(): array
184
    {
185
        return $this->logEntries;
186
    }
187
188
    /**
189
     * Clears log entries.
190
     *
191
     * @return SecurityTxtHelper
192
     */
193
    public function clearLogEntries(): self
194
    {
195
        $this->logEntries = [];
196
197
        return $this;
198
    }
199
200
    /**
201
     * Fetches the raw text of the document.
202
     *
203
     * @return SecurityTxtHelper
204
     */
205
    public function fetch(): string
206
    {
207
        if ($this->cache) {
208
            $text = cache($this->cacheKey, null);
209
210
            if (!is_null($text)) {
211
                return $text;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $text could return the type Illuminate\Cache\CacheMa...tracts\Cache\Repository which is incompatible with the type-hinted return string. Consider adding an additional type-check to rule them out.
Loading history...
212
            }
213
        }
214
215
        $text = $this->writer
216
            ->execute()
217
            ->getText();
218
219
        if ($this->writer->getDebug()) {
220
            $text .= '# Cache is ' . ($this->cache ? 'enabled with key "' . $this->cacheKey . '"' : 'disabled') . '.' . PHP_EOL .
221
                     '#' . PHP_EOL;
222
        }
223
224
        if ($this->cache) {
225
            cache([$this->cacheKey => $text], now()->addMinutes($this->cacheTime));
226
        }
227
228
        return empty($text) ? '' : $text;
0 ignored issues
show
Bug Best Practice introduced by
The expression return empty($text) ? '' : $text returns the type string which is incompatible with the documented return type AustinHeap\Security\Txt\SecurityTxtHelper.
Loading history...
229
    }
230
231
    /**
232
     * Enable the enabled flag.
233
     *
234
     * @return SecurityTxtHelper
235
     */
236
    public function enable(): self
237
    {
238
        return $this->setEnabled(true);
239
    }
240
241
    /**
242
     * Disable the enabled flag.
243
     *
244
     * @return SecurityTxtHelper
245
     */
246
    public function disable(): self
247
    {
248
        return $this->setEnabled(false);
249
    }
250
251
    /**
252
     * Set the enabled flag.
253
     *
254
     * @param  bool $enabled
255
     *
256
     * @return SecurityTxtHelper
257
     */
258
    public function setEnabled(bool $enabled): self
259
    {
260
        $this->enabled = $enabled;
261
262
        return $this;
263
    }
264
265
    /**
266
     * Get the enabled flag.
267
     *
268
     * @return bool
269
     */
270
    public function getEnabled(): bool
271
    {
272
        return is_null($this->enabled) ? false : $this->enabled;
273
    }
274
275
    /**
276
     * Enable the cache flag.
277
     *
278
     * @return SecurityTxtHelper
279
     */
280
    public function enableCache(): self
281
    {
282
        return $this->setCache(true);
283
    }
284
285
    /**
286
     * Disable the cache flag.
287
     *
288
     * @return SecurityTxtHelper
289
     */
290
    public function disableCache(): self
291
    {
292
        return $this->setCache(false);
293
    }
294
295
    /**
296
     * Set the cache flag.
297
     *
298
     * @param  bool $cache
299
     *
300
     * @return SecurityTxtHelper
301
     */
302
    public function setCache(bool $cache): self
303
    {
304
        $this->cache = $cache;
305
306
        return $this;
307
    }
308
309
    /**
310
     * Get the cache flag.
311
     *
312
     * @return bool
313
     */
314
    public function getCache(): bool
315
    {
316
        return $this->cache;
317
    }
318
319
    /**
320
     * Clear the cache.
321
     *
322
     * @return SecurityTxtHelper
323
     */
324
    public function clearCache(): self
325
    {
326
        cache()->delete($this->cacheKey);
327
328
        return $this;
329
    }
330
331
    /**
332
     * Set the cache key.
333
     *
334
     * @param  string $cacheKey
335
     *
336
     * @return SecurityTxtHelper
337
     */
338
    public function setCacheKey(string $cacheKey): self
339
    {
340
        $this->cacheKey = $cacheKey;
341
342
        return $this;
343
    }
344
345
    /**
346
     * Get the cache key.
347
     *
348
     * @return string
349
     */
350
    public function getCacheKey(): string
351
    {
352
        return $this->cacheKey;
353
    }
354
355
    /**
356
     * Set the cache time.
357
     *
358
     * @param  int $cacheTime
359
     *
360
     * @return SecurityTxtHelper
361
     */
362
    public function setCacheTime(int $cacheTime): self
363
    {
364
        $this->cacheTime = $cacheTime;
365
366
        return $this;
367
    }
368
369
    /**
370
     * Get the cache time.
371
     *
372
     * @return int
373
     */
374
    public function getCacheTime(): int
375
    {
376
        return $this->cacheTime;
377
    }
378
379
    /**
380
     * Determines if a SecurityTxt Writer is set.
381
     *
382
     * @return bool
383
     */
384
    public function hasWriter(): bool
385
    {
386
        return !is_null($this->writer);
387
    }
388
389
    /**
390
     * Gets the internal SecurityTxt Writer.
391
     *
392
     * @return Writer
393
     */
394
    public function getWriter(): Writer
395
    {
396
        if (!$this->hasWriter()) {
397
            throw new Exception('Writer not set.');
398
        }
399
400
        return $this->writer;
401
    }
402
403
    /**
404
     * Sets the internal SecurityTxt Writer.
405
     *
406
     * @param Writer|null $writer
407
     *
408
     * @return SecurityTxtHelper
409
     */
410
    public function setWriter($writer): self
411
    {
412
        $this->writer = $writer;
413
414
        return $this;
415
    }
416
}
417