Completed
Push — feature-20rc1 ( 008ae2 )
by Rob
16:55
created

FileTemp::release()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 14
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 14
rs 9.4285
c 0
b 0
f 0
cc 3
eloc 7
nc 3
nop 1
1
<?php
2
3
/*
4
 * This file is part of the `liip/LiipImagineBundle` project.
5
 *
6
 * (c) https://github.com/liip/LiipImagineBundle/graphs/contributors
7
 *
8
 * For the full copyright and license information, please view the LICENSE.md
9
 * file that was distributed with this source code.
10
 */
11
12
namespace Liip\ImagineBundle\File;
13
14
use Liip\ImagineBundle\Exception\File\FileOperationException;
15
use Liip\ImagineBundle\File\Lock\LockInvokable;
16
use Liip\ImagineBundle\Utility\Interpreter\Interpreter;
17
18
/**
19
 * @author Rob Frawley 2nd <[email protected]>
20
 */
21
final class FileTemp extends AbstractFilePath implements FilePathInterface
22
{
23
    /**
24
     * @var string
25
     */
26
    private $name;
27
28
    /**
29
     * @var string
30
     */
31
    private $root;
32
33
    /**
34
     * @param string|null $name
35
     * @param string|null $root
36
     */
37
    public function __construct(string $name = null, string $root = null)
38
    {
39
        parent::__construct();
40
41
        $this->setName($name);
42
        $this->setRoot($root);
43
    }
44
45
    /**
46
     * Automatically release the temporary file.
47
     */
48
    public function __destruct()
49
    {
50
        $this->release();
51
    }
52
53
    /**
54
     * @param string|null $name
55
     * @param string|null $root
56
     * @param string|null $contents
57
     *
58
     * @return self
59
     */
60
    public static function create(string $name = null, string $root = null, string $contents = null): self
61
    {
62
        $temporary = new self($name, $root);
63
64
        if (null !== $contents) {
65
            $temporary->setContents($contents);
66
        }
67
68
        return $temporary;
69
    }
70
71
    /**
72
     * @return string
73
     */
74
    public function getName(): string
75
    {
76
        return $this->name;
77
    }
78
79
    /**
80
     * @param string|null $name
81
     *
82
     * @return self
83
     */
84
    public function setName(string $name = null): self
85
    {
86
        $this->requireReleasedState('failed to change context descriptor');
87
        $this->name = sprintf('imagine-bundle-temporary_%s', $name ?: 'general');
88
89
        return $this;
90
    }
91
92
    /**
93
     * @return string
94
     */
95
    public function getRoot(): string
96
    {
97
        return $this->root;
98
    }
99
100
    /**
101
     * @param string|null $path
102
     *
103
     * @return FileTemp
104
     */
105
    public function setRoot(string $path = null): self
106
    {
107
        $this->requireReleasedState('failed to change path prefix');
108
        $this->root = self::makePathIfNotExists($path ?? sys_get_temp_dir());
109
110
        return $this;
111
    }
112
113
    /**
114
     * @return bool
115
     */
116
    public function isAcquired(): bool
117
    {
118
        return $this->hasFile();
119
    }
120
121
    /**
122
     * @return self
123
     */
124
    public function acquire(): self
125
    {
126
        $this->requireReleasedState('failed to acquire a new one');
127
128
        $this->file = LockInvokable::blocking($this, function (): \SplFileInfo {
129
            if (false !== $file = @tempnam($this->getRoot(), $this->getName())) {
130
                return new \SplFileInfo($file);
131
            }
132
133
            throw new FileOperationException(
134
                'Failed to acquire temporary file in "%s": %s.', $this->getRoot(), Interpreter::error()->message()
135
            );
136
        });
137
138
        return $this;
139
    }
140
141
    /**
142
     * @param bool $remove
143
     *
144
     * @return self
145
     */
146
    public function release(bool $remove = true): self
147
    {
148
        if (!$this->isAcquired()) {
149
            return $this;
150
        }
151
152
        if ($remove) {
153
            $this->remove();
154
        }
155
156
        $this->file = null;
157
158
        return $this;
159
    }
160
161
    /**
162
     * @param string $contents
163
     * @param bool   $append
164
     */
165
    protected function doSetContents(string $contents, bool $append): void
166
    {
167
        if (!$this->isAcquired()) {
168
            $this->acquire();
169
        }
170
171
        parent::doSetContents($contents, $append);
172
    }
173
174
    /**
175
     * @param string $message
176
     */
177
    private function requireReleasedState(string $message): void
178
    {
179
        if ($this->isAcquired()) {
180
            throw new FileOperationException('Temporary file must be released first: %s', $message);
181
        }
182
    }
183
}
184