Passed
Push — master ( b9bc63...f1e2bc )
by Michiel
06:23
created

ChownTask::chown()   B

Complexity

Conditions 9
Paths 40

Size

Total Lines 48
Code Lines 28

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 90

Importance

Changes 0
Metric Value
eloc 28
dl 0
loc 48
ccs 0
cts 28
cp 0
rs 8.0555
c 0
b 0
f 0
cc 9
nc 40
nop 0
crap 90
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
namespace Phing\Task\System;
21
22
use Exception;
23
use Phing\Exception\BuildException;
24
use Phing\Io\File;
25
use Phing\Project;
26
use Phing\Task;
27
use Phing\Type\Element\DirSetAware;
28
use Phing\Type\Element\FileSetAware;
29
30
/**
31
 * Task that changes the permissions on a file/directory.
32
 *
33
 * @author  Mehmet Emre Yilmaz <[email protected]>
34
 * @package phing.tasks.system
35
 */
36
class ChownTask extends Task
37
{
38
    use DirSetAware;
39
    use FileSetAware;
40
41
    private $file;
42
43
    private $user;
44
    private $group;
45
46
    private $quiet = false;
47
    private $failonerror = true;
48
    private $verbose = true;
49
50
    /**
51
     * This flag means 'note errors to the output, but keep going'
52
     *
53
     * @see   setQuiet()
54
     * @param $bool
55
     */
56
    public function setFailonerror($bool)
57
    {
58
        $this->failonerror = $bool;
59
    }
60
61
    /**
62
     * Set quiet mode, which suppresses warnings if chown() fails.
63
     *
64
     * @see   setFailonerror()
65
     * @param $bool
66
     */
67
    public function setQuiet($bool)
68
    {
69
        $this->quiet = $bool;
70
        if ($this->quiet) {
71
            $this->failonerror = false;
72
        }
73
    }
74
75
    /**
76
     * Set verbosity, which if set to false surpresses all but an overview
77
     * of what happened.
78
     *
79
     * @param $bool
80
     */
81
    public function setVerbose(bool $bool)
82
    {
83
        $this->verbose = $bool;
84
    }
85
86
    /**
87
     * Sets a single source file to touch.  If the file does not exist
88
     * an empty file will be created.
89
     *
90
     * @param File $file
91
     */
92
    public function setFile(File $file)
93
    {
94
        $this->file = $file;
95
    }
96
97
    /**
98
     * Sets the user
99
     *
100
     * @param $user
101
     */
102
    public function setUser($user)
103
    {
104
        $this->user = $user;
105
    }
106
107
    /**
108
     * Sets the group
109
     *
110
     * @param $group
111
     */
112
    public function setGroup($group)
113
    {
114
        $this->group = $group;
115
    }
116
117
    /**
118
     * Execute the touch operation.
119
     *
120
     * @return void
121
     */
122
    public function main()
123
    {
124
        // Check Parameters
125
        $this->checkParams();
126
        $this->chown();
127
    }
128
129
    /**
130
     * Ensure that correct parameters were passed in.
131
     *
132
     * @throws BuildException
133
     * @return void
134
     */
135
    private function checkParams()
136
    {
137
        if ($this->file === null && empty($this->filesets) && empty($this->dirsets)) {
138
            throw new BuildException("Specify at least one source - a file or a fileset.");
139
        }
140
141
        if ($this->user === null && $this->group === null) {
142
            throw new BuildException("You have to specify either an owner or a group for chown.");
143
        }
144
    }
145
146
    /**
147
     * Does the actual work.
148
     *
149
     * @return void
150
     */
151
    private function chown()
152
    {
153
        $userElements = explode('.', $this->user);
154
155
        $user = $userElements[0];
156
157
        if (count($userElements) > 1) {
158
            $group = $userElements[1];
159
        } else {
160
            $group = $this->group;
161
        }
162
163
        // counters for non-verbose output
164
        $total_files = 0;
165
        $total_dirs = 0;
166
167
        // one file
168
        if ($this->file !== null) {
169
            $total_files = 1;
170
            $this->chownFile($this->file, $user, $group);
171
        }
172
173
        $this->filesets = array_merge($this->filesets, $this->dirsets);
174
175
        // filesets
176
        foreach ($this->filesets as $fs) {
177
            $ds = $fs->getDirectoryScanner($this->project);
178
            $fromDir = $fs->getDir($this->project);
179
180
            $srcFiles = $ds->getIncludedFiles();
181
            $srcDirs = $ds->getIncludedDirectories();
182
183
            $filecount = count($srcFiles);
184
            $total_files += $filecount;
185
            for ($j = 0; $j < $filecount; $j++) {
186
                $this->chownFile(new File($fromDir, $srcFiles[$j]), $user, $group);
187
            }
188
189
            $dircount = count($srcDirs);
190
            $total_dirs += $dircount;
191
            for ($j = 0; $j < $dircount; $j++) {
192
                $this->chownFile(new File($fromDir, $srcDirs[$j]), $user, $group);
193
            }
194
        }
195
196
        if (!$this->verbose) {
197
            $this->log('Total files changed to ' . $user . ($group ? "." . $group : "") . ': ' . $total_files);
198
            $this->log('Total directories changed to ' . $user . ($group ? "." . $group : "") . ': ' . $total_dirs);
199
        }
200
    }
201
202
    /**
203
     * Actually change the mode for the file.
204
     *
205
     * @param  File $file
206
     * @param  string $user
207
     * @param  string $group
208
     * @throws BuildException
209
     * @throws Exception
210
     */
211
    private function chownFile(File $file, $user, $group = "")
212
    {
213
        if (!$file->exists()) {
214
            throw new BuildException("The file " . $file->__toString() . " does not exist");
215
        }
216
217
        try {
218
            if (!empty($user)) {
219
                $file->setUser($user);
220
            }
221
222
            if (!empty($group)) {
223
                $file->setGroup($group);
224
            }
225
226
            if ($this->verbose) {
227
                $this->log(
228
                    "Changed file owner on '" . $file->__toString() . "' to " . $user . ($group ? "." . $group : "")
229
                );
230
            }
231
        } catch (Exception $e) {
232
            if ($this->failonerror) {
233
                throw $e;
234
            }
235
236
            $this->log($e->getMessage(), $this->quiet ? Project::MSG_VERBOSE : Project::MSG_WARN);
237
        }
238
    }
239
}
240