Complex classes like SRFArray 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 SRFArray, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
17 | class SRFArray extends SMWResultPrinter { |
||
18 | |||
19 | protected static $mDefaultSeps = array(); |
||
20 | protected $mSep; |
||
21 | protected $mPropSep; |
||
22 | protected $mManySep; |
||
23 | protected $mRecordSep; |
||
24 | protected $mHeaderSep; |
||
25 | protected $mArrayName = null; |
||
26 | protected $mShowPageTitles; |
||
27 | |||
28 | protected $mHideRecordGaps; |
||
29 | protected $mHidePropertyGaps; |
||
30 | |||
31 | /** |
||
32 | * @var Boolean true if 'mainlabel' parameter is set to '-' |
||
33 | */ |
||
34 | protected $mMainLabelHack = false; |
||
35 | |||
36 | public function __construct( $format, $inline = true, $useValidator = true ) { |
||
37 | parent::__construct( $format, $inline, $useValidator ); |
||
38 | //overwrite parent default behavior for linking: |
||
39 | $this->mLinkFirst = false; |
||
40 | $this->mLinkOthers = false; |
||
41 | } |
||
42 | |||
43 | public function getQueryMode($context) { |
||
46 | |||
47 | public function getName() { |
||
48 | // Give grep a chance to find the usages: |
||
49 | // srf_printername_array, srf_printername_hash |
||
50 | return wfMessage( 'srf_printername_' . $this->mFormat )->text(); |
||
51 | } |
||
52 | |||
53 | /* |
||
54 | // By overwriting this function, we disable default searchlabel handling? |
||
55 | public function getResult( SMWQueryResult $results, array $params, $outputmode ) { |
||
56 | $this->handleParameters( $params, $outputmode ); |
||
57 | return $this->getResultText( $results, $outputmode ); |
||
58 | } |
||
59 | */ |
||
60 | |||
61 | protected function getResultText( SMWQueryResult $res, $outputmode ) { |
||
62 | /* |
||
63 | * @todo |
||
64 | * labels of requested properties could define default values. Seems not possible at the moment because |
||
65 | * SMWPrintRequest::getLable() always returns the property name even if no specific label is defined. |
||
66 | */ |
||
67 | |||
68 | $perPage_items = array(); |
||
69 | |||
70 | //for each page: |
||
71 | while( $row = $res->getNext() ) { |
||
72 | $perProperty_items = array(); |
||
73 | |||
74 | /** |
||
75 | * first field is always the page title, except, mainlabel is set to '-' |
||
76 | * @todo Is there some other way to check the data value directly for being the |
||
77 | * page title or not? SMWs behavior could change on mainlabel handling... |
||
78 | */ |
||
79 | $isPageTitle = !$this->mMainLabelHack; |
||
80 | |||
81 | //for each property on that page: |
||
82 | foreach( $row as $field ) { // $row is array(), $field of type SMWResultArray |
||
83 | $manyValue_items = array(); |
||
84 | $isMissingProperty = false; |
||
85 | |||
86 | $manyValues = $field->getContent(); |
||
87 | |||
88 | //If property is not set (has no value) on a page: |
||
89 | if( empty( $manyValues ) ) { |
||
90 | $delivery = $this->deliverMissingProperty( $field ); |
||
91 | $manyValue_items = $this->fillDeliveryArray( $manyValue_items, $delivery ); |
||
92 | $isMissingProperty = true; |
||
93 | } else |
||
94 | //otherwise collect property value (potentially many values): |
||
95 | while( $obj = $field->getNextDataValue() ) { |
||
96 | |||
97 | $value_items = array(); |
||
98 | $isRecord = false; |
||
99 | |||
100 | // handle page Title: |
||
101 | if( $isPageTitle ) { |
||
102 | if( ! $this->mShowPageTitles ) { |
||
103 | $isPageTitle = false; |
||
104 | continue 2; //next property |
||
105 | } |
||
106 | $value_items = $this->fillDeliveryArray( $value_items, $this->deliverPageTitle( $obj, $this->mLinkFirst ) ); |
||
107 | } |
||
108 | // handle record values: |
||
109 | elseif( $obj instanceof SMWRecordValue ) { |
||
110 | $recordItems = $obj->getDataItems(); |
||
111 | // walk all single values of the record set: |
||
112 | foreach( $recordItems as $dataItem ) { |
||
113 | $recordField = $dataItem !== null ? SMWDataValueFactory::newDataItemValue( $dataItem, null ) : null; |
||
114 | $value_items = $this->fillDeliveryArray( $value_items, $this->deliverRecordField( $recordField, $this->mLinkOthers ) ); |
||
115 | } |
||
116 | $isRecord = true; |
||
117 | } |
||
118 | // handle normal data values: |
||
119 | else { |
||
120 | $value_items = $this->fillDeliveryArray( $value_items, $this->deliverSingleValue( $obj, $this->mLinkOthers ) ); |
||
121 | } |
||
122 | $delivery = $this->deliverSingleManyValuesData( $value_items, $isRecord, $isPageTitle ); |
||
123 | $manyValue_items = $this->fillDeliveryArray( $manyValue_items, $delivery ); |
||
124 | } // foreach... |
||
125 | $delivery = $this->deliverPropertiesManyValues( $manyValue_items, $isMissingProperty, $isPageTitle, $field ); |
||
126 | $perProperty_items = $this->fillDeliveryArray( $perProperty_items, $delivery ); |
||
127 | $isPageTitle = false; // next one could be record or normal value |
||
128 | } // foreach... |
||
129 | $delivery = $this->deliverPageProperties( $perProperty_items ); |
||
130 | $perPage_items = $this->fillDeliveryArray( $perPage_items, $delivery ); |
||
131 | } // while... |
||
132 | |||
133 | $output = $this->deliverQueryResultPages( $perPage_items ); |
||
134 | |||
135 | return $output; |
||
136 | } |
||
137 | |||
138 | protected function fillDeliveryArray( $array = array(), $value = null ) { |
||
139 | if( ! is_null( $value ) ) { //don't create any empty entries |
||
140 | $array[] = $value; |
||
141 | } |
||
142 | return $array; |
||
143 | } |
||
144 | |||
145 | protected function deliverPageTitle( $value, $link = false ) { |
||
148 | protected function deliverRecordField( $value, $link = false ) { |
||
149 | if( $value !== null ) // contains value |
||
150 | return $this->deliverSingleValue( $value, $link ); |
||
151 | elseif( $this->mHideRecordGaps ) |
||
152 | return null; // hide gap |
||
153 | else |
||
154 | return ''; // empty string will make sure that record value separators are generated |
||
155 | } |
||
156 | protected function deliverSingleValue( $value, $link = false ) { |
||
160 | // Property not declared on a page: |
||
161 | protected function deliverMissingProperty( SMWResultArray $field ) { |
||
162 | if( $this->mHidePropertyGaps ) |
||
163 | return null; |
||
164 | else |
||
165 | return ''; //empty string will make sure that array separator will be generated |
||
168 | //represented by an array of record fields or just a single array value: |
||
169 | protected function deliverSingleManyValuesData( $value_items, $containsRecord, $isPageTitle ) { |
||
200 | |||
201 | /** |
||
202 | * Helper function to create a new Array within 'Arrays' extension. Takes care of different versions |
||
203 | * as well as the old 'ArrayExtension'. |
||
204 | */ |
||
205 | protected function createArray( $array ) { |
||
238 | |||
239 | protected function initializeCfgValue( $dfltVal, $dfltCacheKey ) { |
||
303 | |||
304 | protected function handleParameters( array $params, $outputmode ) { |
||
347 | |||
348 | /** |
||
349 | * @see SMWResultPrinter::getParamDefinitions |
||
350 | * |
||
351 | * @since 1.8 |
||
352 | * |
||
353 | * @param $definitions array of IParamDefinition |
||
354 | * |
||
355 | * @return array of IParamDefinition|array |
||
356 | */ |
||
357 | public function getParamDefinitions( array $definitions ) { |
||
419 | |||
420 | } |
||
421 | |||
424 |
This error could be the result of:
1. Missing dependencies
PHP Analyzer uses your
composer.json
file (if available) to determine the dependencies of your project and to determine all the available classes and functions. It expects thecomposer.json
to be in the root folder of your repository.Are you sure this class is defined by one of your dependencies, or did you maybe not list a dependency in either the
require
orrequire-dev
section?2. Missing use statement
PHP does not complain about undefined classes in
ìnstanceof
checks. For example, the following PHP code will work perfectly fine:If you have not tested against this specific condition, such errors might go unnoticed.