mirror of
https://gerrit.wikimedia.org/r/mediawiki/extensions/DiscussionTools
synced 2024-11-27 09:43:30 +00:00
The Great Parser JS to PHP port of 2020!*
* Not to be confused with the Parsing Team's "Great Parser JS to PHP port of 2019" Gasp as OR hacks are changed to null coalescing operators. Applaud as variable declarations are dropped. Cheer as parameters and return values are type-hinted. Shudder as DomNodeLists have no indexOf method. Moving discussion parsing to the server should allow us to implement much cleaner APIs for commenting. Bug: T252252 Co-authored-by: Ed Sanders <esanders@wikimedia.org> Change-Id: Ic1438d516e223db462cb227f6668e856672f538c
This commit is contained in:
parent
111dbeba9a
commit
7b7a2cd69c
|
@ -1,6 +1,8 @@
|
||||||
<?xml version="1.0"?>
|
<?xml version="1.0"?>
|
||||||
<ruleset>
|
<ruleset>
|
||||||
<rule ref="./vendor/mediawiki/mediawiki-codesniffer/MediaWiki" />
|
<rule ref="./vendor/mediawiki/mediawiki-codesniffer/MediaWiki">
|
||||||
|
<exclude name="MediaWiki.ControlStructures.AssignmentInControlStructures.AssignmentInControlStructures" />
|
||||||
|
</rule>
|
||||||
<file>.</file>
|
<file>.</file>
|
||||||
<arg name="extensions" value="php,php5,inc" />
|
<arg name="extensions" value="php,php5,inc" />
|
||||||
<arg name="encoding" value="UTF-8" />
|
<arg name="encoding" value="UTF-8" />
|
||||||
|
|
|
@ -225,6 +225,7 @@
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"AutoloadClasses": {
|
"AutoloadClasses": {
|
||||||
|
"DiscussionToolsCommentParser": "includes/DiscussionToolsCommentParser.php",
|
||||||
"DiscussionToolsData": "includes/DiscussionToolsData.php",
|
"DiscussionToolsData": "includes/DiscussionToolsData.php",
|
||||||
"DiscussionToolsHooks": "includes/DiscussionToolsHooks.php"
|
"DiscussionToolsHooks": "includes/DiscussionToolsHooks.php"
|
||||||
},
|
},
|
||||||
|
|
1103
includes/DiscussionToolsCommentParser.php
Normal file
1103
includes/DiscussionToolsCommentParser.php
Normal file
File diff suppressed because it is too large
Load diff
124
tests/phpunit/DiscussionToolsCommentParserTest.php
Normal file
124
tests/phpunit/DiscussionToolsCommentParserTest.php
Normal file
|
@ -0,0 +1,124 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
use Wikimedia\TestingAccessWrapper;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @coversDefaultClass DiscussionToolsCommentParser
|
||||||
|
*/
|
||||||
|
class DiscussionToolsCommentParserTest extends MediaWikiTestCase {
|
||||||
|
|
||||||
|
private static function getJson( $relativePath ) {
|
||||||
|
$json = json_decode(
|
||||||
|
// TODO: Move cases out of /qunit
|
||||||
|
file_get_contents( __DIR__ . '/../qunit/' . $relativePath ),
|
||||||
|
true
|
||||||
|
);
|
||||||
|
return $json;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dataProvider provideTimestampRegexps
|
||||||
|
* @covers ::getTimestampRegexp
|
||||||
|
*/
|
||||||
|
public function testGetTimestampRegexp( $format, $expected, $message ) {
|
||||||
|
$parser = TestingAccessWrapper::newFromObject(
|
||||||
|
DiscussionToolsCommentParser::newFromGlobalState()
|
||||||
|
);
|
||||||
|
|
||||||
|
// HACK: Fix differences between JS & PHP regexes
|
||||||
|
// TODO: We may just have to have two version in the test data
|
||||||
|
$expected = preg_replace( '/\\\\u([0-9A-F]+)/', '\\\\x{$1}', $expected );
|
||||||
|
$expected = str_replace( ':', '\:', $expected );
|
||||||
|
$expected = '/' . $expected . '/u';
|
||||||
|
|
||||||
|
$result = $parser->getTimestampRegexp( $format, '\\d', [ 'UTC' => 'UTC' ] );
|
||||||
|
self::assertSame( $expected, $result, $message );
|
||||||
|
}
|
||||||
|
|
||||||
|
public function provideTimestampRegexps() {
|
||||||
|
return self::getJson( './cases/timestamp-regex.json' );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dataProvider provideTimestampParser
|
||||||
|
* @covers ::getTimestampParser
|
||||||
|
*/
|
||||||
|
public function testGetTimestampParser( $format, $data, $expected, $message ) {
|
||||||
|
$parser = TestingAccessWrapper::newFromObject(
|
||||||
|
DiscussionToolsCommentParser::newFromGlobalState()
|
||||||
|
);
|
||||||
|
|
||||||
|
$expected = new DateTimeImmutable( $expected );
|
||||||
|
|
||||||
|
$tsParser = $parser->getTimestampParser( $format, null, 'UTC', [ 'UTC' => 'UTC' ] );
|
||||||
|
self::assertEquals( $expected, $tsParser( $data ), $message );
|
||||||
|
}
|
||||||
|
|
||||||
|
public function provideTimestampParser() {
|
||||||
|
return self::getJson( './cases/timestamp-parser.json' );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dataProvider provideTimestampParserDST
|
||||||
|
* @covers ::getTimestampParser
|
||||||
|
*/
|
||||||
|
public function testGetTimestampParserDST(
|
||||||
|
$sample, $expected, $expectedUtc, $format, $timezone, $timezoneAbbrs, $message
|
||||||
|
) {
|
||||||
|
$parser = TestingAccessWrapper::newFromObject(
|
||||||
|
DiscussionToolsCommentParser::newFromGlobalState()
|
||||||
|
);
|
||||||
|
|
||||||
|
$regexp = $parser->getTimestampRegexp( $format, '\\d', $timezoneAbbrs );
|
||||||
|
$tsParser = $parser->getTimestampParser( $format, null, $timezone, $timezoneAbbrs );
|
||||||
|
|
||||||
|
$expected = new DateTimeImmutable( $expected );
|
||||||
|
$expectedUtc = new DateTimeImmutable( $expectedUtc );
|
||||||
|
|
||||||
|
preg_match( $regexp, $sample, $match, PREG_OFFSET_CAPTURE );
|
||||||
|
$date = $tsParser( $match );
|
||||||
|
|
||||||
|
self::assertEquals( $expected, $date, $message );
|
||||||
|
self::assertEquals( $expectedUtc, $date, $message );
|
||||||
|
}
|
||||||
|
|
||||||
|
public function provideTimestampParserDST() {
|
||||||
|
return self::getJson( './cases/timestamp-parser-dst.json' );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dataProvider provideAuthors
|
||||||
|
* @covers ::getAuthors
|
||||||
|
*/
|
||||||
|
public function testGetAuthors( $thread, $expected ) {
|
||||||
|
$parser = DiscussionToolsCommentParser::newFromGlobalState();
|
||||||
|
|
||||||
|
self::assertEquals( $expected, $parser->getAuthors( $thread ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
public function provideAuthors() {
|
||||||
|
return [
|
||||||
|
[
|
||||||
|
'thread' => (object)[
|
||||||
|
'replies' => [
|
||||||
|
(object)[
|
||||||
|
'author' => 'Eve',
|
||||||
|
'replies' => []
|
||||||
|
],
|
||||||
|
(object)[
|
||||||
|
'author' => 'Bob',
|
||||||
|
'replies' => [
|
||||||
|
(object)[
|
||||||
|
'author' => 'Alice',
|
||||||
|
'replies' => []
|
||||||
|
]
|
||||||
|
]
|
||||||
|
]
|
||||||
|
|
||||||
|
]
|
||||||
|
],
|
||||||
|
'expected' => [ 'Alice', 'Bob', 'Eve' ]
|
||||||
|
]
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue