Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
| Total | |
91.11% |
41 / 45 |
|
66.67% |
2 / 3 |
CRAP | |
0.00% |
0 / 1 |
| BabelAutoCreate | |
91.11% |
41 / 45 |
|
66.67% |
2 / 3 |
13.12 | |
0.00% |
0 / 1 |
| create | |
87.50% |
28 / 32 |
|
0.00% |
0 / 1 |
9.16 | |||
| user | |
100.00% |
2 / 2 |
|
100.00% |
1 / 1 |
1 | |||
| getCategoryText | |
100.00% |
11 / 11 |
|
100.00% |
1 / 1 |
3 | |||
| 1 | <?php |
| 2 | /** |
| 3 | * Code for automatic creation of categories. |
| 4 | * |
| 5 | * @file |
| 6 | * @author Robert Leverington |
| 7 | * @author Robin Pepermans |
| 8 | * @author Niklas Laxström |
| 9 | * @author Brian Wolff |
| 10 | * @author Purodha Blissenbach |
| 11 | * @author Sam Reed |
| 12 | * @author Siebrand Mazeland |
| 13 | * @author Winston Sung |
| 14 | * @license GPL-2.0-or-later |
| 15 | */ |
| 16 | |
| 17 | declare( strict_types = 1 ); |
| 18 | |
| 19 | namespace MediaWiki\Babel; |
| 20 | |
| 21 | use MediaWiki\CommentStore\CommentStoreComment; |
| 22 | use MediaWiki\Content\ContentHandler; |
| 23 | use MediaWiki\Deferred\DeferredUpdates; |
| 24 | use MediaWiki\MainConfigNames; |
| 25 | use MediaWiki\MediaWikiServices; |
| 26 | use MediaWiki\Revision\SlotRecord; |
| 27 | use MediaWiki\Title\Title; |
| 28 | use MediaWiki\User\User; |
| 29 | use RecentChange; |
| 30 | |
| 31 | /** |
| 32 | * Class for automatic creation of Babel category pages. |
| 33 | */ |
| 34 | class BabelAutoCreate { |
| 35 | public const MSG_USERNAME = 'babel-autocreate-user'; |
| 36 | |
| 37 | /** |
| 38 | * Create category. |
| 39 | * |
| 40 | * @param string $category Name of category to create. |
| 41 | * @param string $text Text to use when creating the category. |
| 42 | */ |
| 43 | public static function create( string $category, string $text ): void { |
| 44 | $category = strip_tags( $category ); |
| 45 | $title = Title::makeTitleSafe( NS_CATEGORY, $category ); |
| 46 | # T170654: We need to check whether non-existing category page in one language variant actually |
| 47 | # exists in another language variant when a language supports multiple language variants. |
| 48 | MediaWikiServices::getInstance()->getLanguageConverterFactory()->getLanguageConverter() |
| 49 | ->findVariantLink( $category, $title, true ); |
| 50 | DeferredUpdates::addCallableUpdate( function () use ( $title, $text ) { |
| 51 | $mwServices = MediaWikiServices::getInstance(); |
| 52 | // Extra exists check here in case the category was created while this code was running |
| 53 | if ( $title === null || $title->exists() ) { |
| 54 | return; |
| 55 | } |
| 56 | |
| 57 | $user = self::user(); |
| 58 | # Do not add a message if the username is invalid or if the account that adds it, is blocked |
| 59 | if ( !$user || $user->getBlock() ) { |
| 60 | return; |
| 61 | } |
| 62 | |
| 63 | if ( !$mwServices->getPermissionManager() |
| 64 | ->quickUserCan( 'create', $user, $title ) |
| 65 | ) { |
| 66 | # The Babel AutoCreate account is not allowed to create the page |
| 67 | return; |
| 68 | } |
| 69 | |
| 70 | $pageUpdater = $mwServices |
| 71 | ->getWikiPageFactory() |
| 72 | ->newFromTitle( $title ) |
| 73 | ->newPageUpdater( $user ) |
| 74 | ->setContent( SlotRecord::MAIN, ContentHandler::makeContent( $text, $title ) ) |
| 75 | ->setFlags( EDIT_FORCE_BOT ); |
| 76 | |
| 77 | $config = $mwServices->getMainConfig(); |
| 78 | |
| 79 | $useNPPatrol = $config->get( MainConfigNames::UseNPPatrol ); |
| 80 | $useRCPatrol = $config->get( MainConfigNames::UseRCPatrol ); |
| 81 | $needsPatrol = $useRCPatrol || $useNPPatrol; |
| 82 | |
| 83 | if ( $needsPatrol && $user->authorizeWrite( 'autopatrol', $title ) ) { |
| 84 | $pageUpdater->setRcPatrolStatus( RecentChange::PRC_AUTOPATROLLED ); |
| 85 | } |
| 86 | |
| 87 | $url = wfMessage( 'babel-url' )->inContentLanguage()->plain(); |
| 88 | $commentStoreComment = CommentStoreComment::newUnsavedComment( |
| 89 | wfMessage( 'babel-autocreate-reason', $url ) |
| 90 | ); |
| 91 | $pageUpdater->saveRevision( $commentStoreComment ); |
| 92 | } ); |
| 93 | } |
| 94 | |
| 95 | /** |
| 96 | * Get user object. |
| 97 | * |
| 98 | * @return User|null User object for autocreate user, null if invalid. |
| 99 | */ |
| 100 | public static function user(): ?User { |
| 101 | $userName = wfMessage( self::MSG_USERNAME )->inContentLanguage()->plain(); |
| 102 | return User::newSystemUser( $userName, [ 'steal' => true ] ); |
| 103 | } |
| 104 | |
| 105 | /** |
| 106 | * Returns the text to use when creating a babel category with the given code and level |
| 107 | * @param string $code Code of language that the category is for. |
| 108 | * @param string|null $level Level that the category is for. |
| 109 | * @param string|null $parent An eventual parent category to add to the newly-created category if one is created. |
| 110 | * @return string The text to use to create the category. |
| 111 | */ |
| 112 | public static function getCategoryText( string $code, ?string $level, ?string $parent ): string { |
| 113 | global $wgLanguageCode; |
| 114 | $language = BabelLanguageCodes::getName( $code, $wgLanguageCode ); |
| 115 | if ( !$parent ) { |
| 116 | $parent = ""; |
| 117 | } else { |
| 118 | $sortkey = $level ?? $code; |
| 119 | $parent = "[[Category:$parent|{$sortkey}]]"; |
| 120 | } |
| 121 | $params = [ $language, $code, $parent ]; |
| 122 | if ( $level === null ) { |
| 123 | $text = wfMessage( 'babel-autocreate-text-main', $params )->inContentLanguage()->plain(); |
| 124 | } else { |
| 125 | array_unshift( $params, $level ); |
| 126 | $text = wfMessage( 'babel-autocreate-text-levels', $params )->inContentLanguage()->plain(); |
| 127 | } |
| 128 | return $text; |
| 129 | } |
| 130 | } |