Complex classes like RFA often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.
Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.
While breaking up the class, it is a good idea to analyze how other classes use RFA, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
24 | class RFA { |
||
25 | |||
26 | protected $pgUsername = false; |
||
27 | protected $enddate = false; |
||
28 | protected $support = array(); |
||
29 | protected $oppose = array(); |
||
30 | protected $neutral = array(); |
||
31 | protected $duplicates = array(); |
||
32 | protected $lasterror = ''; |
||
33 | |||
34 | /** |
||
35 | * Analyzes an RFA. Returns TRUE on success, FALSE on failure |
||
36 | * @param Wiki $wiki |
||
37 | * @param $page |
||
38 | * @param null $rawwikitext |
||
39 | */ |
||
40 | public function __construct( Wiki $wiki, $page, $rawwikitext = null ) { |
||
41 | if( is_null( $rawwikitext ) ) $rawwikitext = $wiki->initPage( $page )->get_text(); |
||
42 | |||
43 | $split = preg_split( |
||
44 | "/^(?:(?:'''|(?:<includeonly><noin<\/includeonly><includeonly>clude><\/includeonly>)?={4,5}(?:<includeonly><\/noin<\/includeonly><includeonly>clude><\/includeonly>''')?)" |
||
45 | . "\s*?(Support|Oppose|Neutral|Comments)\s*?(?:'''|(?:'''<includeonly><noin<\/includeonly><includeonly>clude><\/includeonly>)?={4,5}(?:<includeonly><\/noin<\/includeonly><includeonly>clude><\/includeonly>)?)|;\s*(Support|Oppose|Neutral|Comments))\s*(?:<br>|<br \/>)?\s*$/im" |
||
46 | , $rawwikitext, -1, PREG_SPLIT_DELIM_CAPTURE |
||
47 | ); |
||
48 | |||
49 | $header = array_shift( $split ); |
||
50 | |||
51 | //=== Deal with the header ===// |
||
52 | $header = str_ireplace( array( '<nowiki>', '</nowiki>' ), '', $header ); |
||
53 | |||
54 | if( preg_match( "/===\s*\[\[User:(.*?)\|.*?\]\]\s*===/", $header, $matches ) ) { |
||
55 | $this->username = $matches[1]; |
||
|
|||
56 | } elseif( preg_match( "/===\s*\[\[.*?\|(.*?)\]\]\s*===/", $header, $matches ) ) { |
||
57 | $this->username = $matches[1]; |
||
58 | } |
||
59 | |||
60 | $header = str_replace( array( '[[', ']]' ), '', $header ); |
||
61 | |||
62 | if( preg_match( "/end(?:ing|ed)?(?: no earlier than)? (.*?) \(UTC\)/i", $header, $matches ) ) { |
||
63 | $this->enddate = $matches[1]; |
||
64 | } |
||
65 | //=== End header stuff ===// |
||
66 | |||
67 | //Now parse through each non-header section, figuring out what they are |
||
68 | //Nothing expected = 0, Support = 1, Oppose = 2, Neutral = 3 |
||
69 | $nextsection = 0; |
||
70 | |||
71 | foreach( $split as $splut ){ |
||
72 | $splut = trim( $splut ); |
||
73 | if( empty( $splut ) ) { |
||
74 | continue; |
||
75 | } |
||
76 | |||
77 | if( strcasecmp( $splut, 'Support' ) == 0 ) { |
||
78 | $nextsection = 1; |
||
79 | } elseif( strcasecmp( $splut, 'Oppose' ) == 0 ) { |
||
80 | $nextsection = 2; |
||
81 | } elseif( strcasecmp( $splut, 'Neutral' ) == 0 ) { |
||
82 | $nextsection = 3; |
||
83 | } else { |
||
84 | switch( $nextsection ){ |
||
85 | case 1: |
||
86 | $support = $splut; |
||
87 | break; |
||
88 | case 2: |
||
89 | $oppose = $splut; |
||
90 | break; |
||
91 | case 3: |
||
92 | $neutral = $splut; |
||
93 | break; |
||
94 | } |
||
95 | $nextsection = 0; |
||
96 | } |
||
97 | } |
||
98 | |||
99 | if( !isset( $support ) ) { |
||
100 | $this->lasterror = "Support section not found"; |
||
101 | return false; |
||
102 | } |
||
103 | if( !isset( $oppose ) ) { |
||
104 | $this->lasterror = "Oppose section not found"; |
||
105 | return false; |
||
106 | } |
||
107 | if( !isset( $neutral ) ) { |
||
108 | $this->lasterror = "Neutral section not found"; |
||
109 | return false; |
||
110 | } |
||
111 | |||
112 | $this->support = $this->analyzeSection( $support ); |
||
113 | $this->oppose = $this->analyzeSection( $oppose ); |
||
114 | $this->neutral = $this->analyzeSection( $neutral ); |
||
115 | |||
116 | //Merge all votes in one array and sort: |
||
117 | $m = array(); |
||
118 | foreach( $this->support as $s ){ |
||
119 | if( isset( $s['name'] ) ) $m[] = $s['name']; |
||
120 | } |
||
121 | foreach( $this->oppose as $o ){ |
||
122 | if( isset( $o['name'] ) ) $m[] = $o['name']; |
||
123 | } |
||
124 | foreach( $this->neutral as $n ){ |
||
125 | if( isset( $n['name'] ) ) $m[] = $n['name']; |
||
126 | } |
||
127 | sort( $m ); |
||
128 | //Find duplicates: |
||
129 | for( $i = 0; $i < count( $m ); $i++ ){ |
||
130 | if( $i != count( $m ) - 1 ) { |
||
131 | if( $m[$i] == $m[$i + 1] ) { |
||
132 | $this->duplicates[] = $m[$i]; |
||
133 | } |
||
134 | } |
||
135 | } |
||
136 | |||
137 | return true; |
||
138 | } |
||
139 | |||
140 | public function get_username() { |
||
141 | return $this->username; |
||
142 | } |
||
143 | |||
144 | public function get_enddate() { |
||
145 | return $this->enddate; |
||
146 | } |
||
147 | |||
148 | public function get_support() { |
||
149 | return $this->support; |
||
150 | } |
||
151 | |||
152 | public function get_oppose() { |
||
153 | return $this->oppose; |
||
154 | } |
||
155 | |||
156 | public function get_neutral() { |
||
157 | return $this->neutral; |
||
158 | } |
||
159 | |||
160 | public function get_duplicates() { |
||
161 | return $this->duplicates; |
||
162 | } |
||
163 | |||
164 | public function get_lasterror() { |
||
165 | return $this->lasterror; |
||
166 | } |
||
167 | |||
168 | /** |
||
169 | * Attempts to find a signature in $input using the default regex. Returns matches. |
||
170 | * @param $input |
||
171 | * @param $matches |
||
172 | * |
||
173 | * @return int |
||
174 | */ |
||
175 | protected function findSig( $input, &$matches ) { |
||
186 | |||
187 | /** |
||
188 | * Attempts to find a signature in $input using a different regex. Returns matches. |
||
189 | * @param $input |
||
190 | * @param $matches |
||
191 | * |
||
192 | * @return int |
||
193 | */ |
||
194 | protected function findSigAlt( $input, &$matches ) { |
||
201 | |||
202 | /** |
||
203 | * Attempts to find a signature in $input. Returns the name of the user, false on failure. |
||
204 | * @param $input |
||
205 | * @param $iffy |
||
206 | * |
||
207 | * @return bool|string false if not found Signature, or the Signature if it is found |
||
208 | */ |
||
209 | protected function findSigInLine( $input, &$iffy ) { |
||
283 | |||
284 | /** |
||
285 | * Analyzes an RFA section. Returns an array of parsed signatures on success. Undefined behaviour on failure. |
||
286 | * @param string $input |
||
287 | * |
||
288 | * @return array |
||
289 | */ |
||
290 | private function analyzeSection( $input ) { |
||
337 | |||
338 | } |
||
339 |
An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.
If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.