IntroductionFilter::filter()   C
last analyzed

Complexity

Conditions 15
Paths 3

Size

Total Lines 81

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 81
rs 5.1478
c 0
b 0
f 0
cc 15
nc 3
nop 4

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
/**
4
 * \AppserverIo\Doppelgaenger\StreamFilters\IntroductionFilter
5
 *
6
 * NOTICE OF LICENSE
7
 *
8
 * This source file is subject to the Open Software License (OSL 3.0)
9
 * that is available through the world-wide-web at this URL:
10
 * http://opensource.org/licenses/osl-3.0.php
11
 *
12
 * PHP version 5
13
 *
14
 * @author    Bernhard Wick <[email protected]>
15
 * @copyright 2015 TechDivision GmbH - <[email protected]>
16
 * @license   http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
17
 * @link      https://github.com/appserver-io/doppelgaenger
18
 * @link      http://www.appserver.io/
19
 */
20
21
namespace AppserverIo\Doppelgaenger\StreamFilters;
22
23
/**
24
 * This filter will add given interfaces to already defined classes
25
 *
26
 * @author    Bernhard Wick <[email protected]>
27
 * @copyright 2015 TechDivision GmbH - <[email protected]>
28
 * @license   http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
29
 * @link      https://github.com/appserver-io/doppelgaenger
30
 * @link      http://www.appserver.io/
31
 */
32
class IntroductionFilter extends AbstractFilter
33
{
34
35
    /**
36
     * Order number if filters are used as a stack, higher means below others
37
     *
38
     * @const integer FILTER_ORDER
39
     */
40
    const FILTER_ORDER = 00;
41
42
    /**
43
     * The main filter method.
44
     * Implemented according to \php_user_filter class. Will loop over all stream buckets, buffer them and perform
45
     * the needed actions.
46
     *
47
     * @param resource $in       Incoming bucket brigade we need to filter
48
     * @param resource $out      Outgoing bucket brigade with already filtered content
49
     * @param integer  $consumed The count of altered characters as buckets pass the filter
50
     * @param boolean  $closing  Is the stream about to close?
51
     *
52
     * @throws \AppserverIo\Doppelgaenger\Exceptions\GeneratorException
53
     *
54
     * @return integer
55
     *
56
     * @link http://www.php.net/manual/en/php-user-filter.filter.php
57
     */
58
    public function filter($in, $out, & $consumed, $closing)
59
    {
60
        // get all the introductions of a structure definition
61
        $introductions = $this->params;
62
63
        // Get our buckets from the stream
64
        $interfaceHook = '';
65
        $keywordNeeded = true;
66
        while ($bucket = stream_bucket_make_writeable($in)) {
67
            // Has to be done only once at the beginning of the definition
68
            if (empty($interfaceHook) && $introductions->count() > 0) {
69
                // Get the tokens
70
                $tokens = token_get_all($bucket->data);
71
72
                // Go through the tokens and check what we found
73
                $tokensCount = count($tokens);
74
                for ($i = 0; $i < $tokensCount; $i++) {
75
                    // We need something to hook into, right after class header seems fine
76
                    if (is_array($tokens[$i]) && $tokens[$i][0] === T_CLASS && $tokens[$i - 1][0] !== T_PAAMAYIM_NEKUDOTAYIM) {
77
                        for ($j = $i; $j < $tokensCount; $j++) {
78
                            // If we got the opening bracket we can break
79
                            if ($tokens[$j] === '{' || $tokens[$j][0] === T_CURLY_OPEN) {
80
                                break;
81
                            }
82
83
                            if (is_array($tokens[$j])) {
84
                                // we have to check if there already are interfaces
85
                                if ($tokens[$j][0] === T_IMPLEMENTS) {
86
                                    $keywordNeeded = false;
87
                                }
88
89
                                $interfaceHook .= $tokens[$j][1];
90
0 ignored issues
show
Coding Style introduced by
Blank line found at end of control structure
Loading history...
91
                            } else {
92
                                $interfaceHook .= $tokens[$j];
93
                            }
94
                        }
95
96
                        // build up the injected code and make the injection
97
                        if ($keywordNeeded) {
98
                            $implementsCode = ' implements ';
99
0 ignored issues
show
Coding Style introduced by
Blank line found at end of control structure
Loading history...
100
                        } else {
101
                            $implementsCode = ', ';
102
                        }
103
                        $useCode = '';
104
                        $interfaces = array();
105
                        foreach ($introductions as $introduction) {
106
                            $interfaces[] = $introduction->getInterface();
107
108
                            // build up code for the trait usage
109
                            $useCode .= 'use ' . $introduction->getImplementation() . ';
110
                            ';
111
                        }
112
                        $implementsCode .= implode(', ', $interfaces);
113
114
                        // add the "use" code
115
                        $bucket->data = str_replace(
116
                            $interfaceHook . '{',
117
                            $interfaceHook . '{' . $useCode,
118
                            $bucket->data
119
                        );
120
121
                        // add the "implements" code
122
                        $bucket->data = str_replace(
123
                            $interfaceHook,
124
                            $interfaceHook . $implementsCode,
125
                            $bucket->data
126
                        );
127
                    }
128
                }
129
0 ignored issues
show
Coding Style introduced by
Blank line found at end of control structure
Loading history...
130
            }
131
132
            // Tell them how much we already processed, and stuff it back into the output
133
            $consumed += $bucket->datalen;
134
            stream_bucket_append($out, $bucket);
135
        }
136
137
        return PSFS_PASS_ON;
138
    }
139
140
    /**
141
     * Will filter the given params and create a clean array of interface names from them
142
     *
143
     * @return array
144
     */
145
    protected function filterParams()
146
    {
147
        $interfaces = array();
148
149
        // filter the params
150
        if (is_array($this->params)) {
151
            $interfaces = $this->params;
152
0 ignored issues
show
Coding Style introduced by
Blank line found at end of control structure
Loading history...
153
        } else {
154
            $interfaces[] = $this->params;
155
        }
156
157
        // filter out everything which might not be right
158
        foreach ($interfaces as $key => $interfaceCandidate) {
159
            if (!is_string($interfaceCandidate)) {
160
                unset($interfaces[$key]);
161
            }
162
        }
163
164
        return $interfaces;
165
    }
166
}
167