Completed
Push — rmuc ( 126621 )
by Jeroen De
121:49 queued 119:33
created

SRFTimeline::getName()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
dl 0
loc 5
ccs 0
cts 2
cp 0
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 0
crap 2
1
<?php
2
/**
3
 * Print query results in interactive timelines.
4
 *
5
 * @file SRF_Timeline.php
6
 * @ingroup SemanticResultFormats
7
 *
8
 * @author Markus Krötzsch
9
 *
10
 * FIXME: this code is just insane; rewrite from 0 is probably the only way to get it right
11
 */
12
13
/**
14
 * Result printer for timeline data.
15
 * @ingroup SemanticResultFormats
16
 */
17
class SRFTimeline extends SMWResultPrinter {
18
19
	protected $m_tlstart = '';  // name of the start-date property if any
20
	protected $m_tlend = '';  // name of the end-date property if any
21
	protected $m_tlsize = ''; // CSS-compatible size (such as 400px)
22
	protected $m_tlbands = ''; // array of band IDs (MONTH, YEAR, ...)
23
	protected $m_tlpos = ''; // position identifier (start, end, today, middle)
24
	protected $mTemplate;
25
	protected $mNamedArgs;
26
27
	/**
28
	 * @see SMWResultPrinter::handleParameters
29
	 *
30
	 * @since 1.6.3
31
	 *
32
	 * @param array $params
33
	 * @param $outputmode
34
	 */
35 1
	protected function handleParameters( array $params, $outputmode ) {
36 1
		parent::handleParameters( $params, $outputmode );
37
38 1
		$this->mTemplate = trim( $params['template'] );
39 1
		$this->mNamedArgs = $params['named args'];
40 1
		$this->m_tlstart = smwfNormalTitleDBKey( $params['timelinestart'] );
41 1
		$this->m_tlend = smwfNormalTitleDBKey( $params['timelineend'] );
42 1
		$this->m_tlbands = $params['timelinebands'];
43 1
		$this->m_tlpos = strtolower( trim( $params['timelineposition'] ) );
44
45
			// str_replace makes sure this is only one value, not mutliple CSS fields (prevent CSS attacks)
46
			// / FIXME: this is either unsafe or redundant, since Timeline is Wiki-compatible. If the JavaScript makes user inputs to CSS then it is bad even if we block this injection path.
47 1
		$this->m_tlsize = htmlspecialchars( str_replace( ';', ' ', strtolower( $params['timelinesize'] ) ) );
48 1
	}
49
50
	public function getName() {
51
		// Give grep a chance to find the usages:
52
		// srf_printername_timeline, srf_printername_eventline
53
		return wfMessage( 'srf_printername_' . $this->mFormat )->text();
54
	}
55
56 1
	protected function getResultText( SMWQueryResult $res, $outputmode ) {
57
58 1
		SMWOutputs::requireHeadItem( SMW_HEADER_STYLE );
59 1
		SMWOutputs::requireResource( 'ext.srf.timeline' );
60
61 1
		$isEventline = 'eventline' == $this->mFormat;
62 1
		$id = uniqid();
63
64 1
		if ( !$isEventline && ( $this->m_tlstart == '' ) ) { // seek defaults
65 1
			foreach ( $res->getPrintRequests() as $pr ) {
66 1
				if ( ( $pr->getMode() == SMWPrintRequest::PRINT_PROP ) && ( $pr->getTypeID() == '_dat' ) ) {
67 1
					$dataValue = $pr->getData();
68
69 1
					$date_value = $dataValue->getDataItem()->getLabel();
70
71 1
					if ( ( $this->m_tlend == '' ) && ( $this->m_tlstart != '' ) &&
72 1
					     ( $this->m_tlstart != $date_value ) ) {
73
						$this->m_tlend = $date_value;
74 1
					} elseif ( ( $this->m_tlstart == '' ) && ( $this->m_tlend != $date_value ) ) {
75 1
						$this->m_tlstart = $date_value;
76
					}
77
				}
78
			}
79
		}
80
81
		// print header
82 1
		$result = "<div id=\"smwtimeline-$id\" class=\"smwtimeline is-disabled\" style=\"height: $this->m_tlsize\">";
83 1
		$result .= '<span class="smw-overlay-spinner medium" style="top:40%; transform: translate(-50%, -50%);"></span>';
84
85 1
		foreach ( $this->m_tlbands as $band ) {
0 ignored issues
show
Bug introduced by
The expression $this->m_tlbands of type string is not traversable.
Loading history...
86 1
			$result .= '<span class="smwtlband" style="display:none;">' . htmlspecialchars( $band ) . '</span>';
87
			// just print any "band" given, the JavaScript will figure out what to make of it
88
		}
89
90
		// print all result rows
91 1
		if ( ( $this->m_tlstart != '' ) || $isEventline ) {
92 1
			$result .= $this->getEventsHTML( $res, $outputmode, $isEventline );
93
		}
94
		// no further results displayed ...
95
96
		// print footer
97 1
		$result .= '</div>';
98
99
		// yes, our code can be viewed as HTML if requested, no more parsing needed
100 1
		$this->isHTML = $outputmode == SMW_OUTPUT_HTML;
101
102 1
		return $result;
103
	}
104
105
	/**
106
	 * Returns the HTML for the events.
107
	 *
108
	 * @since 1.5.3
109
	 *
110
	 * @param SMWQueryResult $res
111
	 * @param $outputmode
112
	 * @param boolean $isEventline
113
	 *
114
	 * @return string
115
	 */
116 1
	protected function getEventsHTML( SMWQueryResult $res, $outputmode, $isEventline ) {
117 1
		global $curarticle, $cururl; // why not, code flow has reached max insanity already
118
119 1
		$positions = []; // possible positions, collected to select one for centering
120 1
		$curcolor = 0; // color cycling is used for eventline
121
122 1
		$result = '';
123
124 1
		$output = false; // true if output for the popup was given on current line
125 1
		if ( $isEventline ) $events = []; // array of events that are to be printed
126
127 1
		while ( $row = $res->getNext() ) { // Loop over the objcts (pages)
128 1
			$hastime = false; // true as soon as some startdate value was found
129 1
			$hastitle = false; // true as soon as some label for the event was found
130 1
			$curdata = ''; // current *inner* print data (within some event span)
131 1
			$curmeta = ''; // current event meta data
132 1
			$cururl = '';
133 1
			$curarticle = ''; // label of current article, if it was found; needed only for eventline labeling
134 1
			$first_col = true;
135
136 1
			if ( $this->mTemplate != '' ) {
137
				$this->hasTemplates = true;
138
				$template_text = '';
139
				$i = 0;
140
			}
141
142 1
			foreach ( $row as $field ) { // Loop over the returned properties
143 1
				$first_value = true;
144 1
				$pr = $field->getPrintRequest();
145 1
				$dataValue = $pr->getData();
146
147 1
				if ( $dataValue == '' ) {
148 1
					$date_value = null;
149
				}
150
				else {
151 1
					$date_value = $dataValue->getDataItem()->getLabel();
152
				}
153
154 1
				while ( ( $object = $field->getNextDataValue() ) !== false ) { // Loop over property values
155 1
					$event = $this->handlePropertyValue(
156 1
						$object, $outputmode, $pr, $first_col, $hastitle, $hastime,
157 1
						$first_value, $isEventline, $curmeta, $curdata, $date_value, $output, $positions
158
					);
159
160 1
					if ( $this->mTemplate != '')
161
					{
162
						$template_text .= '|' . ( $this->mNamedArgs ? '?' . $field->getPrintRequest()->getLabel() : $i + 1 ) . '=';
0 ignored issues
show
Bug introduced by
The variable $template_text does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
Bug introduced by
The variable $i does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
163
						if ( !$first_value ) {
164
							$template_text .= ', ';
165
						}
166
						$template_text .= $object->getShortText( SMW_OUTPUT_WIKI, $this->getLinker( $first_value ) );
167
						$i++;
168
					}
169
170 1
					if ( $event !== false ) {
171
						$events[] = $event;
0 ignored issues
show
Bug introduced by
The variable $events does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
172
					}
173
174 1
					$first_value = false;
175
				}
176
177 1
				if ( $output ) {
178 1
					$curdata .= '<br />';
179
				}
180
181 1
				$output = false;
182 1
				$first_col = false;
183
			}
184
185 1
			if ( $this->mTemplate != '')
186
			{
187
				$curdata = '{{' . $this->mTemplate . $template_text . '}}';
188
			}
189
190 1
			if ( $hastime ) {
191 1
				$result .= Html::rawElement(
192 1
					'span',
193 1
					[ 'class' => 'smwtlevent', 'style' => 'display:none;' ],
194 1
					$curmeta . Html::element(
195 1
						'span',
196 1
						[ 'class' => 'smwtlcoloricon' ],
197 1
						$curcolor
198 1
					) . $curdata
199
				);
200
			}
201
202 1
			if ( $isEventline ) {
203
				foreach ( $events as $event ) {
204
					$result .= '<span class="smwtlevent" style="display:none;" ><span class="smwtlstart">' . $event[0] . '</span><span class="smwtlurl">' . $curarticle . '</span><span class="smwtlcoloricon">' . $curcolor . '</span>';
205
					if ( $curarticle != '' ) $result .= '<span class="smwtlprefix">' . $curarticle . ' </span>';
206
					$result .=  $curdata . '</span>';
207
					$positions[$event[2]] = $event[0];
208
				}
209
				$events = [];
210
				$curcolor = ( $curcolor + 1 ) % 10;
211
			}
212
		}
213
214 1
		if ( count( $positions ) > 0 ) {
215 1
			ksort( $positions );
216 1
			$positions = array_values( $positions );
217
218 1
			switch ( $this->m_tlpos ) {
219 1
				case 'start':
220
					$result .= '<span class="smwtlposition" style="display:none;" >' . $positions[0] . '</span>';
221
					break;
222 1
				case 'end':
223
					$result .= '<span class="smwtlposition" style="display:none;" >' . $positions[count( $positions ) - 1] . '</span>';
224
					break;
225 1
				case 'today': break; // default
226 1
				case 'middle': default:
227 1
					$result .= '<span class="smwtlposition" style="display:none;" >' . $positions[ceil( count( $positions ) / 2 ) - 1] . '</span>';
228 1
					break;
229
			}
230
		}
231
232 1
		return $result;
233
	}
234
235
	/**
236
	 * Hanldes a single property value. Returns an array with data for a single event or false.
237
	 *
238
	 * FIXME: 13 arguments, of which a whole bunch are byref... not a good design :)
239
	 *
240
	 * @since 1.5.3
241
	 *
242
	 * @param SMWDataValue $object
243
	 * @param $outputmode
244
	 * @param SMWPrintRequest $pr
245
	 * @param boolean $first_col
246
	 * @param boolean &$hastitle
247
	 * @param boolean &$hastime
248
	 * @param boolean $first_value
249
	 * @param boolean $isEventline
250
	 * @param string &$curmeta
251
	 * @param string &$curdata
252
	 * @param &$date_value
253
	 * @param boolean &$output
254
	 * @param array &$positions
255
	 *
256
	 * @return false or array
257
	 */
258 1
	protected function handlePropertyValue( SMWDataValue $object, $outputmode, SMWPrintRequest $pr, $first_col,
259
		&$hastitle, &$hastime, $first_value, $isEventline, &$curmeta, &$curdata, $date_value, &$output, array &$positions ) {
260 1
			global $curarticle, $cururl;
261
262 1
		$event = false;
263
264 1
		$l = $this->getLinker( $first_col );
265
266 1
		if ( !$hastitle && $object->getTypeID() != '_wpg' ) { // "linking" non-pages in title positions confuses timeline scripts, don't try this
267
			$l = null;
268
		}
269
270 1
		if ( $object->getTypeID() == '_wpg' ) { // use shorter "LongText" for wikipage
271 1
			$objectlabel = $object->getLongText( $outputmode, $l );
272
		} else {
273 1
			$objectlabel = $object->getShortText( $outputmode, $l );
274
		}
275
276 1
		$urlobject =  ( $l !== null );
277 1
		$header = '';
278
279 1
		if ( $first_value ) {
280
			// find header for current value:
281 1
			if ( $this->mShowHeaders && ( '' != $pr->getLabel() ) ) {
282 1
				$header = $pr->getText( $outputmode, $this->mLinker ) . ': ';
283
			}
284
285
			// is this a start date?
286 1
			if ( ( $pr->getMode() == SMWPrintRequest::PRINT_PROP ) &&
287 1
			     ( $date_value == $this->m_tlstart ) ) {
288
				// FIXME: Timeline scripts should support XSD format explicitly. They
289
				// currently seem to implement iso8601 which deviates from XSD in cases.
290
				// NOTE: We can assume $object to be an SMWDataValue in this case.
291 1
				$curmeta .= Html::element(
292 1
					'span',
293 1
					[ 'class' => 'smwtlstart' ],
294 1
					$object->getXMLSchemaDate()
0 ignored issues
show
Bug introduced by
It seems like you code against a specific sub-type and not the parent class SMWDataValue as the method getXMLSchemaDate() does only exist in the following sub-classes of SMWDataValue: SMWTimeValue. Maybe you want to instanceof check for one of these explicitly?

Let’s take a look at an example:

abstract class User
{
    /** @return string */
    abstract public function getPassword();
}

class MyUser extends User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different sub-classes of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the parent class:

    abstract class User
    {
        /** @return string */
        abstract public function getPassword();
    
        /** @return string */
        abstract public function getDisplayName();
    }
    
Loading history...
295
				);
296 1
				$positions[$object->getHash()] = $object->getXMLSchemaDate();
0 ignored issues
show
Bug introduced by
It seems like you code against a specific sub-type and not the parent class SMWDataValue as the method getXMLSchemaDate() does only exist in the following sub-classes of SMWDataValue: SMWTimeValue. Maybe you want to instanceof check for one of these explicitly?

Let’s take a look at an example:

abstract class User
{
    /** @return string */
    abstract public function getPassword();
}

class MyUser extends User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different sub-classes of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the parent class:

    abstract class User
    {
        /** @return string */
        abstract public function getPassword();
    
        /** @return string */
        abstract public function getDisplayName();
    }
    
Loading history...
297 1
				$hastime = true;
298
			}
299
300
			// is this the end date?
301 1
			if ( ( $pr->getMode() == SMWPrintRequest::PRINT_PROP ) &&
302 1
			     ( $date_value == $this->m_tlend ) ) {
303
				// NOTE: We can assume $object to be an SMWDataValue in this case.
304
				$curmeta .= Html::element(
305
					'span',
306
					[ 'class' => 'smwtlend' ],
307
					$object->getXMLSchemaDate( false )
0 ignored issues
show
Bug introduced by
It seems like you code against a specific sub-type and not the parent class SMWDataValue as the method getXMLSchemaDate() does only exist in the following sub-classes of SMWDataValue: SMWTimeValue. Maybe you want to instanceof check for one of these explicitly?

Let’s take a look at an example:

abstract class User
{
    /** @return string */
    abstract public function getPassword();
}

class MyUser extends User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different sub-classes of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the parent class:

    abstract class User
    {
        /** @return string */
        abstract public function getPassword();
    
        /** @return string */
        abstract public function getDisplayName();
    }
    
Loading history...
308
				);
309
			}
310
311
			// find title for displaying event
312 1
			if ( !$hastitle ) {
313 1
				$curmeta .= Html::rawElement(
314 1
					'span',
315
					[
316 1
						'class' => $urlobject ? 'smwtlurl' : 'smwtltitle'
317
					],
318 1
					$objectlabel
319
				);
320
321 1
				if ( $pr->getMode() == SMWPrintRequest::PRINT_THIS ) {
322 1
					$curarticle = $object->getLongText( $outputmode, $l );
323 1
					$cururl = $object->getTitle()->getFullUrl();
0 ignored issues
show
Bug introduced by
It seems like you code against a specific sub-type and not the parent class SMWDataValue as the method getTitle() does only exist in the following sub-classes of SMWDataValue: SMWWikiPageValue. Maybe you want to instanceof check for one of these explicitly?

Let’s take a look at an example:

abstract class User
{
    /** @return string */
    abstract public function getPassword();
}

class MyUser extends User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different sub-classes of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the parent class:

    abstract class User
    {
        /** @return string */
        abstract public function getPassword();
    
        /** @return string */
        abstract public function getDisplayName();
    }
    
Loading history...
324
				}
325
326
				// NOTE: type Title of $object implied
327 1
				$hastitle = true;
328
			}
329
		} elseif ( $output ) {
330
			// it *can* happen that output is false here, if the subject was not printed (fixed subject query) and mutliple items appear in the first row
331
			$curdata .= ', ';
332
		}
333
334 1
		if ( !$first_col || !$first_value || $isEventline ) {
335 1
			$curdata .= $header . $objectlabel;
336 1
			$output = true;
337
		}
338
339 1
		if ( $isEventline && ( $pr->getMode() == SMWPrintRequest::PRINT_PROP ) && ( $pr->getTypeID() == '_dat' ) && ( '' != $pr->getLabel() ) && ( $date_value != $this->m_tlstart ) && ( $date_value != $this->m_tlend ) ) {
340
			$event = [
341
				$object->getXMLSchemaDate(),
0 ignored issues
show
Bug introduced by
It seems like you code against a specific sub-type and not the parent class SMWDataValue as the method getXMLSchemaDate() does only exist in the following sub-classes of SMWDataValue: SMWTimeValue. Maybe you want to instanceof check for one of these explicitly?

Let’s take a look at an example:

abstract class User
{
    /** @return string */
    abstract public function getPassword();
}

class MyUser extends User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different sub-classes of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the parent class:

    abstract class User
    {
        /** @return string */
        abstract public function getPassword();
    
        /** @return string */
        abstract public function getDisplayName();
    }
    
Loading history...
342
				$pr->getLabel(),
343
				$object->getDataItem()->getSortKey(),
344
			];
345
		}
346
347 1
		return $event;
348
	}
349
350
	/**
351
	 * @see SMWResultPrinter::getParamDefinitions
352
	 *
353
	 * @since 1.8
354
	 *
355
	 * @param $definitions array of IParamDefinition
356
	 *
357
	 * @return array of IParamDefinition|array
358
	 */
359 1
	public function getParamDefinitions( array $definitions ) {
360 1
		$params = parent::getParamDefinitions( $definitions );
361
362 1
		$params['timelinesize'] = [
363
			'default' => '300px',
364
			'message' => 'srf_paramdesc_timelinesize',
365
		];
366
367 1
		$params['timelineposition'] = [
368
			'default' => 'middle',
369
			'message' => 'srf_paramdesc_timelineposition',
370
			'values' => [ 'start', 'middle', 'end', 'today' ],
371
		];
372
373 1
		$params['timelinestart'] = [
374
			'default' => '',
375
			'message' => 'srf_paramdesc_timelinestart',
376
		];
377
378 1
		$params['timelineend'] = [
379
			'default' => '',
380
			'message' => 'srf_paramdesc_timelineend',
381
		];
382
383 1
		$params['timelinebands'] = [
384
			'islist' => true,
385
			'default' => [ 'MONTH', 'YEAR' ],
386
			'message' => 'srf_paramdesc_timelinebands',
387
			'values' => [ 'MINUTE', 'HOUR', 'DAY', 'WEEK', 'MONTH', 'YEAR', 'DECADE' ],
388
		];
389
390 1
		$params['template'] = [
391
			'message' => 'smw-paramdesc-template',
392
			'default' => '',
393
		];
394
395 1
		$params['named args'] = [
396
			'type' => 'boolean',
397
			'message' => 'smw-paramdesc-named_args',
398
			'default' => false,
399
		];
400
401
402 1
		return $params;
403
	}
404
405
}
406