���ѧۧݧ�ӧ�� �ާ֧ߧ֧էا֧� - ���֧էѧܧ�ڧ��ӧѧ�� - /home/rickpfrv/wiki.craftaro.com/vendor/wikimedia/parsoid/src/Tokens/Token.php
���ѧ٧ѧ�
<?php declare( strict_types = 1 ); namespace Wikimedia\Parsoid\Tokens; use stdClass; use Wikimedia\Assert\Assert; use Wikimedia\Parsoid\Core\DomSourceRange; use Wikimedia\Parsoid\NodeData\DataParsoid; use Wikimedia\Parsoid\Utils\PHPUtils; use Wikimedia\Parsoid\Wt2Html\Frame; /** * Catch-all class for all token types. */ abstract class Token implements \JsonSerializable { /** @var DataParsoid|null */ public $dataAttribs; /** @var KV[] */ public $attribs; /** * @inheritDoc */ #[\ReturnTypeWillChange] abstract public function jsonSerialize(); /** * Get a name for the token. * Derived classes can override this. * @return string */ public function getName(): string { return $this->getType(); } /** * Returns a string key for this token * @return string */ public function getType(): string { $classParts = explode( '\\', get_class( $this ) ); return end( $classParts ); } /** * Generic set attribute method. * * @param string $name * Always a string when used this way. * The more complex form (where the key is a non-string) are found when * KV objects are constructed in the tokenizer. * @param string|Token|array<Token|string> $value * @param ?KVSourceRange $srcOffsets */ public function addAttribute( string $name, $value, ?KVSourceRange $srcOffsets = null ): void { $this->attribs[] = new KV( $name, $value, $srcOffsets ); } /** * Generic set attribute method with support for change detection. * Set a value and preserve the original wikitext that produced it. * * @param string $name * @param string|Token|Token[] $value * @param mixed $origValue */ public function addNormalizedAttribute( string $name, $value, $origValue ): void { $this->addAttribute( $name, $value ); $this->setShadowInfo( $name, $value, $origValue ); } /** * Generic attribute accessor. * * @param string $name * @return string|Token|Token[]|KV[]|null */ public function getAttribute( string $name ) { return KV::lookup( $this->attribs, $name ); } /** * Generic attribute accessor. * * @param string $name * @return KV|null */ public function getAttributeKV( string $name ) { return KV::lookupKV( $this->attribs, $name ); } /** * Generic attribute accessor. * * @param string $name * @return bool */ public function hasAttribute( string $name ): bool { return $this->getAttributeKV( $name ) !== null; } /** * Set an unshadowed attribute. * * @param string $name * @param string|Token|Token[] $value */ public function setAttribute( string $name, $value ): void { // First look for the attribute and change the last match if found. for ( $i = count( $this->attribs ) - 1; $i >= 0; $i-- ) { $kv = $this->attribs[$i]; $k = $kv->k; if ( is_string( $k ) && mb_strtolower( $k ) === $name ) { $kv->v = $value; $this->attribs[$i] = $kv; return; } } // Nothing found, just add the attribute $this->addAttribute( $name, $value ); } /** * Store the original value of an attribute in a token's dataAttribs. * * @param string $name * @param mixed $value * @param mixed $origValue */ public function setShadowInfo( string $name, $value, $origValue ): void { // Don't shadow if value is the same or the orig is null if ( $value !== $origValue && $origValue !== null ) { if ( !isset( $this->dataAttribs->a ) ) { $this->dataAttribs->a = []; } $this->dataAttribs->a[$name] = $value; if ( !isset( $this->dataAttribs->sa ) ) { $this->dataAttribs->sa = []; } $this->dataAttribs->sa[$name] = $origValue; } } /** * Attribute info accessor for the wikitext serializer. Performs change * detection and uses unnormalized attribute values if set. Expects the * context to be set to a token. * * @param string $name * @return array Information about the shadow info attached to this attribute: * - value: (Token|Token[]|string) * When modified is false and fromsrc is true, this is always a string. * - modified: (bool) * - fromsrc: (bool) */ public function getAttributeShadowInfo( string $name ): array { $curVal = $this->getAttribute( $name ); // Not the case, continue regular round-trip information. if ( !property_exists( $this->dataAttribs, 'a' ) || !array_key_exists( $name, $this->dataAttribs->a ) ) { return [ "value" => $curVal, // Mark as modified if a new element "modified" => $this->dataAttribs->isModified(), "fromsrc" => false ]; } elseif ( $this->dataAttribs->a[$name] !== $curVal ) { return [ "value" => $curVal, "modified" => true, "fromsrc" => false ]; } elseif ( !property_exists( $this->dataAttribs, 'sa' ) || !array_key_exists( $name, $this->dataAttribs->sa ) ) { return [ "value" => $curVal, "modified" => false, "fromsrc" => false ]; } else { return [ "value" => $this->dataAttribs->sa[$name], "modified" => false, "fromsrc" => true ]; } } /** * Completely remove all attributes with this name. * * @param string $name */ public function removeAttribute( string $name ): void { $out = []; $attribs = $this->attribs; // FIXME: Could use array_filter for ( $i = 0, $l = count( $attribs ); $i < $l; $i++ ) { $kv = $attribs[$i]; if ( mb_strtolower( $kv->k ) !== $name ) { $out[] = $kv; } } $this->attribs = $out; } /** * Add a space-separated property value. * These are Parsoid-added attributes, not something present in source. * So, only a regular ASCII space characters will be used here. * * @param string $name The attribute name * @param string $value The value to add to the attribute */ public function addSpaceSeparatedAttribute( string $name, string $value ): void { $curVal = $this->getAttributeKV( $name ); if ( $curVal !== null ) { if ( in_array( $value, explode( ' ', $curVal->v ), true ) ) { // value is already included, nothing to do. return; } // Value was not yet included in the existing attribute, just add // it separated with a space $this->setAttribute( $curVal->k, $curVal->v . ' ' . $value ); } else { // the attribute did not exist at all, just add it $this->addAttribute( $name, $value ); } } /** * Get the wikitext source of a token. * * @param Frame $frame * @return string */ public function getWTSource( Frame $frame ): string { $tsr = $this->dataAttribs->tsr ?? null; if ( !( $tsr instanceof SourceRange ) ) { throw new InvalidTokenException( 'Expected token to have tsr info.' ); } $srcText = $frame->getSrcText(); Assert::invariant( $tsr->end >= $tsr->start, 'Bad TSR' ); return $tsr->substr( $srcText ); } /** * Create key value set from an array * * @param array $a * @return array */ private static function kvsFromArray( array $a ): array { $kvs = []; foreach ( $a as $e ) { if ( is_array( $e["k"] ?? null ) ) { self::rebuildNestedTokens( $e["k"] ); } $v = $e['v'] ?? null; if ( is_array( $v ) ) { // $v is either an array of Tokens or an array of KVs if ( count( $v ) > 0 ) { if ( is_array( $v[0] ) && array_key_exists( 'k', $v[0] ) ) { $v = self::kvsFromArray( $v ); } else { self::rebuildNestedTokens( $v ); } } } $so = $e["srcOffsets"] ?? null; if ( $so ) { $so = KVSourceRange::fromArray( $so ); } $kvs[] = new KV( $e["k"] ?? null, $v, $so, $e["ksrc"] ?? null, $e["vsrc"] ?? null ); } return $kvs; } /** * @param iterable|stdClass|DataParsoid &$a */ private static function rebuildNestedTokens( &$a ): void { // objects do not count as iterables in PHP but can be iterated nevertheless // @phan-suppress-next-line PhanTypeSuspiciousNonTraversableForeach foreach ( $a as &$v ) { $v = self::getToken( $v ); } unset( $v ); // Future-proof protection } /** * Get a token from some PHP structure. Used by the PHPUnit tests. * * @param KV|Token|array|string|int|float|bool|null $input * @return Token|string|int|float|bool|null|array<Token|string|int|float|bool|null> */ public static function getToken( $input ) { if ( !$input ) { return $input; } if ( is_array( $input ) && isset( $input['type'] ) ) { if ( isset( $input['dataAttribs'] ) ) { $da = new DataParsoid; foreach ( $input['dataAttribs'] as $key => $value ) { switch ( $key ) { case 'tmp': $tmp = $da->getTemp(); foreach ( $value as $key2 => $value2 ) { $tmp->$key2 = $value2; } break; case 'dsr': // dsr is generally for DOM trees, not Tokens. $da->dsr = DomSourceRange::fromArray( $value ); break; case 'tsr': $da->tsr = SourceRange::fromArray( $value ); break; case 'extTagOffsets': $da->extTagOffsets = DomSourceRange::fromArray( $value ); break; case 'extLinkContentOffsets': $da->extLinkContentOffsets = SourceRange::fromArray( $value ); break; default: $da->$key = $value; } } } else { $da = null; } switch ( $input['type'] ) { case "SelfclosingTagTk": $token = new SelfclosingTagTk( $input['name'], self::kvsFromArray( $input['attribs'] ), $da ); break; case "TagTk": $token = new TagTk( $input['name'], self::kvsFromArray( $input['attribs'] ), $da ); break; case "EndTagTk": $token = new EndTagTk( $input['name'], self::kvsFromArray( $input['attribs'] ), $da ); break; case "NlTk": $token = new NlTk( $da->tsr ?? null, $da ); break; case "EOFTk": $token = new EOFTk(); break; case "CommentTk": $token = new CommentTk( $input["value"], $da ); break; default: // Looks like data-parsoid can have a 'type' property in some cases // We can change that usage and then throw an exception here $token = &$input; } } elseif ( is_array( $input ) ) { $token = &$input; } else { $token = $input; } if ( is_array( $token ) ) { self::rebuildNestedTokens( $token ); } else { if ( !empty( $token->attribs ) ) { self::rebuildNestedTokens( $token->attribs ); } if ( !empty( $token->dataAttribs ) ) { self::rebuildNestedTokens( $token->dataAttribs ); } } return $token; } /** * @param string $key * @return ?string */ public function fetchExpandedAttrValue( string $key ): ?string { if ( preg_match( '/mw:ExpandedAttrs/', $this->getAttribute( 'typeof' ) ?? '' ) ) { $attribs = PHPUtils::jsonDecode( $this->getAttribute( 'data-mw' ), false )->attribs; foreach ( $attribs as $attr ) { if ( $attr[0]->txt === $key ) { return $attr[1]->html; } } } return null; } }
| ver. 1.4 |
Github
|
.
| PHP 7.4.33 | ���֧ߧ֧�ѧ�ڧ� ����ѧߧڧ��: 0.02 |
proxy
|
phpinfo
|
���ѧ����ۧܧ�