Completed
Push — master ( faecaf...e43139 )
by Siad
15:28
created

Mapper::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 2
nc 1
nop 1
dl 0
loc 4
ccs 3
cts 3
cp 1
crap 1
rs 10
c 0
b 0
f 0
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
 * Filename Mapper maps source file name(s) to target file name(s).
22
 *
23
 * Built-in mappers can be accessed by specifying they "type" attribute:
24
 * <code>
25
 * <mapper type="glob" from="*.php" to="*.php.bak"/>
26
 * </code>
27
 * Custom mappers can be specified by providing a dot-path to a include_path-relative
28
 * class:
29
 * <code>
30
 * <mapper classname="myapp.mappers.DevToProdMapper" from="*.php" to="*.php"/>
31
 * <!-- maps all PHP files from development server to production server, for example -->
32
 * </code>
33
 *
34
 * @author  Hans Lellelid <[email protected]>
35
 * @package phing.types
36
 */
37
class Mapper extends DataType
38
{
39
    protected $type;
40
    protected $classname;
41
    protected $from;
42
    protected $to;
43
44
    /**
45
     * @var Path $classpath
46
     */
47
    protected $classpath;
48
    protected $classpathId;
49
50
    /**
51
     * @var ContainerMapper $container
52
     */
53
    private $container = null;
54
55
    /**
56
     * @param Project $project
57
     */
58 15
    public function __construct(Project $project)
59
    {
60 15
        parent::__construct();
61 15
        $this->project = $project;
62 15
    }
63
64
    /**
65
     * Set the classpath to be used when searching for component being defined
66
     *
67
     * @param  Path $classpath An Path object containing the classpath.
68
     * @throws BuildException
69
     */
70 2
    public function setClasspath(Path $classpath)
71
    {
72 2
        if ($this->isReference()) {
73 1
            throw $this->tooManyAttributes();
74
        }
75 1
        if ($this->classpath === null) {
76 1
            $this->classpath = $classpath;
77
        } else {
78
            $this->classpath->append($classpath);
79
        }
80 1
    }
81
82
    /**
83
     * Create the classpath to be used when searching for component being defined
84
     */
85 2
    public function createClasspath()
86
    {
87 2
        if ($this->isReference()) {
88 1
            throw $this->tooManyAttributes();
89
        }
90 1
        if ($this->classpath === null) {
91
            $this->classpath = new Path($this->project);
92
        }
93
94 1
        return $this->classpath->createPath();
95
    }
96
97
    /**
98
     * Reference to a classpath to use when loading the files.
99
     *
100
     * @param  Reference $r
101
     * @throws BuildException
102
     */
103 1
    public function setClasspathRef(Reference $r)
104
    {
105 1
        if ($this->isReference()) {
106 1
            throw $this->tooManyAttributes();
107
        }
108
        $this->classpathId = $r->getRefId();
109
        $this->createClasspath()->setRefid($r);
110
    }
111
112
    /**
113
     * Set the type of FileNameMapper to use.
114
     *
115
     * @param  $type
116
     * @throws BuildException
117
     */
118 10
    public function setType($type)
119
    {
120 10
        if ($this->isReference()) {
121 1
            throw $this->tooManyAttributes();
122
        }
123 9
        $this->type = $type;
124 9
    }
125
126
    /**
127
     * Add a nested <code>FileNameMapper</code>.
128
     *
129
     * @param  FileNameMapper $fileNameMapper the <code>FileNameMapper</code> to add.
130
     * @throws BuildException
131
     */
132 2
    public function add(Mapper $fileNameMapper)
133
    {
134 2
        if ($this->isReference()) {
135
            throw $this->noChildrenAllowed();
136
        }
137 2
        if ($this->container == null) {
138 2
            if ($this->type == null && $this->classname == null) {
139 1
                $this->container = new CompositeMapper();
140
            } else {
141 2
                $m = $this->getImplementation();
142 2
                if ($m instanceof ContainerMapper) {
143 2
                    $this->container = $m;
144
                } else {
145
                    throw new BuildException("$m mapper implementation does not support nested mappers!");
146
                }
147
            }
148
        }
149 2
        $this->container->add($fileNameMapper);
150 2
        $this->checked = false;
151 2
    }
152
153
    /**
154
     * Add a Mapper
155
     *
156
     * @param Mapper $mapper the mapper to add
157
     */
158 2
    public function addMapper(Mapper $mapper)
159
    {
160 2
        $this->add($mapper);
161 2
    }
162
163
    /**
164
     * Set the class name of the FileNameMapper to use.
165
     *
166
     * @param  string $classname
167
     * @throws BuildException
168
     */
169 1
    public function setClassname($classname)
170
    {
171 1
        if ($this->isReference()) {
172 1
            throw $this->tooManyAttributes();
173
        }
174
        $this->classname = $classname;
175
    }
176
177
    /**
178
     * Set the argument to FileNameMapper.setFrom
179
     *
180
     * @param  $from
181
     * @throws BuildException
182
     */
183 9
    public function setFrom($from)
184
    {
185 9
        if ($this->isReference()) {
186 1
            throw $this->tooManyAttributes();
187
        }
188 9
        $this->from = $from;
189 9
    }
190
191
    /**
192
     * Set the argument to FileNameMapper.setTo
193
     *
194
     * @param  $to
195
     * @throws BuildException
196
     */
197 10
    public function setTo($to)
198
    {
199 10
        if ($this->isReference()) {
200 1
            throw $this->tooManyAttributes();
201
        }
202 9
        $this->to = $to;
203 9
    }
204
205
    /**
206
     * Make this Mapper instance a reference to another Mapper.
207
     *
208
     * You must not set any other attribute if you make it a reference.
209
     *
210
     * @param  Reference $r
211
     * @throws BuildException
212
     */
213 6
    public function setRefid(Reference $r)
214
    {
215 6
        if ($this->type !== null || $this->from !== null || $this->to !== null) {
216 1
            throw DataType::tooManyAttributes();
217
        }
218 6
        parent::setRefid($r);
219 6
    }
220
221
    /**
222
     * Factory, returns inmplementation of file name mapper as new instance
223
     */
224 8
    public function getImplementation()
225
    {
226 8
        if ($this->isReference()) {
227 1
            $o = $this->getRef();
228 1
            if ($o instanceof FileNameMapper) {
229
                return $o;
230
            }
231 1
            if ($o instanceof Mapper) {
232 1
                return $o->getImplementation();
233
            }
234
235
            $od = $o == null ? "null" : get_class($o);
236
            throw new BuildException($od . " at reference '" . $this->getRefId() . "' is not a valid mapper reference.");
237
        }
238
239 8
        if ($this->type === null && $this->classname === null && $this->container == null) {
240
            throw new BuildException("either type or classname attribute must be set for <mapper>");
241
        }
242
243 8
        if ($this->container != null) {
244 2
            return $this->container;
245
        }
246
247 8
        if ($this->type !== null) {
248 8
            switch ($this->type) {
249 8
                case 'chained':
250 1
                    $this->classname = 'phing.mappers.ChainedMapper';
251 1
                    break;
252 8
                case 'composite':
253
                    $this->classname = 'phing.mappers.CompositeMapper';
254
                    break;
255 8
                case 'cutdirs':
256 1
                    $this->classname = 'phing.mappers.CutDirsMapper';
257 1
                    break;
258 7
                case 'identity':
259
                    $this->classname = 'phing.mappers.IdentityMapper';
260
                    break;
261 7
                case 'firstmatch':
262 1
                    $this->classname = 'phing.mappers.FirstMatchMapper';
263 1
                    break;
264 7
                case 'flatten':
265 1
                    $this->classname = 'phing.mappers.FlattenMapper';
266 1
                    break;
267 7
                case 'glob':
268 7
                    $this->classname = 'phing.mappers.GlobMapper';
269 7
                    break;
270
                case 'regexp':
271
                case 'regex':
272
                    $this->classname = 'phing.mappers.RegexpMapper';
273
                    break;
274
                case 'merge':
275
                    $this->classname = 'phing.mappers.MergeMapper';
276
                    break;
277
                default:
278
                    throw new BuildException("Mapper type {$this->type} not known");
279
                    break;
280
            }
281
        }
282
283
        // get the implementing class
284 8
        $cls = Phing::import($this->classname, $this->classpath);
285
286 8
        $m = new $cls();
287 8
        $m->setFrom($this->from);
288 8
        $m->setTo($this->to);
289
290 8
        return $m;
291
    }
292
293
    /**
294
     * Performs the check for circular references and returns the referenced Mapper.
295
     */
296 1
    private function getRef()
297
    {
298 1
        $dataTypeName = StringHelper::substring(__CLASS__, strrpos(__CLASS__, '\\') + 1);
299 1
        return $this->getCheckedRef(__CLASS__, $dataTypeName);
300
    }
301
}
302