AbstractUnkeyedHashFunction::hashFile()   A
last analyzed

Complexity

Conditions 6
Paths 6

Size

Total Lines 31
Code Lines 18

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 19
CRAP Score 6

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 18
c 1
b 0
f 0
dl 0
loc 31
ccs 19
cts 19
cp 1
rs 9.0444
cc 6
nc 6
nop 1
crap 6
1
<?php
2
3
/**
4
 * Abstraction for unkeyed hash objects like checksums and plain cryptographic hash functions.
5
 */
6
7
namespace CryptoManana\Core\Abstractions\MessageDigestion;
8
9
use CryptoManana\Core\Abstractions\MessageDigestion\AbstractHashAlgorithm as HashAlgorithm;
10
use CryptoManana\Core\Interfaces\MessageDigestion\ObjectHashingInterface as ObjectHashing;
11
use CryptoManana\Core\Interfaces\MessageDigestion\FileHashingInterface as FileHashing;
12
use CryptoManana\Core\Interfaces\MessageDigestion\RepetitiveHashingInterface as RecursiveHashing;
13
use CryptoManana\Core\Traits\MessageDigestion\ObjectHashingTrait as HashObjects;
14
use CryptoManana\Core\Traits\MessageDigestion\FileHashingTrait as HashFiles;
15
use CryptoManana\Core\Traits\MessageDigestion\RepetitiveHashingTrait as HashRepetitively;
16
17
/**
18
 * Class AbstractUnkeyedHashFunction - Abstraction for unkeyed hash classes.
19
 *
20
 * @package CryptoManana\Core\Abstractions\MessageDigestion
21
 *
22
 * @mixin HashObjects
23
 * @mixin HashFiles
24
 * @mixin HashRepetitively
25
 */
26
abstract class AbstractUnkeyedHashFunction extends HashAlgorithm implements
27
    ObjectHashing,
28
    FileHashing,
29
    RecursiveHashing
30
{
31
    /**
32
     * Object hashing capabilities.
33
     *
34
     * {@internal Reusable implementation of `ObjectHashingInterface`. }}
35
     */
36
    use HashObjects;
37
38
    /**
39
     * File hashing capabilities.
40
     *
41
     * {@internal Reusable implementation of `FileHashingInterface`. }}
42
     */
43
    use HashFiles;
44
45
    /**
46
     * Repetitive/recursive hashing capabilities.
47
     *
48
     * {@internal Reusable implementation of `RepetitiveHashingInterface`. }}
49
     */
50
    use HashRepetitively;
51
52
    /**
53
     * The internal name of the algorithm.
54
     */
55
    const ALGORITHM_NAME = 'none';
56
57
    /**
58
     * Flag to force native code polyfill realizations, if available.
59
     *
60
     * @var bool Flag to force native realizations.
61
     */
62
    protected $useNative = false;
63
64
    /**
65
     * Unkeyed hash algorithm constructor.
66
     */
67 304
    public function __construct()
68
    {
69 304
    }
70
71
    /**
72
     * Get debug information for the class instance.
73
     *
74
     * @return array Debug information.
75
     */
76 15
    public function __debugInfo()
77
    {
78 15
        return [
79 15
            'standard' => static::ALGORITHM_NAME,
80 15
            'type' => 'unkeyed digestion or checksum',
81 15
            'salt' => $this->salt,
82 15
            'mode' => $this->saltingMode,
83 15
        ];
84
    }
85
86
    /**
87
     * Calculates a hash value for the given data.
88
     *
89
     * @param string $data The input string.
90
     *
91
     * @return string The digest.
92
     * @throws \Exception Validation errors.
93
     */
94 132
    public function hashData($data)
95
    {
96 132
        if (!is_string($data)) {
97 22
            throw new \InvalidArgumentException('The data for hashing must be a string or a binary string.');
98
        }
99
100 110
        $data = $this->addSaltString($data);
101
102 110
        $digest = hash(
103 110
            static::ALGORITHM_NAME,
104 110
            $data,
105 110
            ($this->digestFormat === self::DIGEST_OUTPUT_RAW)
106 110
        );
107
108 110
        $digest = $this->changeOutputFormat($digest);
109
110 110
        return $digest;
111
    }
112
113
    /**
114
     * Calculates a hash value for the content of the given filename and location.
115
     *
116
     * @param string $filename The full path and name of the file for hashing.
117
     *
118
     * @return string The digest.
119
     * @throws \Exception Validation errors.
120
     */
121 45
    public function hashFile($filename)
122
    {
123 45
        if (!is_string($filename)) {
124 15
            throw new \InvalidArgumentException('The file path must be of type string.');
125
        }
126
127 30
        $this->validateFileNamePath($filename);
128
129 15
        $useFileSalting = $this->isFileSaltingForcingNativeHashing();
130
131 15
        if ($this->useNative || $useFileSalting) {
132 15
            $oldSalt = $this->salt;
133 15
            $oldMode = $this->saltingMode;
134
135 15
            $this->salt = ($useFileSalting) ? $this->salt : '';
136 15
            $this->saltingMode = ($useFileSalting) ? $this->saltingMode : self::SALTING_MODE_NONE;
137
138 15
            $digest = $this->hashData(file_get_contents($filename));
139
140 15
            $this->setSalt($oldSalt)->setSaltingMode($oldMode);
141
        } else {
142 15
            $digest = hash_file(
143 15
                static::ALGORITHM_NAME,
144 15
                $filename,
145 15
                ($this->digestFormat === self::DIGEST_OUTPUT_RAW)
146 15
            );
147
148 15
            $digest = $this->changeOutputFormat($digest);
149
        }
150
151 15
        return $digest;
152
    }
153
}
154