MediaWiki master
OpenSearchDescriptionHandler.php
Go to the documentation of this file.
1<?php
2
22
35
49
50 private UrlUtils $urlUtils;
51
53 private string $favicon;
54
56 private array $templates;
57
58 public function __construct( Config $config, UrlUtils $urlUtils ) {
59 $this->favicon = $config->get( MainConfigNames::Favicon );
60 $this->templates = $config->get( MainConfigNames::OpenSearchTemplates );
61 $this->urlUtils = $urlUtils;
62 }
63
64 public function execute(): Response {
65 $ctype = $this->getContentType();
66
67 $response = $this->getResponseFactory()->create();
68 $response->setHeader( 'Content-type', $ctype );
69
70 // Set an Expires header so that CDN can cache it for a short time
71 // Short enough so that the sysadmin barely notices when $wgSitename is changed
72 $expiryTime = 600; # 10 minutes
73 $response->setHeader( 'Expires', gmdate( 'D, d M Y H:i:s', time() + $expiryTime ) . ' GMT' );
74 $response->setHeader( 'Cache-control', 'max-age=600' );
75
76 $body = new StringStream();
77
78 $body->write( '<?xml version="1.0"?>' );
79 $body->write( Xml::openElement( 'OpenSearchDescription',
80 [
81 'xmlns' => 'http://a9.com/-/spec/opensearch/1.1/',
82 'xmlns:moz' => 'http://www.mozilla.org/2006/browser/search/' ] ) );
83
84 // The spec says the ShortName must be no longer than 16 characters,
85 // but 16 is *realllly* short. In practice, browsers don't appear to care
86 // when we give them a longer string, so we're no longer attempting to trim.
87 //
88 // Note: ShortName and the <link title=""> need to match; they are used as
89 // a key for identifying if the search engine has been added already, *and*
90 // as the display name presented to the end-user.
91 //
92 // Behavior seems about the same between Firefox and IE 7/8 here.
93 // 'Description' doesn't appear to be used by either.
94 $fullName = wfMessage( 'opensearch-desc' )->inContentLanguage()->text();
95 $body->write( Xml::element( 'ShortName', null, $fullName ) );
96 $body->write( Xml::element( 'Description', null, $fullName ) );
97
98 // By default we'll use the site favicon.
99 // Double-check if IE supports this properly?
100 $body->write( Xml::element( 'Image',
101 [
102 'height' => 16,
103 'width' => 16,
104 'type' => 'image/x-icon'
105 ],
106 (string)$this->urlUtils->expand( $this->favicon, PROTO_CURRENT )
107 ) );
108
109 $urls = [];
110
111 // General search template. Given an input term, this should bring up
112 // search results or a specific found page.
113 // At least Firefox and IE 7 support this.
114 $searchPage = SpecialPage::getTitleFor( 'Search' );
115 $urls[] = [
116 'type' => 'text/html',
117 'method' => 'get',
118 'template' => $searchPage->getCanonicalURL( 'search={searchTerms}' ) ];
119
120 // TODO: add v1/search/ endpoints?
121
122 foreach ( $this->templates as $type => $template ) {
123 if ( !$template ) {
124 $template = ApiOpenSearch::getOpenSearchTemplate( $type );
125 }
126
127 if ( $template ) {
128 $urls[] = [
129 'type' => $type,
130 'method' => 'get',
131 'template' => $template,
132 ];
133 }
134 }
135
136 // Allow hooks to override the suggestion URL settings in a more
137 // general way than overriding the whole search engine...
138 ( new HookRunner( $this->getHookContainer() ) )->onOpenSearchUrls( $urls );
139
140 foreach ( $urls as $attribs ) {
141 $body->write( Xml::element( 'Url', $attribs ) );
142 }
143
144 // And for good measure, add a link to the straight search form.
145 // This is a custom format extension for Firefox, which otherwise
146 // sends you to the domain root if you hit "enter" with an empty
147 // search box.
148 $body->write( Xml::element( 'moz:SearchForm', null,
149 $searchPage->getCanonicalURL() ) );
150
151 $body->write( Xml::closeElement( 'OpenSearchDescription' ) );
152
153 $response->setBody( $body );
154 return $response;
155 }
156
164 private function getContentType(): string {
165 $params = $this->getValidatedParams();
166 if ( $params['ctype'] == 'application/xml' ) {
167 // Makes testing tweaks about a billion times easier
168 return 'application/xml';
169 }
170
171 $acceptHeader = $this->getRequest()->getHeader( 'accept' );
172
173 if ( $acceptHeader ) {
174 $parser = new HttpAcceptParser();
175 $acceptableTypes = $parser->parseAccept( $acceptHeader[0] );
176
177 foreach ( $acceptableTypes as $acc ) {
178 if ( $acc['type'] === 'application/xml' ) {
179 return 'application/xml';
180 }
181 }
182 }
183
184 return 'application/opensearchdescription+xml';
185 }
186
187 public function getParamSettings() {
188 return [
189 'ctype' => [
190 self::PARAM_SOURCE => 'query',
191 ]
192 ];
193 }
194
195}
getRequest()
const PROTO_CURRENT
Definition Defines.php:209
wfMessage( $key,... $params)
This is the function for getting translated interface messages.
array $params
The job parameters.
static getOpenSearchTemplate( $type)
Fetch the template for a type.
This class provides an implementation of the core hook interfaces, forwarding hook calls to HookConta...
static openElement( $element, $attribs=[])
Identical to rawElement(), but has no third parameter and omits the end tag (and the self-closing '/'...
Definition Html.php:240
static closeElement( $element)
Returns "</$element>".
Definition Html.php:304
static element( $element, $attribs=[], $contents='')
Identical to rawElement(), but HTML-escapes $contents (like Xml::element()).
Definition Html.php:216
A class containing constants representing the names of configuration variables.
const OpenSearchTemplates
Name constant for the OpenSearchTemplates setting, for use with Config::get()
const Favicon
Name constant for the Favicon setting, for use with Config::get()
This class contains schema declarations for all configuration variables known to MediaWiki core.
Handler for generating an OpenSearch description document.
getParamSettings()
Fetch ParamValidator settings for parameters.
Base class for REST route handlers.
Definition Handler.php:24
getHookContainer()
Get a HookContainer, for running extension hooks or for hook metadata.
Definition Handler.php:984
getValidatedParams()
Fetch the validated parameters.
Definition Handler.php:820
getResponseFactory()
Get the ResponseFactory which can be used to generate Response objects.
Definition Handler.php:356
setHeader( $name, $value)
Set or replace the specified header.
Definition Response.php:94
A stream class which uses a string as the underlying storage.
Parent class for all special pages.
static getTitleFor( $name, $subpage=false, $fragment='')
Get a localised Title object for a specified special page name If you don't need a full Title object,...
A service to expand, parse, and otherwise manipulate URLs.
Definition UrlUtils.php:16
Module of static functions for generating XML.
Definition Xml.php:37
Interface for configuration instances.
Definition Config.php:32
get( $name)
Get a configuration variable such as "Sitename" or "UploadMaintenance.".
Copyright (C) 2011-2020 Wikimedia Foundation and others.