Passed
Push — master ( f7820d...ce329c )
by Siad
11:00
created

TruncateTask::shouldProcess()   A

Complexity

Conditions 6
Paths 7

Size

Total Lines 22
Code Lines 15

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 8
CRAP Score 9.6594

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 6
eloc 15
c 1
b 0
f 0
nc 7
nop 1
dl 0
loc 22
ccs 8
cts 15
cp 0.5333
crap 9.6594
rs 9.2222
1
<?php
2
/**
3
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
4
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
5
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
6
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
7
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
8
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
9
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
10
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
11
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
12
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
13
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
14
 *
15
 * This software consists of voluntary contributions made by many individuals
16
 * and is licensed under the LGPL. For more information please see
17
 * <http://phing.info>.
18
 */
19
20
/**
21
 * @author  Siad Ardroumli <[email protected]>
22
 * @package phing.tasks.system
23
 */
24
class TruncateTask extends Task
25
{
26
    private $create = true;
27
    private $mkdirs = false;
28
29
    private $length;
30
    private $adjust;
31
    private $file;
32
33
    /**
34
     * Set a single target File.
35
     *
36
     * @param  PhingFile $f the single File
37
     * @throws \IOException
38
     * @throws \NullPointerException
39
     */
40 9
    public function setFile(PhingFile $f): void
41
    {
42 9
        $this->file = $f;
43 9
    }
44
45
    /**
46
     * Set the amount by which files' lengths should be adjusted.
47
     * It is permissible to append k / m / g.
48
     *
49
     * @param string $adjust (positive or negative) adjustment amount.
50
     */
51 3
    public function setAdjust(string $adjust)
52
    {
53 3
        $this->adjust = Phing::convertShorthand($adjust);
54 3
    }
55
56
    /**
57
     * Set the length to which files should be set.
58
     * It is permissible to append k / m / g.
59
     *
60
     * @param string $length (positive) adjustment amount.
61
     *
62
     * @throws \BuildException
63
     */
64 9
    public function setLength(string $length)
65
    {
66 9
        $this->length = Phing::convertShorthand($length);
67 9
        if ($this->length !== null && $this->length < 0) {
68 1
            throw new BuildException('Cannot truncate to length ' . $this->length);
69
        }
70 8
    }
71
72
    /**
73
     * Set whether to create nonexistent files.
74
     *
75
     * @param boolean $create default <code>true</code>.
76
     */
77 1
    public function setCreate($create)
78
    {
79 1
        $this->create = $create;
80 1
    }
81
82
    /**
83
     * Set whether, when creating nonexistent files, nonexistent directories
84
     * should also be created.
85
     *
86
     * @param boolean $mkdirs default <code>false</code>.
87
     */
88 1
    public function setMkdirs($mkdirs)
89
    {
90 1
        $this->mkdirs = $mkdirs;
91 1
    }
92
93
    /**
94
     * {@inheritDoc}.
95
     *
96
     * @throws \BuildException
97
     */
98 9
    public function main()
99
    {
100 9
        if ($this->length !== null && $this->adjust !== null) {
101 1
            throw new BuildException(
102 1
                'length and adjust are mutually exclusive options'
103
            );
104
        }
105 8
        if ($this->length === null && $this->adjust === null) {
106 1
            $this->length = 0;
107
        }
108 8
        if ($this->file === null) {
109 1
            throw new BuildException('No files specified.');
110
        }
111
112 7
        if ($this->shouldProcess($this->file)) {
113 6
            $this->process($this->file);
114
        }
115 7
    }
116
117
    /**
118
     * @param PhingFile $f
119
     * @return bool
120
     * @throws \BuildException
121
     */
122 7
    private function shouldProcess(PhingFile $f)
123
    {
124 7
        if ($f->isFile()) {
125 2
            return true;
126
        }
127 7
        if (!$this->create) {
128 1
            return false;
129
        }
130 6
        $exception = null;
131
        try {
132 6
            if ($f->createNewFile($this->mkdirs)) {
133 6
                return true;
134
            }
135
        } catch (IOException $e) {
136
            $exception = $e;
137
        }
138
        $msg = "Unable to create " . $f;
139
        if ($exception === null) {
140
            $this->log($msg, Project::MSG_WARN);
141
            return false;
142
        }
143
        throw new BuildException($msg, $exception);
144
    }
145
146 6
    private function process(PhingFile $f)
147
    {
148 6
        $len = $f->length();
149 6
        $newLength = $this->length ?? $len + $this->adjust;
150
151 6
        if ($len === $newLength) {
152
            //nothing to do!
153 2
            return;
154
        }
155
156 4
        $splFile = new SplFileObject($f->getPath(), 'a+');
157
158 4
        if (!$splFile->ftruncate((int) $newLength)) {
159
            throw new BuildException("Exception working with " . (string) $splFile);
160
        }
161
162 4
        $splFile->rewind();
163 4
        clearstatcache();
164 4
    }
165
}
166