Completed
Push — master ( 7082f0...55a2b2 )
by Siad
15:25
created

ReplaceTokens::initialize()   C

Complexity

Conditions 13
Paths 10

Size

Total Lines 53
Code Lines 36

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 182

Importance

Changes 0
Metric Value
cc 13
eloc 36
nc 10
nop 0
dl 0
loc 53
ccs 0
cts 34
cp 0
crap 182
rs 6.6166
c 0
b 0
f 0

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

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
 * Replaces tokens in the original input with user-supplied values.
22
 *
23
 * Example:
24
 *
25
 * <pre><replacetokens begintoken="#" endtoken="#">;
26
 *   <token key="DATE" value="${TODAY}"/>
27
 * </replacetokens></pre>
28
 *
29
 * Or:
30
 *
31
 * <pre><filterreader classname="phing.filters.ReplaceTokens">
32
 *   <param type="tokenchar" name="begintoken" value="#"/>
33
 *   <param type="tokenchar" name="endtoken" value="#"/>
34
 *   <param type="token" name="DATE" value="${TODAY}"/>
35
 * </filterreader></pre>
36
 *
37
 * @author  <a href="mailto:[email protected]">Yannick Lecaillez</a>
38
 * @author  hans lellelid, [email protected]
39
 * @see     BaseParamFilterReader
40
 * @package phing.filters
41
 */
42
class ReplaceTokens extends BaseParamFilterReader implements ChainableReader
43
{
44
45
    /**
46
     * Default "begin token" character.
47
     *
48
     * @var string
49
     */
50
    const DEFAULT_BEGIN_TOKEN = "@";
51
52
    /**
53
     * Default "end token" character.
54
     *
55
     * @var string
56
     */
57
    const DEFAULT_END_TOKEN = "@";
58
59
    /**
60
     * Array to hold the replacee-replacer pairs (String to String).
61
     *
62
     * @var array
63
     */
64
    private $tokens = [];
65
66
    /**
67
     * Array to hold the token sources that make tokens from
68
     * different sources available
69
     *
70
     * @var array
71
     */
72
    private $tokensources = [];
73
74
    /**
75
     * Array holding all tokens given directly to the Filter and
76
     * those passed via a TokenSource.
77
     *
78
     * @var array|null
79
     */
80
    private $alltokens = null;
81
82
    /**
83
     * Character marking the beginning of a token.
84
     *
85
     * @var string
86
     */
87
    private $beginToken = "@"; // self::DEFAULT_BEGIN_TOKEN;
88
89
    /**
90
     * Character marking the end of a token.
91
     *
92
     * @var string
93
     */
94
    private $endToken = "@"; //self::DEFAULT_END_TOKEN;
95
96
    /**
97
     * Performs lookup on key and returns appropriate replacement string.
98
     *
99
     * @param  array $matches Array of 1 el containing key to search for.
100
     * @return string Text with which to replace key or value of key if none is found.
101
     */
102 5
    private function replaceTokenCallback($matches)
103
    {
104 5
        $key = $matches[1];
105
106
        /* Get tokens from tokensource and merge them with the
107
         * tokens given directly via build file. This should be
108
         * done a bit more elegantly
109
         */
110 5
        if ($this->alltokens === null) {
111 5
            $this->alltokens = [];
112
113 5
            $count = count($this->tokensources);
114 5
            for ($i = 0; $i < $count; $i++) {
115 1
                $source = $this->tokensources[$i];
116 1
                $this->alltokens = array_merge($this->alltokens, $source->getTokens());
117
            }
118
119 5
            $this->alltokens = array_merge($this->tokens, $this->alltokens);
120
        }
121
122 5
        $tokens = $this->alltokens;
123
124 5
        $replaceWith = null;
125 5
        $count = count($tokens);
126
127 5
        for ($i = 0; $i < $count; $i++) {
128 5
            if ($tokens[$i]->getKey() === $key) {
129 5
                $replaceWith = $tokens[$i]->getValue();
130
            }
131
        }
132
133 5
        if ($replaceWith === null) {
0 ignored issues
show
introduced by
The condition $replaceWith === null is always true.
Loading history...
134
            $replaceWith = $this->beginToken . $key . $this->endToken;
135
            $this->log("No token defined for key \"" . $this->beginToken . $key . $this->endToken . "\"");
136
        } else {
137 5
            $this->log(
138 5
                "Replaced \"" . $this->beginToken . $key . $this->endToken . "\" with \"" . $replaceWith . "\"",
139 5
                Project::MSG_VERBOSE
140
            );
141
        }
142
143 5
        return $replaceWith;
144
    }
145
146
    /**
147
     * Returns stream with tokens having been replaced with appropriate values.
148
     * If a replacement value is not found for a token, the token is left in the stream.
149
     *
150
     * @param  int $len
151
     * @return mixed filtered stream, -1 on EOF.
152
     */
153 5
    public function read($len = null)
154
    {
155 5
        if (!$this->getInitialized()) {
156
            $this->initialize();
157
            $this->setInitialized(true);
158
        }
159
160
        // read from next filter up the chain
161 5
        $buffer = $this->in->read($len);
162
163 5
        if ($buffer === -1) {
164 4
            return -1;
165
        }
166
167
        // filter buffer
168 5
        $buffer = preg_replace_callback(
169 5
            "/" . preg_quote($this->beginToken, '/') . "([\w\.\-:]+?)" . preg_quote($this->endToken, '/') . "/",
170 5
            [$this, 'replaceTokenCallback'],
171 5
            $buffer
172
        );
173
174 5
        return $buffer;
175
    }
176
177
    /**
178
     * Sets the "begin token" character.
179
     *
180
     * @param string $beginToken the character used to denote the beginning of a token.
181
     */
182 5
    public function setBeginToken($beginToken)
183
    {
184 5
        $this->beginToken = (string) $beginToken;
185 5
    }
186
187
    /**
188
     * Returns the "begin token" character.
189
     *
190
     * @return string The character used to denote the beginning of a token.
191
     */
192 5
    public function getBeginToken()
193
    {
194 5
        return $this->beginToken;
195
    }
196
197
    /**
198
     * Sets the "end token" character.
199
     *
200
     * @param string $endToken the character used to denote the end of a token
201
     */
202 5
    public function setEndToken($endToken)
203
    {
204 5
        $this->endToken = (string) $endToken;
205 5
    }
206
207
    /**
208
     * Returns the "end token" character.
209
     *
210
     * @return string the character used to denote the beginning of a token
211
     */
212 5
    public function getEndToken()
213
    {
214 5
        return $this->endToken;
215
    }
216
217
    /**
218
     * Adds a token element to the map of tokens to replace.
219
     *
220
     * @return object The token added to the map of replacements.
221
     *                Must not be <code>null</code>.
222
     */
223 4
    public function createToken()
224
    {
225 4
        $num = array_push($this->tokens, new Token());
226
227 4
        return $this->tokens[$num - 1];
228
    }
229
230
    /**
231
     * Adds a token source to the sources of this filter.
232
     *
233
     * @return object A Reference to the source just added.
234
     */
235 1
    public function createTokensource()
236
    {
237 1
        $num = array_push($this->tokensources, new TokenSource());
238
239 1
        return $this->tokensources[$num - 1];
240
    }
241
242
    /**
243
     * Sets the map of tokens to replace.
244
     * ; used by ReplaceTokens::chain()
245
     *
246
     * @param    $tokens
247
     * @throws   Exception
248
     * @internal param A $array map (String->String) of token keys to replacement
249
     *              values. Must not be <code>null</code>.
250
     */
251 5
    public function setTokens($tokens)
252
    {
253
        // type check, error must never occur, bad code of it does
254 5
        if (!is_array($tokens)) {
255
            throw new Exception("Expected 'array', got something else");
256
        }
257
258 5
        $this->tokens = $tokens;
259 5
    }
260
261
    /**
262
     * Returns the map of tokens which will be replaced.
263
     * ; used by ReplaceTokens::chain()
264
     *
265
     * @return array A map (String->String) of token keys to replacement values.
266
     */
267 5
    public function getTokens()
268
    {
269 5
        return $this->tokens;
270
    }
271
272
    /**
273
     * Sets the tokensources to use; used by ReplaceTokens::chain()
274
     *
275
     * @param    $sources
276
     * @throws   Exception
277
     * @internal param An $array array of token sources.
278
     */
279 5
    public function setTokensources($sources)
280
    {
281
        // type check
282 5
        if (!is_array($sources)) {
283
            throw new Exception("Exspected 'array', got something else");
284
        }
285 5
        $this->tokensources = $sources;
286 5
    }
287
288
    /**
289
     * Returns the token sources used by this filter; used by ReplaceTokens::chain()
290
     *
291
     * @return array
292
     */
293 5
    public function getTokensources()
294
    {
295 5
        return $this->tokensources;
296
    }
297
298
    /**
299
     * Creates a new ReplaceTokens using the passed in
300
     * Reader for instantiation.
301
     *
302
     * @param Reader $reader
303
     * @return ReplaceTokens A new filter based on this configuration, but filtering
304
     *                the specified reader
305
     * @throws Exception
306
     * @internal param A $object Reader object providing the underlying stream.
307
     *               Must not be <code>null</code>.
308
     */
309 5
    public function chain(Reader $reader): Reader
310
    {
311 5
        $newFilter = new ReplaceTokens($reader);
312 5
        $newFilter->setProject($this->getProject());
313 5
        $newFilter->setBeginToken($this->getBeginToken());
314 5
        $newFilter->setEndToken($this->getEndToken());
315 5
        $newFilter->setTokens($this->getTokens());
316 5
        $newFilter->setTokensources($this->getTokensources());
317 5
        $newFilter->setInitialized(true);
318
319 5
        return $newFilter;
320
    }
321
322
    /**
323
     * Initializes tokens and loads the replacee-replacer hashtable.
324
     * This method is only called when this filter is used through
325
     * a <filterreader> tag in build file.
326
     */
327
    private function initialize()
328
    {
329
        $params = $this->getParameters();
330
        if ($params !== null) {
0 ignored issues
show
introduced by
The condition $params !== null is always true.
Loading history...
331
            for ($i = 0, $paramsCount = count($params); $i < $paramsCount; $i++) {
332
                if ($params[$i] !== null) {
333
                    $type = $params[$i]->getType();
334
                    if ($type === "tokenchar") {
335
                        $name = $params[$i]->getName();
336
                        if ($name === "begintoken") {
337
                            $this->beginToken = substr($params[$i]->getValue(), 0, strlen($params[$i]->getValue()));
338
                        } else {
339
                            if ($name === "endtoken") {
340
                                $this->endToken = substr($params[$i]->getValue(), 0, strlen($params[$i]->getValue()));
341
                            }
342
                        }
343
                    } else {
344
                        if ($type === "token") {
345
                            $name = $params[$i]->getName();
346
                            $value = $params[$i]->getValue();
347
348
                            $tok = new Token();
349
                            $tok->setKey($name);
350
                            $tok->setValue($value);
351
352
                            $this->tokens[] = $tok;
353
                        } else {
354
                            if ($type === "tokensource") {
355
                                // Store data from nested tags in local array
356
                                $arr = [];
357
358
                                $subparams = $params[$i]->getParams();
359
                                foreach ($subparams as $subparam) {
360
                                    $arr[$subparam->getName()] = $subparam->getValue();
361
                                }
362
363
                                // Create TokenSource
364
                                $tokensource = new TokenSource();
365
                                if (isset($arr["classname"])) {
366
                                    $tokensource->setClassname($arr["classname"]);
367
                                }
368
369
                                // Copy other parameters 1:1 to freshly created TokenSource
370
                                foreach ($arr as $key => $value) {
371
                                    if (strtolower($key) === "classname") {
372
                                        continue;
373
                                    }
374
                                    $param = $tokensource->createParam();
375
                                    $param->setName($key);
376
                                    $param->setValue($value);
377
                                }
378
379
                                $this->tokensources[] = $tokensource;
380
                            }
381
                        }
382
                    }
383
                }
384
            }
385
        }
386
    }
387
}
388