Passed
Push — master ( e80b48...a06265 )
by Théo
02:43
created

PharInfo::getPharHash()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 1
dl 0
loc 5
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 0
1
<?php
2
3
declare(strict_types=1);
4
5
/*
6
 * This file is part of the box project.
7
 *
8
 * (c) Kevin Herrera <[email protected]>
9
 *     Théo Fidry <[email protected]>
10
 *
11
 * This source file is subject to the MIT license that is bundled
12
 * with this source code in the file LICENSE.
13
 */
14
15
namespace KevinGH\Box\PharInfo;
16
17
use function array_flip;
18
use function KevinGH\Box\get_phar_compression_algorithms;
19
use function KevinGH\Box\unique_id;
20
use Phar;
21
use PharData;
22
use PharFileInfo;
23
use RecursiveIteratorIterator;
24
use UnexpectedValueException;
25
26
final class PharInfo
27
{
28
    private static $ALGORITHMS;
29
30
    private $phar;
31
32
    /** @var null|array */
33
    private $compressionCount;
34
    /** @var null|string */
35
    private $hash;
36
37
    public function __construct(string $pharFile)
38
    {
39
        if (null === self::$ALGORITHMS) {
40
            self::$ALGORITHMS = array_flip(get_phar_compression_algorithms());
41
            self::$ALGORITHMS[Phar::NONE] = 'None';
42
        }
43
44
        try {
45
            $this->phar = new Phar($pharFile);
46
        } catch (UnexpectedValueException $exception) {
47
            $this->phar = new PharData($pharFile);
48
        }
49
    }
50
51
    public function equals(self $pharInfo): bool
52
    {
53
        return
54
            $pharInfo->getCompressionCount() === $this->getCompressionCount()
55
            && $pharInfo->getNormalizedMetadata() === $this->getNormalizedMetadata()
56
        ;
57
    }
58
59
    public function getCompressionCount(): array
60
    {
61
        if (null === $this->compressionCount || $this->hash !== $this->getPharHash()) {
62
            $this->compressionCount = $this->calculateCompressionCount();
63
            $this->hash = $this->getPharHash();
64
        }
65
66
        return $this->compressionCount;
67
    }
68
69
    /**
70
     * @return Phar|PharData
71
     */
72
    public function getPhar()
73
    {
74
        return $this->phar;
75
    }
76
77
    public function getRoot(): string
78
    {
79
        // Do not cache the result
80
        return 'phar://'.str_replace('\\', '/', realpath($this->phar->getPath())).'/';
81
    }
82
83
    public function getVersion(): string
84
    {
85
        // Do not cache the result
86
        return '' !== $this->phar->getVersion() ? $this->phar->getVersion() : 'No information found';
87
    }
88
89
    public function getNormalizedMetadata(): ?string
90
    {
91
        // Do not cache the result
92
        $metadata = var_export($this->phar->getMetadata(), true);
93
94
        return 'NULL' === $metadata ? null : $metadata;
95
    }
96
97
    private function getPharHash(): string
98
    {
99
        // If no signature is available (e.g. a tar.gz file), we generate a random hash to ensure
100
        // it will always be invalidated
101
        return $this->phar->getSignature()['hash'] ?? unique_id('');
102
    }
103
104
    private function calculateCompressionCount(): array
105
    {
106
        $count = array_fill_keys(
107
            self::$ALGORITHMS,
108
            0
109
        );
110
111
        if ($this->phar instanceof PharData) {
112
            $count[self::$ALGORITHMS[$this->phar->isCompressed()]] = 1;
113
114
            return $count;
115
        }
116
117
        $countFile = static function (array $count, PharFileInfo $file): array {
118
            if (false === $file->isCompressed()) {
119
                ++$count['None'];
120
121
                return $count;
122
            }
123
124
            foreach (self::$ALGORITHMS as $compressionAlgorithmCode => $compressionAlgorithmName) {
125
                if ($file->isCompressed($compressionAlgorithmCode)) {
126
                    ++$count[$compressionAlgorithmName];
127
128
                    return $count;
129
                }
130
            }
131
132
            return $count;
133
        };
134
135
        return array_reduce(
136
            iterator_to_array(new RecursiveIteratorIterator($this->phar), true),
137
            $countFile,
138
            $count
139
        );
140
    }
141
}
142