MaxSize   A
last analyzed

Complexity

Total Complexity 12

Size/Duplication

Total Lines 113
Duplicated Lines 0 %

Test Coverage

Coverage 100%

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 20
dl 0
loc 113
ccs 24
cts 24
cp 1
rs 10
c 1
b 0
f 0
wmc 12

7 Methods

Rating   Name   Duplication   Size   Complexity  
A errorMessage() 0 3 2
A errorDetails() 0 3 1
A toMegaBytes() 0 3 1
A isValid() 0 3 1
A setUp() 0 3 1
A toBytes() 0 10 2
A isTooBig() 0 12 4
1
<?php
2
3
/**
4
 * This file is part of CaptainHook
5
 *
6
 * (c) Sebastian Feldmann <[email protected]>
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
12
namespace CaptainHook\App\Hook\File\Action;
13
14
use CaptainHook\App\Config;
15
use RuntimeException;
16
use SebastianFeldmann\Git\Repository;
17
18
/**
19
 * MaxSize
20
 *
21
 * Check all staged files for file size
22
 *
23
 * {
24
 *     "action": "\\CaptainHook\\App\\Hook\\File\\Action\\MaxSize",
25
 *     "options": {
26
 *         "size" : "5M"
27
 *     }
28
 * }
29
 *
30
 * @package CaptainHook
31
 * @author  Sebastian Feldmann <[email protected]>
32
 * @link    https://github.com/captainhook-git/captainhook
33
 * @since   Class available since Release 5.4.3
34
 */
35
class MaxSize extends Check
36
{
37
    /**
38
     * @var int
39
     */
40
    private int $maxBytes;
41
42
    /**
43
     * File sizes for all checked files
44
     *
45
     * @var array<string, int>
46
     */
47
    private array $fileSizes = [];
48
49 3
    protected function setUp(Config\Options $options): void
50
    {
51 3
        $this->maxBytes = $this->toBytes($options->get('maxSize', ''));
52
    }
53
54
    /**
55
     * Make sure the given file is not too big
56
     *
57
     * @param  \SebastianFeldmann\Git\Repository $repository
58
     * @param  string                            $file
59
     * @return bool
60
     */
61 2
    protected function isValid(Repository $repository, string $file): bool
62
    {
63 2
        return !$this->isTooBig($file);
64
    }
65
66
    /**
67
     * Append the actual file size
68
     *
69
     * @param string $file
70
     * @return string
71
     */
72 1
    protected function errorDetails(string $file): string
73
    {
74 1
        return ' <comment>(' . $this->toMegaBytes($this->fileSizes[$file]) . ' MB)</comment>';
75
    }
76
77
    /**
78
     * Custom error message
79
     *
80
     * @param  int $filesFailed
81
     * @return string
82
     */
83 1
    protected function errorMessage(int $filesFailed): string
84
    {
85 1
        return  $filesFailed . ' file' . ($filesFailed > 1 ? ' s are' : ' is') . ' too big';
86
    }
87
88
    /**
89
     * Compare a file to configured max file size
90
     *
91
     * @param  string $file
92
     * @return bool
93
     */
94 2
    private function isTooBig(string $file): bool
95
    {
96 2
        if (!file_exists($file) || is_dir($file)) {
97 1
            return false;
98
        }
99
100 2
        $this->fileSizes[$file] = (int) filesize($file);
101
102 2
        if ($this->fileSizes[$file] > $this->maxBytes) {
103 1
            return true;
104
        }
105 1
        return false;
106
    }
107
108
    /**
109
     * Return given size in bytes
110
     * Allowed units:
111
     *   B => byte
112
     *   K => kilobyte
113
     *   M => megabyte
114
     *   G => gigabyte
115
     *   T => terra byte
116
     *   P => peta byte
117
     *
118
     * e.g.
119
     * 1K => 1024
120
     * 2K => 2048
121
     * ...
122
     *
123
     * @param  string $value
124
     * @throws \RuntimeException
125
     * @return int
126
     */
127 10
    public function toBytes(string $value): int
128
    {
129 10
        if (!preg_match('#^[0-9]*[BKMGTP]$#i', $value)) {
130 2
            throw new RuntimeException('Invalid size value');
131
        }
132 8
        $units  = ['B' => 0, 'K' => 1, 'M' => 2, 'G' => 3, 'T' => 4, 'P' => 5];
133 8
        $unit   = strtoupper(substr($value, -1));
134 8
        $number = intval(substr($value, 0, -1));
135
136 8
        return $number * pow(1024, $units[$unit]);
137
    }
138
139
    /**
140
     * Display bytes in a readable format
141
     *
142
     * @param  int $bytes
143
     * @return float
144
     */
145 1
    private function toMegaBytes(int $bytes): float
146
    {
147 1
        return round($bytes / 1024 / 1024, 3);
148
    }
149
}
150