Completed
Push — master ( 71c033...f73bc6 )
by mw
34:22
created

InfoLinksProvider::createInfoLinks()   C

Complexity

Conditions 8
Paths 6

Size

Total Lines 32
Code Lines 16

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 1
Metric Value
cc 8
eloc 16
c 1
b 0
f 1
nc 6
nop 0
dl 0
loc 32
rs 5.3846
1
<?php
2
3
namespace SMW\DataValues;
4
5
use SMWInfolink as Infolink;
6
use SMWDataValue  as DataValue;
7
use SMW\ApplicationFactory;
8
use SMW\InTextAnnotationParser;
9
use SMW\DIProperty;
10
use SMW\Message;
11
use SMWStringValue as StringValue;
12
use SMWDIBlob as DIBlob;
13
14
/**
15
 * @license GNU GPL v2+
16
 * @since 2.4
17
 *
18
 * @author mwjames
19
 */
20
class InfoLinksProvider {
21
22
	/**
23
	 * @var DataValue
24
	 */
25
	private $dataValue;
26
27
	/**
28
	 * @var Infolink[]
29
	 */
30
	protected $infoLinks = array();
31
32
	/**
33
	 * Used to control the addition of the standard search link.
34
	 * @var boolean
35
	 */
36
	private $hasSearchLink;
37
38
	/**
39
	 * Used to control service link creation.
40
	 * @var boolean
41
	 */
42
	private $hasServiceLinks;
43
44
	/**
45
	 * @var boolean
46
	 */
47
	private $enabledServiceLinks = true;
48
49
	/**
50
	 * @var boolean|array
51
	 */
52
	private $serviceLinkParameters = false;
53
54
	/**
55
	 * @since 2.4
56
	 *
57
	 * @param DataValue $dataValue
58
	 */
59
	public function __construct( DataValue $dataValue ) {
60
		$this->dataValue = $dataValue;
61
	}
62
63
	/**
64
	 * @since 2.4
65
	 */
66
	public function init() {
67
		$this->infoLinks = array();
68
		$this->hasSearchLink = false;
69
		$this->hasServiceLinks = false;
70
		$this->enabledServiceLinks = true;
71
		$this->serviceLinkParameters = false;
72
	}
73
74
	/**
75
	 * @since 2.4
76
	 */
77
	public function disableServiceLinks() {
78
		$this->enabledServiceLinks = false;
79
	}
80
81
	/**
82
	 * Adds a single SMWInfolink object to the infoLinks array.
83
	 *
84
	 * @since 2.4
85
	 *
86
	 * @param Infolink $link
0 ignored issues
show
Bug introduced by
There is no parameter named $link. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
87
	 */
88
	public function addInfolink( Infolink $infoLink ) {
89
		$this->infoLinks[] = $infoLink;
90
	}
91
92
	/**
93
	 * @since 2.4
94
	 *
95
	 * @param array|false $serviceLinkParameters
96
	 */
97
	public function setServiceLinkParameters( $serviceLinkParameters ) {
98
		$this->serviceLinkParameters = $serviceLinkParameters;
99
	}
100
101
	/**
102
	 * Return an array of SMWLink objects that provide additional resources
103
	 * for the given value. Captions can contain some HTML markup which is
104
	 * admissible for wiki text, but no more. Result might have no entries
105
	 * but is always an array.
106
	 *
107
	 * @since 2.4
108
	 */
109
	public function createInfoLinks() {
110
111
		if ( $this->infoLinks !== array() ) {
112
			return $this->infoLinks;
113
		}
114
115
		if ( !$this->dataValue->isValid() || $this->dataValue->getProperty() === null ) {
116
			return array();
117
		}
118
119
		$value = $this->dataValue->getWikiValue();
120
121
		// InTextAnnotationParser will detect :: therefore avoid link
122
		// breakage by encoding the string
123
		if ( strpos( $value, '::' ) !== false && !$this->hasInternalAnnotationMarker( $value ) ) {
124
			$value = str_replace( ':', '-3A', $value );
125
		}
126
127
		$this->hasSearchLink = true;
128
		$this->infoLinks[] = Infolink::newPropertySearchLink(
129
			'+',
130
			$this->dataValue->getProperty()->getLabel(),
131
			$value
132
		);
133
134
		 // add further service links
135
		if ( !$this->hasServiceLinks && $this->enabledServiceLinks ) {
136
			$this->addServiceLinks();
137
		}
138
139
		return $this->infoLinks;
140
	}
141
142
	/**
143
	 * Return text serialisation of info links. Ensures more uniform layout
144
	 * throughout wiki (Factbox, Property pages, ...).
145
	 *
146
	 * @param integer $outputformat Element of the SMW_OUTPUT_ enum
147
	 * @param Linker|null $linker
148
	 *
149
	 * @return string
150
	 */
151
	public function getInfolinkText( $outputformat, $linker = null ) {
152
153
		$result = '';
154
		$first = true;
155
		$extralinks = array();
156
157
		foreach ( $this->dataValue->getInfolinks() as $link ) {
158
159
			if ( $outputformat === SMW_OUTPUT_WIKI ) {
160
				$text = $link->getWikiText();
161
			} else {
162
				$text = $link->getHTML( $linker );
163
			}
164
165
			// the comment is needed to prevent MediaWiki from linking
166
			// URL-strings together with the nbsps!
167
			if ( $first ) {
168
				$result .= ( $outputformat === SMW_OUTPUT_WIKI ? '<!-- -->  ' : '&#160;&#160;' ) . $text;
169
				$first = false;
170
			} else {
171
				$extralinks[] = $text;
172
			}
173
		}
174
175
		if ( $extralinks !== array() ) {
176
			$result .= smwfEncodeMessages( $extralinks, 'service', '', false );
177
		}
178
179
		// #1453 SMW::on/off will break any potential link therefore just don't even try
180
		return !$this->hasInternalAnnotationMarker( $result ) ? $result : '';
181
	}
182
183
	/**
184
	 * Servicelinks are special kinds of infolinks that are created from
185
	 * current parameters and in-wiki specification of URL templates. This
186
	 * method adds the current property's servicelinks found in the
187
	 * messages. The number and content of the parameters is depending on
188
	 * the datatype, and the service link message is usually crafted with a
189
	 * particular datatype in mind.
190
	 */
191
	public function addServiceLinks() {
192
193
		if ( $this->hasServiceLinks ) {
194
			return;
195
		}
196
197
		if ( $this->dataValue->getProperty() !== null ) {
198
			$propertyDiWikiPage = $this->dataValue->getProperty()->getDiWikiPage();
199
		}
200
201
		if ( $propertyDiWikiPage === null ) {
0 ignored issues
show
Bug introduced by
The variable $propertyDiWikiPage 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...
202
			return; // no property known, or not associated with a page
203
		}
204
205
		$args = $this->serviceLinkParameters;
206
207
		if ( $args === false ) {
208
			return; // no services supported
209
		}
210
211
		array_unshift( $args, '' ); // add a 0 element as placeholder
212
213
		$servicelinks = ApplicationFactory::getInstance()->getCachedPropertyValuesPrefetcher()->getPropertyValues(
214
			$propertyDiWikiPage,
215
			new DIProperty( '_SERV' )
216
		);
217
218
		foreach ( $servicelinks as $dataItem ) {
219
			if ( !( $dataItem instanceof DIBlob ) ) {
220
				continue;
221
			}
222
223
			$args[0] = 'smw_service_' . str_replace( ' ', '_', $dataItem->getString() ); // messages distinguish ' ' from '_'
224
			$text = Message::get( $args, Message::TEXT, Message::CONTENT_LANGUAGE );
225
			$links = preg_split( "/[\n][\s]?/u", $text );
226
227
			foreach ( $links as $link ) {
228
				$linkdat = explode( '|', $link, 2 );
229
230
				if ( count( $linkdat ) == 2 ) {
231
					$this->addInfolink( Infolink::newExternalLink( $linkdat[0], trim( $linkdat[1] ) ) );
232
				}
233
			}
234
		}
235
236
		$this->hasServiceLinks = true;
237
	}
238
239
	private function hasInternalAnnotationMarker( $value ) {
240
		return strpos( $value, 'SMW::off' ) !== false || strpos( $value, 'SMW::on' ) !== false;
241
	}
242
243
}
244