Page Menu
Home
WickedGov Phorge
Search
Configure Global Search
Log In
Files
F4062729
SitemapGenerator.php
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Flag For Later
Award Token
Size
6 KB
Referenced Files
None
Subscribers
None
SitemapGenerator.php
View Options
<?php
namespace
MediaWiki\Page
;
use
MediaWiki\Cache\GenderCache
;
use
MediaWiki\Config\Config
;
use
MediaWiki\Language\Language
;
use
MediaWiki\Languages\LanguageConverterFactory
;
use
MediaWiki\MainConfigNames
;
use
MediaWiki\Title\Title
;
use
MediaWiki\Xml\Xml
;
use
Wikimedia\Rdbms\IReadableDatabase
;
/**
* Utility for generating a sitemap
*
* @internal
*/
class
SitemapGenerator
{
private
?
array
$namespaces
=
null
;
private
?
array
$excludedNamespaces
=
null
;
private
?
int
$startId
=
null
;
private
?
int
$endId
=
null
;
private
array
$variants
=
[];
private
bool
$skipRedirects
=
false
;
private
?
int
$limit
=
null
;
private
?
int
$nextBatchStart
=
null
;
/**
* The gender cache, or null if the content language has no gendered namespaces
* @var GenderCache|null
*/
private
?
GenderCache
$genderCache
;
/** @return array */
public
static
function
getVariants
(
Language
$contLang
,
LanguageConverterFactory
$languageConverterFactory
,
)
{
$converter
=
$languageConverterFactory
->
getLanguageConverter
(
$contLang
);
$variants
=
[];
foreach
(
$converter
->
getVariants
()
as
$vCode
)
{
// We don't want the default variant
if
(
$vCode
!==
$contLang
->
getCode
()
)
{
$variants
[]
=
$vCode
;
}
}
return
$variants
;
}
public
function
__construct
(
Language
$contLang
,
LanguageConverterFactory
$languageConverterFactory
,
GenderCache
$genderCache
,
)
{
$this
->
variants
=
self
::
getVariants
(
$contLang
,
$languageConverterFactory
);
$this
->
genderCache
=
$contLang
->
needsGenderDistinction
()
?
$genderCache
:
null
;
}
/**
* Optionally limit the namespace IDs
*
* @param int[]|null $namespaces
* @return $this
*/
public
function
namespaces
(
?
array
$namespaces
)
{
$this
->
namespaces
=
$namespaces
;
return
$this
;
}
/**
* Set the included/excluded namespace list based on configuration
*
* @param Config $config
* @return $this
*/
public
function
namespacesFromConfig
(
Config
$config
)
{
$this
->
namespaces
=
null
;
$this
->
excludedNamespaces
=
null
;
$namespaces
=
$config
->
get
(
MainConfigNames
::
SitemapNamespaces
);
if
(
$namespaces
)
{
$this
->
namespaces
=
$namespaces
;
return
$this
;
}
$defaultPolicy
=
$config
->
get
(
MainConfigNames
::
DefaultRobotPolicy
);
$namespacePolicies
=
$config
->
get
(
MainConfigNames
::
NamespaceRobotPolicies
);
if
(
self
::
isNoIndex
(
$defaultPolicy
)
)
{
$namespaces
=
[];
foreach
(
$namespacePolicies
as
$ns
=>
$policy
)
{
if
(
!
self
::
isNoIndex
(
$policy
)
)
{
$namespaces
[]
=
$ns
;
}
}
$this
->
namespaces
=
$namespaces
;
}
else
{
$excluded
=
[];
foreach
(
$namespacePolicies
as
$ns
=>
$policy
)
{
if
(
self
::
isNoIndex
(
$policy
)
)
{
$excluded
[]
=
$ns
;
}
}
if
(
$excluded
)
{
$this
->
excludedNamespaces
=
$excluded
;
}
}
return
$this
;
}
/**
* Interpret a configured robots policy
*
* @param string|array $policy
* @return bool
*/
private
static
function
isNoIndex
(
$policy
)
{
$policyArray
=
Article
::
formatRobotPolicy
(
$policy
);
return
(
$policyArray
[
'index'
]
??
''
)
===
'noindex'
;
}
/**
* Limit the page_id range to the given half-open interval
*
* @param int|null $startId The start ID, or null for unlimited
* @param int|null $endId The end ID, or null for unlimited. Only pages
* with a page_id less than this value will be returned.
* @return $this
*/
public
function
idRange
(
?
int
$startId
,
?
int
$endId
)
{
$this
->
startId
=
$startId
;
$this
->
endId
=
$endId
;
return
$this
;
}
/**
* Skip redirects
*
* @param bool $skip
* @return $this
*/
public
function
skipRedirects
(
bool
$skip
=
true
)
{
$this
->
skipRedirects
=
$skip
;
return
$this
;
}
/**
* Limit the number of returned results.
*
* @param int $limit
* @return $this
*/
public
function
limit
(
int
$limit
)
{
$this
->
limit
=
$limit
;
return
$this
;
}
/**
* If a previous call to getXml() reached the limit set by limit() and there
* were still more rows, calling this will advance an internal cursor to the
* start of the next batch, and return true.
*
* If there were no more rows, return false.
*
* @return bool
*/
public
function
nextBatch
()
{
if
(
$this
->
nextBatchStart
!==
null
)
{
$this
->
startId
=
$this
->
nextBatchStart
;
return
true
;
}
else
{
return
false
;
}
}
/**
* Use the previously set options to generate an XML sitemap
*
* @param IReadableDatabase $dbr
* @return string
*/
public
function
getXml
(
IReadableDatabase
$dbr
)
{
$empty
=
false
;
$sqb
=
$dbr
->
newSelectQueryBuilder
()
->
select
(
[
'page_id'
,
'page_namespace'
,
'page_title'
,
'page_touched'
]
)
->
from
(
'page'
)
->
leftJoin
(
'page_props'
,
null
,
[
'page_id = pp_page'
,
'pp_propname'
=>
'noindex'
]
)
->
where
(
[
'pp_propname'
=>
null
]
)
->
orderBy
(
'page_id'
)
->
caller
(
__METHOD__
);
if
(
$this
->
startId
!==
null
)
{
$sqb
->
where
(
$dbr
->
expr
(
'page_id'
,
'>='
,
$this
->
startId
)
);
}
if
(
$this
->
endId
!==
null
)
{
$sqb
->
where
(
$dbr
->
expr
(
'page_id'
,
'<'
,
$this
->
endId
)
);
}
if
(
$this
->
namespaces
!==
null
)
{
if
(
$this
->
namespaces
===
[]
)
{
$empty
=
true
;
}
else
{
$sqb
->
where
(
[
'page_namespace'
=>
$this
->
namespaces
]
);
}
}
if
(
$this
->
excludedNamespaces
!==
null
)
{
$sqb
->
where
(
[
$dbr
->
expr
(
'page_namespace'
,
'!='
,
$this
->
excludedNamespaces
)
]
);
}
if
(
$this
->
skipRedirects
)
{
$sqb
->
where
(
[
'page_is_redirect'
=>
0
]
);
}
$variants
=
[
null
,
...
$this
->
variants
];
if
(
$this
->
limit
)
{
$pageLimit
=
(
int
)(
$this
->
limit
/
count
(
$variants
)
);
$sqb
->
limit
(
$pageLimit
+
1
);
}
else
{
$pageLimit
=
null
;
}
$res
=
$empty
?
[]
:
$sqb
->
fetchResultSet
();
$this
->
genderCache
?->
doPageRows
(
$res
);
$xml
=
"<?xml version=
\"
1.0
\"
encoding=
\"
UTF-8
\"
?>
\n
"
.
"<urlset xmlns=
\"
http://www.sitemaps.org/schemas/sitemap/0.9
\"
>
\n
"
;
$count
=
0
;
$nextBatchStart
=
0
;
foreach
(
$res
as
$row
)
{
if
(
$pageLimit
!==
null
&&
++
$count
>
$pageLimit
)
{
$nextBatchStart
=
(
int
)
$row
->
page_id
;
break
;
}
$title
=
Title
::
makeTitle
(
$row
->
page_namespace
,
$row
->
page_title
);
foreach
(
$variants
as
$variant
)
{
$query
=
$variant
===
null
?
''
:
'variant='
.
urlencode
(
$variant
);
$xml
.=
'<url>'
.
Xml
::
element
(
'loc'
,
null
,
$title
->
getCanonicalURL
(
$query
)
)
.
Xml
::
element
(
'lastmod'
,
null
,
wfTimestamp
(
TS_ISO_8601
,
$row
->
page_touched
)
)
.
"</url>
\n
"
;
}
}
$xml
.=
"</urlset>
\n
"
;
if
(
$nextBatchStart
)
{
$this
->
nextBatchStart
=
$nextBatchStart
;
}
else
{
$this
->
nextBatchStart
=
null
;
}
return
$xml
;
}
}
File Metadata
Details
Attached
Mime Type
text/x-php
Expires
Aug 16 2026, 11:20 (12 w, 6 h ago)
Storage Engine
local-disk
Storage Format
Raw Data
Storage Handle
2b/f1/b4cfee3ccc7ae6c62b910a27c0aa
Default Alt Text
SitemapGenerator.php (6 KB)
Attached To
Mode
rMWPROD MediaWiki Production
Attached
Detach File
Event Timeline
Log In to Comment