Completed
Push — master ( 37ee2c...b1f948 )
by Eric
06:59
created

Base64FileTrait::createCopyException()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 9
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 6
CRAP Score 1

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 9
ccs 6
cts 6
cp 1
rs 9.6666
cc 1
eloc 5
nc 1
nop 0
crap 1
1
<?php
2
3
/*
4
 * This file is part of the Ivory Base64 File package.
5
 *
6
 * (c) Eric GELOEN <[email protected]>
7
 *
8
 * For the full copyright and license information, please read the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
12
namespace Ivory\Base64FileBundle\Model;
13
14
/**
15
 * @author GeLo <[email protected]>
16
 */
17
trait Base64FileTrait
18
{
19
    /**
20
     * @var string
21
     */
22
    private $path;
23
24
    /**
25
     * @var resource
26
     */
27
    private $resource;
28
29
    /**
30
     * {@inheritdoc}
31
     */
32 318
    public function __destruct()
33
    {
34 318
        if (is_resource($this->resource)) {
35 318
            fclose($this->resource);
36 248
        }
37
38 318
        if (file_exists($this->path)) {
39 318
            unlink($this->path);
40 248
        }
41 318
    }
42
43
    /**
44
     * @param bool $encoded
45
     * @param bool $asResource
46
     *
47
     * @return resource|string
48
     */
49 315
    public function getData($encoded = true, $asResource = true)
50
    {
51 315
        $resource = fopen('php://temp', 'rb+');
52
53 315
        if ($encoded) {
54 171
            $filter = stream_filter_append($resource, 'convert.base64-encode', STREAM_FILTER_WRITE);
55 133
        }
56
57 315
        $this->copyStreamToStream($this->resource, $resource);
58
59 315
        if (isset($filter)) {
60 171
            stream_filter_remove($filter);
61 133
        }
62
63 315
        if ($asResource) {
64 144
            return $resource;
65
        }
66
67 171
        $content = stream_get_contents($resource);
68 171
        fclose($resource);
69
70 171
        return $content;
71
    }
72
73
    /**
74
     * @param string|resource $value
75
     * @param bool            $encoded
76
     *
77
     * @return string
78
     */
79 405
    private function load($value, $encoded = true)
80
    {
81 405
        $this->path = tempnam(sys_get_temp_dir(), 'ivory_base64');
82 405
        $this->resource = fopen($this->path, 'w+');
83
84 405
        if ($encoded) {
85 261
            $filter = stream_filter_append($this->resource, 'convert.base64-decode', STREAM_FILTER_WRITE);
86 203
        }
87
88
        try {
89 405
            if (is_string($value)) {
90 198
                $this->copyStringToStream($value, $this->resource);
91 340
            } elseif (is_resource($value)) {
92 189
                $this->copyStreamToStream($value, $this->resource);
93 133
            } else {
94 18
                throw new \InvalidArgumentException(sprintf(
95 18
                    'The base64 file value must be a string or a resource, got "%s".',
96 94
                    is_object($value) ? get_class($value) : gettype($value)
97 14
                ));
98
            }
99 329
        } catch (\Exception $e) {
100 63
            fclose($this->resource);
101
102 63
            throw $e;
103
        }
104
105 342
        if (isset($filter)) {
106 198
            stream_filter_remove($filter);
107 154
        }
108
109 342
        fflush($this->resource);
110
111 342
        return $this->path;
112
    }
113
114
    /**
115
     * @param string   $from
116
     * @param resource $to
117
     */
118 198
    private function copyStringToStream($from, $to)
119
    {
120 198
        $toPosition = ftell($to);
121 198
        $success = @fwrite($to, $from);
122 198
        fseek($to, $toPosition);
123
124 198
        if (!$success) {
125 27
            throw $this->createCopyException();
126
        }
127 171
    }
128
129
    /**
130
     * @param resource $from
131
     * @param resource $to
132
     */
133 360
    private function copyStreamToStream($from, $to)
134
    {
135 360
        $metadata = stream_get_meta_data($from);
136 360
        $seekable = $metadata['seekable'];
137
138 360
        $toPosition = ftell($to);
139
140 360
        if ($seekable) {
141 360
            $fromPosition = ftell($from);
142 360
            rewind($from);
143 280
        }
144
145 360
        $success = @stream_copy_to_stream($from, $to);
146
147 360
        if (isset($fromPosition)) {
148 360
            fseek($from, $fromPosition);
149 280
        }
150
151 360
        fseek($to, $toPosition);
152
153 360
        if (!$success) {
154 18
            throw $this->createCopyException();
155
        }
156 342
    }
157
158
    /**
159
     * @return \RuntimeException
160
     */
161 45
    private function createCopyException()
162
    {
163 45
        $error = error_get_last();
164
165 45
        return new \RuntimeException(sprintf(
166 45
            'An error occurred while copying the value (%s).',
167 45
            $error['message']
168 35
        ));
169
    }
170
}
171