22 public static $id = 0;
34 $parser->setHook(
'imagemap',
array(
'ImageMap',
'render' ) );
44 global $wgUrlProtocols, $wgNoFollowLinks;
55 $descTypesCanonical =
'top-right, bottom-right, bottom-left, top-left, none';
57 $defaultLinkAttribs =
false;
74 $bits = explode(
'|',
$line, 2 );
75 if (
count( $bits ) == 1 ) {
82 if ( !$imageTitle || !$imageTitle->inNamespace(
NS_FILE ) ) {
90 $imageHTML =
$parser->makeImage( $imageTitle, $parsedOptions );
91 $parser->replaceLinkHolders( $imageHTML );
92 $imageHTML =
$parser->mStripState->unstripBoth( $imageHTML );
93 $imageHTML = Sanitizer::normalizeCharReferences( $imageHTML );
95 $domDoc =
new DOMDocument();
97 $ok = $domDoc->loadXML( $imageHTML );
102 $xpath =
new DOMXPath( $domDoc );
103 $imgs = $xpath->query(
'//img' );
104 if ( !$imgs->length ) {
107 $imageNode = $imgs->item( 0 );
108 $thumbWidth = $imageNode->getAttribute(
'width' );
109 $thumbHeight = $imageNode->getAttribute(
'height' );
112 if ( !$imageObj || !$imageObj->exists() ) {
118 $denominator = $imageObj->getWidth() + $imageObj->getHeight();
119 $numerator = $thumbWidth + $thumbHeight;
120 if ( $denominator <= 0 || $numerator <= 0 ) {
123 $scale = $numerator / $denominator;
128 $cmd = strtok(
$line,
" \t" );
129 if ( $cmd ==
'desc' ) {
130 $typesText =
wfMessage(
'imagemap_desc_types' )->inContentLanguage()->text();
131 if ( $descTypesCanonical != $typesText ) {
133 $typesText = $descTypesCanonical .
', ' . $typesText;
135 $types = array_map(
'trim', explode(
',', $typesText ) );
136 $type = trim( strtok(
'' ) );
137 $descType = array_search(
$type, $types );
138 if ( $descType > 4 ) {
140 $descType = $descType - 5;
143 if ( $descType ===
false || $descType < 0 ) {
144 return self::error(
'imagemap_invalid_desc', $typesText );
153 if ( preg_match(
'/^ \[\[ ([^|]*+) \| ([^\]]*+) \]\] \w* $ /x',
$link, $m ) ) {
155 $alt = trim( $m[2] );
156 } elseif ( preg_match(
'/^ \[\[ ([^\]]*+) \]\] \w* $ /x',
$link, $m ) ) {
158 if ( is_null(
$title ) ) {
159 return self::error(
'imagemap_invalid_title', $lineNum );
161 $alt =
$title->getFullText();
162 } elseif ( in_array( substr(
$link, 1, strpos(
$link,
'//' ) + 1 ), $wgUrlProtocols ) || in_array( substr(
$link, 1, strpos(
$link,
':' ) ), $wgUrlProtocols ) ) {
163 if ( preg_match(
'/^ \[ ([^\s]*+) \s ([^\]]*+) \] \w* $ /x',
$link, $m ) ) {
165 $alt = trim( $m[2] );
167 } elseif ( preg_match(
'/^ \[ ([^\]]*+) \] \w* $ /x',
$link, $m ) ) {
168 $title = $alt = trim( $m[1] );
172 return self::error(
'imagemap_no_link', $lineNum );
175 return self::error(
'imagemap_invalid_title', $lineNum );
178 $shapeSpec = substr(
$line, 0, -strlen(
$link ) );
181 $shape = strtok( $shapeSpec,
" \t" );
188 if ( !is_array( $coords ) ) {
194 if ( !is_array( $coords ) ) {
200 $coord = strtok(
" \t" );
201 while ( $coord !==
false ) {
203 $coord = strtok(
" \t" );
205 if ( !
count( $coords ) ) {
206 return self::error(
'imagemap_missing_coord', $lineNum );
208 if (
count( $coords ) % 2 !== 0 ) {
209 return self::error(
'imagemap_poly_odd', $lineNum );
213 return self::error(
'imagemap_unrecognised_shape', $lineNum );
217 foreach ( $coords
as $i => $c ) {
218 $coords[$i] = intval( round( $c * $scale ) );
226 if ( $wgNoFollowLinks ) {
229 } elseif (
$title->getFragment() !=
'' &&
$title->getPrefixedDBkey() ==
'' ) {
236 if ( $shape !=
'default' ) {
240 $attribs[
'coords'] = implode(
',', $coords );
243 if ( $shape !=
'default' ) {
248 if ( $shape ==
'default' ) {
264 if ( $mapHTML ==
'' ) {
273 $mapName =
"ImageMap_" . ++self::$id .
'_' . mt_rand( 0, 0x7fffffff );
274 $mapHTML =
"<map name=\"$mapName\">\n$mapHTML</map>\n";
277 $imageNode->setAttribute(
'usemap',
"#$mapName" );
281 $anchor = $imageNode->parentNode;
282 $parent = $anchor->parentNode;
283 $div = $parent->insertBefore(
new DOMElement(
'div' ), $anchor );
284 $div->setAttribute(
'class',
'noresize' );
285 if ( $defaultLinkAttribs ) {
286 $defaultAnchor = $div->appendChild(
new DOMElement(
'a' ) );
290 $imageParent = $defaultAnchor;
297 if ( $mapHTML !=
'' ) {
298 $mapDoc =
new DOMDocument();
299 $mapDoc->loadXML( $mapHTML );
300 $mapNode = $domDoc->importNode( $mapDoc->documentElement,
true );
301 $div->appendChild( $mapNode );
304 $imageParent->appendChild( $imageNode->cloneNode(
true ) );
305 $parent->removeChild( $anchor );
308 $xpath =
new DOMXPath( $domDoc );
309 $magnify = $xpath->query(
'//div[@class="magnify"]' );
310 if ( !$magnify->length && $descType != self::NONE ) {
312 if ( $descType == self::TOP_LEFT || $descType == self::BOTTOM_LEFT ) {
315 $marginLeft = $thumbWidth - 20;
317 if ( $descType == self::TOP_LEFT || $descType == self::TOP_RIGHT ) {
318 $marginTop = -$thumbHeight;
324 $div->setAttribute(
'style',
"height: {$thumbHeight}px; width: {$thumbWidth}px; " );
325 $descWrapper = $div->appendChild(
new DOMElement(
'div' ) );
326 $descWrapper->setAttribute(
'style',
327 "margin-left: {$marginLeft}px; " .
328 "margin-top: {$marginTop}px; " .
332 $descAnchor = $descWrapper->appendChild(
new DOMElement(
'a' ) );
333 $descAnchor->setAttribute(
'href', $imageTitle->getLocalURL() );
334 $descAnchor->setAttribute(
336 wfMessage(
'imagemap_description' )->inContentLanguage()->
text()
338 $descImg = $descAnchor->appendChild(
new DOMElement(
'img' ) );
339 $descImg->setAttribute(
341 wfMessage(
'imagemap_description' )->inContentLanguage()->
text()
343 $url = $config->get(
'ExtensionAssetsPath' ) .
'/ImageMap/desc-20.png';
344 $descImg->setAttribute(
348 $descImg->setAttribute(
'style',
'border: none;' );
354 $output = preg_replace(
'/<\?xml[^?]*\?>/',
'', $domDoc->saveXML(
null, LIBXML_NOEMPTYTAG ) );
383 for ( $i = 0; $i < $count; $i++ ) {
384 $coord = strtok(
" \t" );
385 if ( $coord ===
false ) {
386 return self::error(
'imagemap_missing_coord', $lineNum );
388 if ( !is_numeric( $coord ) || $coord > 1e9 || $coord < 0 ) {
389 return self::error(
'imagemap_invalid_coord', $lineNum );
391 $coords[$i] = $coord;