Файловый менеджер - Редактировать - /var/www/html/mediawiki-1.43.1/includes/OutputTransform/Stages/HandleSectionLinks.php
Ðазад
<?php namespace MediaWiki\OutputTransform\Stages; use LogicException; use MediaWiki\Config\ServiceOptions; use MediaWiki\Context\RequestContext; use MediaWiki\Html\Html; use MediaWiki\Html\HtmlHelper; use MediaWiki\MainConfigNames; use MediaWiki\OutputTransform\ContentTextTransformStage; use MediaWiki\Parser\ParserOptions; use MediaWiki\Parser\ParserOutput; use MediaWiki\Parser\ParserOutputFlags; use MediaWiki\Parser\Sanitizer; use MediaWiki\Title\TitleFactory; use Psr\Log\LoggerInterface; use Skin; /** * Add anchors and other heading formatting, and replace the section link placeholders. * @internal */ class HandleSectionLinks extends ContentTextTransformStage { private const EDITSECTION_REGEX = '#<mw:editsection page="(.*?)" section="(.*?)">(.*?)</mw:editsection>#s'; private const HEADING_REGEX = '/<H(?P<level>[1-6])(?P<attrib>(?:[^\'">]*|"([^"]*)"|\'([^\']*)\')*>)(?P<header>[\s\S]*?)<\/H[1-6] *>/i'; private TitleFactory $titleFactory; /** @internal */ public const CONSTRUCTOR_OPTIONS = [ MainConfigNames::ParserEnableLegacyHeadingDOM, // For HandleSectionLinks ]; public function __construct( ServiceOptions $options, LoggerInterface $logger, TitleFactory $titleFactory ) { parent::__construct( $options, $logger ); $this->titleFactory = $titleFactory; } public function shouldRun( ParserOutput $po, ?ParserOptions $popts, array $options = [] ): bool { $isParsoid = $options['isParsoidContent'] ?? false; return !$isParsoid; } protected function transformText( string $text, ParserOutput $po, ?ParserOptions $popts, array &$options ): string { $text = $this->replaceHeadings( $text, $options ); if ( ( $options['enableSectionEditLinks'] ?? true ) && !$po->getOutputFlag( ParserOutputFlags::NO_SECTION_EDIT_LINKS ) ) { return $this->addSectionLinks( $text, $po, $options ); } else { return preg_replace( self::EDITSECTION_REGEX, '', $text ); } } private function replaceHeadings( string $text, array $options ): string { $skin = $this->resolveSkin( $options ); $useLegacyHeading = $this->options->get( MainConfigNames::ParserEnableLegacyHeadingDOM ); if ( $skin && !$skin->getOptions()['supportsMwHeading'] ) { $useLegacyHeading = true; } $needToCheckExistingWrappers = preg_match( '/class="[^"]*\bmw-heading\b[^"]*"/', $text ); return preg_replace_callback( self::HEADING_REGEX, function ( $m ) use ( $useLegacyHeading, $needToCheckExistingWrappers, $text ) { // Parse attributes out of the <h#> tag. Do not actually use HtmlHelper's output, // because EDITSECTION_REGEX is sensitive to quotes in HTML serialization. $attrs = []; HtmlHelper::modifyElements( $m[0][0], static fn ( $node ) => in_array( $node->name, [ 'h1', 'h2', 'h3', 'h4', 'h5', 'h6' ] ), static function ( $node ) use ( &$attrs ) { $attrs = $node->attrs->getValues(); return $node; } ); if ( !isset( $attrs['data-mw-anchor'] ) ) { return $m[0][0]; } $anchor = $attrs['data-mw-anchor']; $fallbackAnchor = $attrs['data-mw-fallback-anchor'] ?? false; unset( $attrs['data-mw-anchor'] ); unset( $attrs['data-mw-fallback-anchor'] ); // Split the heading content from the section edit link placeholder $editlink = ''; $contents = preg_replace_callback( self::EDITSECTION_REGEX, static function ( $mm ) use ( &$editlink ) { $editlink = $mm[0]; return ''; }, $m['header'][0] ); if ( !$useLegacyHeading ) { $wrapperType = 'mwheading'; // Do not add another wrapper if an existing wrapper if present. // This is to support DiscussionTools adding wrappers itself. // TODO: This is obviously bad and unreliable. One day, this code will use DOM transforms, // and can just check ->parentNode like in HandleParsoidSectionLinks. if ( $needToCheckExistingWrappers ) { $textBeforeMatch = substr( $text, 0, $m[0][1] ); $openOffset = strrpos( $textBeforeMatch, '<div class="mw-heading' ); if ( $openOffset !== false ) { $closeOffset = strpos( $textBeforeMatch, '</div>', $openOffset ); if ( $closeOffset === false ) { // Looks like we're already inside a wrapper $wrapperType = 'none'; } } } // Do not add the wrapper if the heading has attributes generated from wikitext (T353489). // In this case it's also guaranteed that there's no edit link, so we don't need wrappers. foreach ( $attrs as $name => $value ) { if ( !Sanitizer::isReservedDataAttribute( $name ) ) { $wrapperType = 'none'; } } } else { $wrapperType = 'legacy'; } return $this->makeHeading( (int)$m['level'][0], $attrs, $anchor, $contents, $editlink, $fallbackAnchor, $wrapperType ); }, $text, -1, $count, PREG_OFFSET_CAPTURE ); } /** * @param int $level The level of the headline (1-6) * @param array $attrs HTML attributes * @param string $anchor The anchor to give the headline (the bit after the #) * @param string $html HTML for the text of the header * @param string $link HTML to add for the section edit link * @param string|false $fallbackAnchor A second, optional anchor to give for * backward compatibility (false to omit) * @param string $wrapperType 'legacy', 'mwheading' or 'none' * @return string HTML headline */ private function makeHeading( $level, $attrs, $anchor, $html, $link, $fallbackAnchor, string $wrapperType ) { $anchorEscaped = htmlspecialchars( $anchor, ENT_COMPAT ); $fallback = ''; if ( $fallbackAnchor !== false && $fallbackAnchor !== $anchor ) { $fallbackAnchor = htmlspecialchars( $fallbackAnchor, ENT_COMPAT ); $fallback = "<span id=\"$fallbackAnchor\"></span>"; } switch ( $wrapperType ) { case 'legacy': return "<h$level" . Html::expandAttributes( $attrs ) . ">" . "$fallback<span class=\"mw-headline\" id=\"$anchorEscaped\">$html</span>" . $link . "</h$level>"; case 'mwheading': return "<div class=\"mw-heading mw-heading$level\">" . "<h$level id=\"$anchorEscaped\"" . Html::expandAttributes( $attrs ) . ">$fallback$html</h$level>" . $link . "</div>"; case 'none': return "<h$level id=\"$anchorEscaped\"" . Html::expandAttributes( $attrs ) . ">$fallback$html</h$level>" . $link; default: throw new LogicException( "Bad wrapper type: $wrapperType" ); } } private function addSectionLinks( string $text, ParserOutput $po, array $options ): string { $skin = $this->resolveSkin( $options ); if ( !$skin ) { // Should be unreachable return $text; } $titleText = $po->getTitleText(); return preg_replace_callback( self::EDITSECTION_REGEX, function ( $m ) use ( $skin, $titleText ) { $editsectionPage = $this->titleFactory->newFromTextThrow( htmlspecialchars_decode( $m[1] ) ); $editsectionSection = htmlspecialchars_decode( $m[2] ); $editsectionContent = Sanitizer::decodeCharReferences( $m[3] ); return $skin->doEditSectionLink( $editsectionPage, $editsectionSection, $editsectionContent, $skin->getLanguage() ); }, $text ); } /** * Extracts the skin from the $options array, with a fallback on request context skin * @param array $options * @return ?Skin */ private function resolveSkin( array $options ): ?Skin { $skin = $options[ 'skin' ] ?? null; if ( !$skin ) { if ( defined( 'MW_NO_SESSION' ) ) { return null; } // T348853 passing $skin will be mandatory in the future $skin = RequestContext::getMain()->getSkin(); } return $skin; } }
| ver. 1.1 | |
.
| PHP 8.4.18 | Ð“ÐµÐ½ÐµÑ€Ð°Ñ†Ð¸Ñ Ñтраницы: 0 |
proxy
|
phpinfo
|
ÐаÑтройка