Completed
Push — master ( 074443...b3b676 )
by Alexey
08:58 queued 11s
created

ZipNewData::__clone()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 7
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 6

Importance

Changes 0
Metric Value
cc 2
eloc 4
c 0
b 0
f 0
nc 2
nop 0
dl 0
loc 7
ccs 0
cts 0
cp 0
crap 6
rs 10
1
<?php
2
3
namespace PhpZip\Model\Data;
4
5
use PhpZip\Model\ZipData;
6
use PhpZip\Model\ZipEntry;
7
use PhpZip\ZipFile;
8
9
/**
10
 * The class contains a streaming resource with new content added to the ZIP archive.
11
 */
12
class ZipNewData implements ZipData
13
{
14
    /**
15
     * A static variable allows closing the stream in the destructor
16
     * only if it is its sole holder.
17
     *
18
     * @var array<int, int> array of resource ids and the number of class clones
19
     */
20
    private static $guardClonedStream = [];
21
22
    /** @var ZipEntry */
23
    private $zipEntry;
24
25 66
    /** @var resource */
26
    private $stream;
27 66
28
    /**
29 66
     * ZipStringData constructor.
30 63
     *
31
     * @param ZipEntry        $zipEntry
32 63
     * @param string|resource $data
33
     */
34
    public function __construct(ZipEntry $zipEntry, $data)
35 63
    {
36 63
        $this->zipEntry = $zipEntry;
37 63
38 4
        if (\is_string($data)) {
39 4
            $zipEntry->setUncompressedSize(\strlen($data));
40
41 66
            if (!($handle = fopen('php://temp', 'w+b'))) {
42
                throw new \RuntimeException('Temp resource can not open from write.');
43
            }
44
            fwrite($handle, $data);
45
            rewind($handle);
46 52
            $this->stream = $handle;
47
        } elseif (\is_resource($data)) {
48 52
            $this->stream = $data;
49
        }
50
51
        $resourceId = (int) $this->stream;
52 52
        self::$guardClonedStream[$resourceId] =
53
            isset(self::$guardClonedStream[$resourceId]) ?
54
                self::$guardClonedStream[$resourceId] + 1 :
55
                0;
56
    }
57
58 1
    /**
59
     * @return resource returns stream data
60 1
     */
61 1
    public function getDataAsStream()
62
    {
63
        if (!\is_resource($this->stream)) {
64 1
            throw new \LogicException(sprintf('Resource was closed (entry=%s).', $this->zipEntry->getName()));
65
        }
66 1
67
        return $this->stream;
68 1
    }
69
70
    /**
71
     * @return string returns data as string
72
     */
73
    public function getDataAsString()
74
    {
75 1
        $stream = $this->getDataAsStream();
76
        $pos = ftell($stream);
77 1
78 1
        try {
79 1
            rewind($stream);
80 1
81
            return stream_get_contents($stream);
82 4
        } finally {
83
            fseek($stream, $pos);
84 4
        }
85 4
    }
86
87 4
    /**
88
     * @param resource $outStream
89
     */
90
    public function copyDataToStream($outStream)
91
    {
92
        $stream = $this->getDataAsStream();
93
        rewind($stream);
94
        stream_copy_to_stream($stream, $outStream);
95
    }
96
97
    /**
98
     * @see https://php.net/manual/en/language.oop5.cloning.php
99
     */
100
    public function __clone()
101
    {
102
        $resourceId = (int) $this->stream;
103
        self::$guardClonedStream[$resourceId] =
104
            isset(self::$guardClonedStream[$resourceId]) ?
105
                self::$guardClonedStream[$resourceId] + 1 :
106
                1;
107
    }
108
109
    /**
110
     * The stream will be closed when closing the zip archive.
111
     *
112
     * The method implements protection against closing the stream of the cloned object.
113
     *
114
     * @see ZipFile::close()
115
     */
116
    public function __destruct()
117
    {
118
        $resourceId = (int) $this->stream;
119
120
        if (isset(self::$guardClonedStream[$resourceId]) && self::$guardClonedStream[$resourceId] > 0) {
121
            self::$guardClonedStream[$resourceId]--;
122
123
            return;
124
        }
125
126
        if (\is_resource($this->stream)) {
127
            fclose($this->stream);
128
        }
129
    }
130
}
131