16 use ProtectedHookAccessorTrait;
22 $this->skinContext = $skinContext;
28 private function getTemplateDataFooter(): array {
30 'info' => $this->formatFooterInfoData(
31 $this->getFooterInfoData()
33 'places' => $this->getSiteFooterLinks(),
35 $skin = $this->skinContext->getContextSource()->getSkin();
36 foreach ( $data as $key => $existingItems ) {
38 $this->getHookRunner()->onSkinAddFooterLinks( $skin, $key, $newItems );
39 foreach ( $newItems as $index => $linkHTML ) {
40 $data[ $key ][ $index ] = [
41 'id' =>
'footer-' . $key .
'-' . $index,
53 $footerData = $this->getTemplateDataFooter();
59 $this->skinContext->getMessageLocalizer()
63 $footerData[
'places'],
64 $this->skinContext->getMessageLocalizer()
72 $footerMenuData[
'data-info'] = $footerInfoMenuData->getTemplateData();
73 $footerMenuData[
'data-places'] = $footerSiteMenuData->getTemplateData();
74 $footerMenuData[
'data-icons'] = $this->getFooterIcons();
75 $footerMenuData = $this->formatFooterDataForCurrentSpec( $footerMenuData );
78 'data-info' => $footerMenuData[
'data-info'],
79 'data-places' => $footerMenuData[
'data-places'],
80 'data-icons' => $footerMenuData[
'data-icons']
94 private function getFooterInfoData(): array {
96 $skinContext = $this->skinContext;
101 $titleExists = $title && $title->exists();
103 $maxCredits = $config->get( MainConfigNames::MaxCredits );
104 $showCreditsIfMax = $config->get( MainConfigNames::ShowCreditsIfMax );
105 $useCredits = $titleExists
107 && $out->isRevisionCurrent()
108 && $maxCredits !== 0;
112 $article = Article::newFromWikiPage( $skinContext->
getWikiPage(), $ctx );
113 $action = Action::factory(
'credits', $article, $ctx );
116 '@phan-var CreditsAction $action';
118 'lastmod' => !$useCredits ? $this->lastModified() : null,
119 'numberofwatchingusers' => null,
120 'credits' => $useCredits && $action ?
121 $action->getCredits( $maxCredits, $showCreditsIfMax ) : null,
122 'copyright' => $titleExists &&
123 $out->showsCopyright() ? $this->getCopyright() : null,
130 private function getCopyright() {
131 $copyright =
new SkinComponentCopyright( $this->skinContext );
132 return $copyright->getTemplateData()[
'html' ];
144 private function formatFooterInfoData( array $data ): array {
146 foreach ( $data as $key => $item ) {
148 $formattedData[ $key ] = [
149 'id' =>
'footer-info-' . $key,
154 return $formattedData;
163 private function getSiteFooterLinks(): array {
166 'privacy' => [
'privacy',
'privacypage' ],
167 'about' => [
'aboutsite',
'aboutpage' ],
168 'disclaimers' => [
'disclaimers',
'disclaimerpage' ]
170 $localizer = $this->skinContext->getMessageLocalizer();
172 foreach ( $siteLinks as $key => $siteLink ) {
175 if ( !$localizer->msg( $siteLink[0] )->inContentLanguage()->isDisabled() ) {
178 $title = Title::newFromText( $localizer->msg( $siteLink[1] )->inContentLanguage()->text() );
179 if ( $title !==
null ) {
180 $siteLinksData[$key] = [
181 'id' =>
"footer-places-$key",
182 'text' => $localizer->msg( $siteLink[0] )->text(),
183 'href' => $title->fixSpecialName()->getLinkURL()
188 return $siteLinksData;
203 if ( is_string( $icon ) ) {
206 $url = $icon[
'url'] ??
null;
207 unset( $icon[
'url'] );
208 if ( isset( $icon[
'src'] ) && $withImage ===
'withImage' ) {
210 $icon[
'loading'] =
'lazy';
212 $html = Html::element(
'img', $icon );
214 $html = htmlspecialchars( $icon[
'alt'] ??
'' );
217 $html = Html::rawElement(
223 'cdx-button',
'cdx-button--fake-button',
224 'cdx-button--size-large',
'cdx-button--fake-button--enabled'
226 'target' => $config->get( MainConfigNames::ExternalLinkTarget ),
245 $config->
get( MainConfigNames::FooterIcons ) as $footerIconsKey => &$footerIconsBlock
247 if ( count( $footerIconsBlock ) > 0 ) {
248 $footericons[$footerIconsKey] = [];
249 foreach ( $footerIconsBlock as &$footerIcon ) {
250 if ( isset( $footerIcon[
'src'] ) ) {
251 if ( !isset( $footerIcon[
'width'] ) ) {
252 $footerIcon[
'width'] = 88;
254 if ( !isset( $footerIcon[
'height'] ) ) {
255 $footerIcon[
'height'] = 31;
264 if ( is_string( $footerIcon ) || isset( $footerIcon[
'src'] ) ) {
265 $footericons[$footerIconsKey][] = $footerIcon;
271 if ( !count( $footericons[$footerIconsKey] ) ) {
272 unset( $footericons[$footerIconsKey] );
286 private function getFooterIcons(): array {
288 $skinContext = $this->skinContext;
291 $footerIcons = self::getFooterIconsData(
295 if ( count( $footerIcons ) > 0 ) {
297 foreach ( $footerIcons as $blockName => $blockIcons ) {
299 foreach ( $blockIcons as $icon ) {
300 $html .= self::makeFooterIconHTML(
307 $block = htmlspecialchars( $blockName );
310 'id' =>
'footer-' . $block .
'ico',
312 'class' => [
'noprint' ],
319 if ( count( $icons ) > 0 ) {
320 $dataIcons =
new SkinComponentMenu(
323 $this->skinContext->getMessageLocalizer(),
330 return $dataIcons ? $dataIcons->getTemplateData() : [];
344 private function formatFooterDataForCurrentSpec( array $data ): array {
346 foreach ( $data as $key => $item ) {
347 unset( $item[
'html-tooltip'] );
348 unset( $item[
'html-items'] );
349 unset( $item[
'html-after-portal'] );
350 unset( $item[
'html-before-portal'] );
351 unset( $item[
'label'] );
352 unset( $item[
'class'] );
353 foreach ( $item[
'array-items'] ?? [] as $index => $arrayItem ) {
354 unset( $item[
'array-items'][$index][
'html-item'] );
356 $formattedData[$key] = $item;
357 $formattedData[$key][
'className'] = $key ===
'data-icons' ?
'noprint' :
null;
359 return $formattedData;
368 private function lastModified() {
369 $skinContext = $this->skinContext;
371 $timestamp = $out->getRevisionTimestamp();
376 if ( $timestamp ===
null ) {
377 $revId = $out->getRevisionId();
378 if ( $revId !==
null ) {
379 $timestamp = MediaWikiServices::getInstance()->getRevisionLookup()->getTimestampFromId( $revId );
383 $lastModified =
new SkinComponentLastModified(
388 return $lastModified->getTemplateData()[
'text'];
Legacy class representing an editable page and handling UI for some page actions.