These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
1 | <?php |
||
2 | |||
3 | use SMW\DataValues\UnitConversionFetcher; |
||
4 | use SMW\Message; |
||
5 | use SMW\ApplicationFactory; |
||
6 | |||
7 | /** |
||
8 | * @ingroup SMWDataValues |
||
9 | */ |
||
10 | |||
11 | /** |
||
12 | * This datavalue implements unit support custom units, for which users have |
||
13 | * provided linear conversion factors within the wiki. Those user settings |
||
14 | * are retrieved from a property page associated with this object. |
||
15 | * |
||
16 | * @author Markus Krötzsch |
||
17 | * @ingroup SMWDataValues |
||
18 | */ |
||
19 | class SMWQuantityValue extends SMWNumberValue { |
||
20 | |||
21 | /** |
||
22 | * Array with format (canonical unit ID string) => (conversion factor) |
||
23 | * @var float[]|bool |
||
24 | */ |
||
25 | protected $m_unitfactors = false; |
||
26 | |||
27 | /** |
||
28 | * Array with format (normalised unit string) => (canonical unit ID string) |
||
29 | * @var string[]|bool |
||
30 | */ |
||
31 | protected $m_unitids = false; |
||
32 | |||
33 | /** |
||
34 | * Ordered array of (normalized) units that should be displayed in tooltips, etc. |
||
35 | * @var string[]|bool |
||
36 | */ |
||
37 | protected $m_displayunits = false; |
||
38 | |||
39 | /** |
||
40 | * Main unit in canonical form (recognised by the conversion factor 1) |
||
41 | * @var string|bool |
||
42 | */ |
||
43 | protected $m_mainunit = false; |
||
44 | |||
45 | 22 | protected function convertToMainUnit( $number, $unit ) { |
|
46 | 22 | $this->initConversionData(); |
|
47 | |||
48 | 22 | if ( array_key_exists( $unit, $this->m_unitids ) ) { |
|
49 | 21 | $this->m_unitin = $this->m_unitids[$unit]; |
|
50 | 21 | assert( $this->m_unitfactors[$this->m_unitin] != 0 /* Should be filtered by initConversionData() */ ); |
|
51 | 21 | $this->m_dataitem = new SMWDINumber( $number / $this->m_unitfactors[$this->m_unitin], $this->m_typeid ); |
|
52 | 21 | return true; |
|
53 | } else { // unsupported unit |
||
54 | 7 | return false; |
|
55 | } |
||
56 | } |
||
57 | |||
58 | 13 | protected function makeConversionValues() { |
|
59 | 13 | if ( $this->m_unitvalues !== false ) { |
|
60 | return; // do this only once |
||
61 | } |
||
62 | |||
63 | 13 | $this->m_unitvalues = array(); |
|
64 | |||
65 | 13 | if ( !$this->isValid() ) { |
|
66 | return; |
||
67 | } |
||
68 | |||
69 | 13 | $this->initDisplayData(); |
|
70 | |||
71 | 13 | if ( count( $this->m_displayunits ) == 0 ) { // no display units, just show all |
|
72 | 11 | foreach ( $this->m_unitfactors as $unit => $factor ) { |
|
0 ignored issues
–
show
|
|||
73 | 11 | if ( $unit !== '' ) { // filter out the empty fallback unit that is always there |
|
74 | 11 | $this->m_unitvalues[$unit] = $this->m_dataitem->getNumber() * $factor; |
|
75 | } |
||
76 | } |
||
77 | } else { |
||
78 | 3 | foreach ( $this->m_displayunits as $unit ) { |
|
79 | /// NOTE We keep non-ID units unless the input unit is used, so display units can be used to pick |
||
80 | /// the preferred form of a unit. Doing this requires us to recompute the conversion values whenever |
||
81 | /// the m_unitin changes. |
||
82 | 3 | $unitkey = ( $this->m_unitids[$unit] == $this->m_unitin ) ? $this->m_unitids[$unit] : $unit; |
|
83 | 3 | $this->m_unitvalues[$unitkey] = $this->m_dataitem->getNumber() * $this->m_unitfactors[$this->m_unitids[$unit]]; |
|
84 | } |
||
85 | } |
||
86 | 13 | } |
|
87 | |||
88 | 8 | protected function makeUserValue() { |
|
89 | 8 | $printunit = false; // the normalised string of a known unit to use for printouts |
|
90 | |||
91 | // Check if a known unit is given as outputformat: |
||
92 | 8 | if ( ( $this->m_outformat ) && ( $this->m_outformat != '-' ) && |
|
93 | 8 | ( $this->m_outformat != '-n' ) && ( $this->m_outformat != '-u' ) ) { // first try given output unit |
|
94 | 2 | $wantedunit = $this->normalizeUnit( $this->m_outformat ); |
|
95 | 2 | if ( array_key_exists( $wantedunit, $this->m_unitids ) ) { |
|
96 | 2 | $printunit = $wantedunit; |
|
97 | } |
||
98 | } |
||
99 | |||
100 | // Alternatively, try to use the main display unit as a default: |
||
101 | 8 | if ( $printunit === false ) { |
|
102 | 8 | $this->initDisplayData(); |
|
103 | 8 | if ( count( $this->m_displayunits ) > 0 ) { |
|
104 | 3 | $printunit = reset( $this->m_displayunits ); |
|
105 | } |
||
106 | } |
||
107 | // Finally, fall back to main unit: |
||
108 | 8 | if ( $printunit === false ) { |
|
109 | 6 | $printunit = $this->getUnit(); |
|
110 | } |
||
111 | |||
112 | 8 | $asPrefix = isset( $this->prefixalUnitPreference[$printunit] ) && $this->prefixalUnitPreference[$printunit]; |
|
113 | |||
114 | 8 | $this->m_unitin = $this->m_unitids[$printunit]; |
|
115 | 8 | $this->m_unitvalues = false; // this array depends on m_unitin if displayunits were used, better invalidate it here |
|
116 | |||
117 | 8 | $value = $this->m_dataitem->getNumber() * $this->m_unitfactors[$this->m_unitin]; |
|
118 | |||
119 | 8 | $this->m_caption = ''; |
|
120 | |||
121 | 8 | if ( $this->m_outformat != '-u' ) { // -u is the format for displaying the unit only |
|
122 | 8 | $this->m_caption .= ( ( $this->m_outformat != '-' ) && ( $this->m_outformat != '-n' ) ? $this->getLocalizedFormattedNumber( $value ) : $this->getNormalizedFormattedNumber( $value ) ); |
|
123 | } |
||
124 | |||
125 | 8 | if ( ( $printunit !== '' ) && ( $this->m_outformat != '-n' ) ) { // -n is the format for displaying the number only |
|
126 | |||
127 | 8 | $sep = ''; |
|
128 | |||
129 | 8 | if ( $this->m_outformat != '-u' ) { |
|
130 | 8 | $sep = ( $this->m_outformat != '-' ? ' ' : ' ' ); |
|
131 | } |
||
132 | |||
133 | 8 | $this->m_caption = $asPrefix ? $printunit . $sep . $this->m_caption : $this->m_caption . $sep . $printunit; |
|
134 | } |
||
135 | 8 | } |
|
136 | |||
137 | public function getUnitList() { |
||
138 | $this->initConversionData(); |
||
139 | return array_keys( $this->m_unitfactors ); |
||
140 | } |
||
141 | |||
142 | 7 | public function getUnit() { |
|
143 | 7 | $this->initConversionData(); |
|
144 | 7 | return $this->m_mainunit; |
|
145 | } |
||
146 | |||
147 | /// The remaining functions are relatively "private" but are kept protected since |
||
148 | /// subclasses might exploit this to, e.g., "fake" conversion factors instead of |
||
149 | /// getting them from the database. A cheap way of making built-in types. |
||
150 | |||
151 | /** |
||
152 | * This method initializes $m_unitfactors, $m_unitids, and $m_mainunit. |
||
153 | */ |
||
154 | 22 | protected function initConversionData() { |
|
155 | 22 | if ( $this->m_unitids !== false ) { |
|
156 | 14 | return; // do the below only once |
|
157 | } |
||
158 | |||
159 | 22 | $unitConversionFetcher = new UnitConversionFetcher( $this ); |
|
160 | 22 | $unitConversionFetcher->fetchCachedConversionData( $this->m_property ); |
|
161 | |||
162 | 22 | if ( $unitConversionFetcher->getErrors() !== array() ) { |
|
163 | 7 | foreach ( $unitConversionFetcher->getErrors() as $error ) { |
|
164 | 7 | $this->addErrorMsg( |
|
165 | $error, |
||
166 | 7 | Message::TEXT, |
|
167 | 7 | Message::USER_LANGUAGE |
|
168 | ); |
||
169 | } |
||
170 | } |
||
171 | |||
172 | 22 | $this->m_unitids = $unitConversionFetcher->getUnitIds(); |
|
173 | 22 | $this->m_unitfactors = $unitConversionFetcher->getUnitFactors(); |
|
174 | 22 | $this->m_mainunit = $unitConversionFetcher->getMainUnit(); |
|
175 | 22 | $this->prefixalUnitPreference = $unitConversionFetcher->getPrefixalUnitPreference(); |
|
176 | 22 | } |
|
177 | |||
178 | /** |
||
179 | * This method initializes $m_displayunits. |
||
180 | */ |
||
181 | 14 | protected function initDisplayData() { |
|
182 | 14 | if ( $this->m_displayunits !== false ) { |
|
183 | 6 | return; // do the below only once |
|
184 | } |
||
185 | 14 | $this->initConversionData(); // needed to normalise unit strings |
|
186 | 14 | $this->m_displayunits = array(); |
|
187 | |||
188 | 14 | if ( is_null( $this->m_property ) || is_null( $this->m_property->getDIWikiPage() ) ) { |
|
189 | return; |
||
190 | } |
||
191 | |||
192 | 14 | $units = ApplicationFactory::getInstance()->getPropertySpecificationLookup()->getDisplayUnitsBy( |
|
193 | 14 | $this->getProperty() |
|
194 | ); |
||
195 | |||
196 | 14 | foreach ( $units as $unit ) { |
|
197 | 4 | $unit = $this->normalizeUnit( $unit ); |
|
198 | 4 | if ( array_key_exists( $unit, $this->m_unitids ) ) { |
|
199 | 4 | $this->m_displayunits[] = $unit; // do not avoid duplicates, users can handle this |
|
200 | } // note: we ignore unsuppported units -- no way to display them |
||
201 | } |
||
202 | 14 | } |
|
203 | } |
||
204 |
There are different options of fixing this problem.
If you want to be on the safe side, you can add an additional type-check:
If you are sure that the expression is traversable, you might want to add a doc comment cast to improve IDE auto-completion and static analysis:
Mark the issue as a false-positive: Just hover the remove button, in the top-right corner of this issue for more options.