Passed
Push — main ( 7acf43...7c92cb )
by Michiel
06:10
created

ReflexiveTask::setFile()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
eloc 1
dl 0
loc 3
ccs 2
cts 2
cp 1
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 1
crap 1
1
<?php
2
3
/**
4
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
5
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
6
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
7
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
8
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
9
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
10
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
11
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
12
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
13
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
14
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
15
 *
16
 * This software consists of voluntary contributions made by many individuals
17
 * and is licensed under the LGPL. For more information please see
18
 * <http://phing.info>.
19
 */
20
21
namespace Phing\Task\System;
22
23
use Exception;
24
use Phing\Exception\BuildException;
25
use Phing\Io\File;
26
use Phing\Io\FileReader;
27
use Phing\Io\FileUtils;
28
use Phing\Io\FileWriter;
29
use Phing\Io\IOException;
30
use Phing\Project;
31
use Phing\Task;
32
use Phing\Type\Element\FileSetAware;
33
use Phing\Type\Element\FilterChainAware;
34
35
/**
36
 * This task is for using filter chains to make changes to files and overwrite the original files.
37
 *
38
 * This task was created to serve the need for "cleanup" tasks -- e.g. a ReplaceRegexp task or strip task
39
 * being used to modify files and then overwrite the modified files.  In many (most?) cases you probably
40
 * should just use a copy task  to preserve the original source files, but this task supports situations
41
 * where there is no src vs. build directory, and modifying source files is actually desired.
42
 *
43
 * <code>
44
 *    <reflexive>
45
 *        <fileset dir=".">
46
 *            <include pattern="*.html">
47
 *        </fileset>
48
 *        <filterchain>
49
 *            <replaceregexp>
50
 *                <regexp pattern="\n\r" replace="\n"/>
51
 *            </replaceregexp>
52
 *        </filterchain>
53
 *    </reflexive>
54
 * </code>
55
 *
56
 * @author Hans Lellelid <[email protected]>
57
 */
58
class ReflexiveTask extends Task
59
{
60
    use FileSetAware;
61
    use FilterChainAware;
62
63
    /**
64
     * Single file to process.
65
     *
66
     * @var File
67
     */
68
    private $file;
69
70
    /**
71
     * Alias for setFrom().
72
     */
73 2
    public function setFile(File $f)
74
    {
75 2
        $this->file = $f;
76
    }
77
78
    /**
79
     * Append the file(s).
80
     *
81
     * @throws \InvalidArgumentException|IOException
82
     */
83 4
    public function main()
84
    {
85 4
        $this->validateAttributes();
86
87
        // compile a list of all files to modify, both file attrib and fileset elements
88
        // can be used.
89
90 1
        $files = [];
91
92 1
        if (null !== $this->file) {
93
            $files[] = $this->file;
94
        }
95
96 1
        if (!empty($this->filesets)) {
97 1
            foreach ($this->filesets as $fs) {
98
                try {
99 1
                    $ds = $fs->getDirectoryScanner($this->project);
100 1
                    $filenames = $ds->getIncludedFiles(); // get included filenames
101 1
                    $dir = $fs->getDir($this->project);
102 1
                    foreach ($filenames as $fname) {
103 1
                        $files[] = new File($dir, $fname);
104
                    }
105
                } catch (BuildException $be) {
106
                    $this->log($be->getMessage(), Project::MSG_WARN);
107
                }
108
            }
109
        }
110
111 1
        $this->log('Applying reflexive processing to ' . count($files) . ' files.');
112
113
        // These "slots" allow filters to retrieve information about the currently-being-process files
114 1
        $slot = $this->getRegisterSlot('currentFile');
115 1
        $basenameSlot = $this->getRegisterSlot('currentFile.basename');
116
117 1
        foreach ($files as $file) {
118
            // set the register slots
119
120 1
            $slot->setValue($file->getPath());
121 1
            $basenameSlot->setValue($file->getName());
122
123
            // 1) read contents of file, pulling through any filters
124 1
            $in = null;
0 ignored issues
show
Unused Code introduced by
The assignment to $in is dead and can be removed.
Loading history...
125 1
            $out = null;
0 ignored issues
show
Unused Code introduced by
The assignment to $out is dead and can be removed.
Loading history...
126 1
            $contents = '';
127
128
            try {
129 1
                $in = FileUtils::getChainedReader(new FileReader($file), $this->filterChains, $this->project);
130 1
                while (-1 !== ($buffer = $in->read())) {
131 1
                    $contents .= $buffer;
132
                }
133 1
                $in->close();
134
            } catch (Exception $e) {
135
                if ($in) {
136
                    $in->close();
137
                }
138
                $this->log('Error reading file: ' . $e->getMessage(), Project::MSG_WARN);
139
            }
140
141
            try {
142
                // now create a FileWriter w/ the same file, and write to the file
143 1
                $out = new FileWriter($file);
144 1
                $out->write($contents);
145 1
                $out->close();
146 1
                $this->log('Applying reflexive processing to ' . $file->getPath(), Project::MSG_VERBOSE);
147
            } catch (Exception $e) {
148
                if ($out) {
149
                    $out->close();
150
                }
151
                $this->log('Error writing file back: ' . $e->getMessage(), Project::MSG_WARN);
152
            }
153
        }
154
    }
155
156
    /**
157
     * Validate task attributes.
158
     *
159
     * @throws IOException
160
     */
161 4
    private function validateAttributes(): void
162
    {
163 4
        if (null === $this->file && empty($this->filesets)) {
164 1
            throw new BuildException('You must specify a file or fileset(s) for the <reflexive> task.');
165
        }
166
167 3
        if (null !== $this->file && $this->file->isDirectory()) {
168 1
            throw new BuildException('File cannot be a directory.');
169
        }
170
171 2
        if (empty($this->filterChains)) {
172 1
            throw new BuildException('You must specify a filterchain for the <reflexive> task.');
173
        }
174
    }
175
}
176