Mollywhite has submitted this change and it was merged.

Change subject: Bug 50957: Populate navbar from JSON block.
......................................................................


Bug 50957: Populate navbar from JSON block.

The chapterlist, metadata, and previous/next links are now
populated from the page's corresponding JSON block. A category
on each section of the book (of the form
[[Category:Book:Book Title]]) indicates which Book: JSON block
belongs to the book. It then pulls in the JSON and populates
the navbar from that.

This is a pretty huge commit, and since I'm not just tweaking
someone else's code, I'm going to wait for some reviews before
merging this in.

Bug: 50957
Change-Id: I9c2d77ce649c678ae34343032ef68b2b673dc92e
---
M BookManagerv2.hooks.php
M BookManagerv2.i18n.php
2 files changed, 348 insertions(+), 59 deletions(-)

Approvals:
  Mollywhite: Verified; Looks good to me, approved
  jenkins-bot: Checked



diff --git a/BookManagerv2.hooks.php b/BookManagerv2.hooks.php
index c90fd35..868987d 100644
--- a/BookManagerv2.hooks.php
+++ b/BookManagerv2.hooks.php
@@ -5,6 +5,8 @@
  * @file
  * @ingroup Extensions
  *
+ * @author Molly White
+ *
  * @section LICENSE
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
@@ -23,95 +25,338 @@
 
 class BookManagerv2Hooks {
 
-       public static function readingInterfaceUX( $out, $prev, $next, 
$chapterList, $metadata ) {
+       /**
+        * Adds a navigation bar to the page
+        *
+        * @param object $prev Object representing the preceding page; contains
+        *              "link" and "name" properties.
+        * @param object $next Object representing the following page; contains
+        *              "link" and "name" properties.
+        * @param string $chapterList String containing the chapter list HTML
+        * @param string $metadata String containing the metadata HTML
+        * @return string HTML string
+        */
+       public static function readingInterfaceUX( $prev, $next, $chapterList, 
$metadata ) {
                global $wgExtensionAssetsPath;
                $imagePath = $wgExtensionAssetsPath . "/BookManagerv2/images/";
 
-               $html = Html::openElement( 'div', array( 'class' => 
'mw-bookmanagerv2-nav-wrap' ) )
-                       . Html::openElement( 'div', array( 'class' => 
'mw-bookmanagerv2-nav-constrain' ) )
-                       . Html::openElement( 'div', array( 'class' => 
'mw-bookmanagerv2-nav-bar' ) )
-                       . Html::openElement( 'a', array(
+               $html = array();
+               $html[] = Html::openElement( 'div', array( 'class' => 
'mw-bookmanagerv2-nav-wrap' ) );
+               $html[] = Html::openElement( 'div', array( 'class' => 
'mw-bookmanagerv2-nav-constrain' ) );
+               $html[] = Html::openElement( 'div', array( 'class' => 
'mw-bookmanagerv2-nav-bar' ) );
+               $html[] = Html::openElement( 'a', array(
                                'class' => array(
                                        'mw-bookmanagerv2-nav-icon',
-                                       'mw-bookmanagerv2-nav-data' )
+                                       'mw-bookmanagerv2-nav-data' )
                                )
-                       )
-                       . Html::element( 'img', array(
+                       );
+               $html[] = Html::element( 'img', array(
                                'class' => 'mw-bookmanagerv2-nav-data',
                                'src' => $imagePath . 
'Info_sign_font_awesome.png'
-                       ), '' )
-                       . Html::closeElement( 'a' )
-                       . Html::openElement( 'a', array(
+                       ), '' );
+               $html[] = Html::closeElement( 'a' );
+               $html[] = Html::openElement( 'a', array(
                                'class' => array(
                                        'mw-bookmanagerv2-nav-icon',
                                        'mw-bookmanagerv2-nav-toc' )
                                )
-                       )
-                       . Html::element( 'img', array(
+                       );
+               $html[] = Html::element( 'img', array(
                                'class' => 'mw-bookmanagerv2-nav-toc',
                                'src' => $imagePath . 'Ul_font_awesome.png'
-                       ), '' )
-                       . Html::closeElement( 'a' )
-                       . Html::openElement( 'a', array(
-                               'class' => 'mw-bookmanagerv2-nav-prev',
-                               'href' => $prev->link )
-                       )
-                       . Html::element( 'img', array(
-                               'class' => 'mw-bookmanagerv2-nav-prev',
-                               'src' => $imagePath . 
'Angle_left_font_awesome.png'
-                       ), '' )
-                       . $prev->title
-                       . Html::closeElement( 'a' )
-                       . Html::openElement( 'a', array(
-                               'class' => 'mw-bookmanagerv2-nav-next',
-                               'href' => $next->link )
-                       )
-                       . $next->title
-                       . Html::element( 'img', array(
-                               'class' => 'mw-bookmanagerv2-nav-next',
-                               'src' => $imagePath . 
'Angle_right_font_awesome.png'
-                       ), '' )
-                       . Html::closeElement( 'a' )
-                       . Html::closeElement( 'div' )
-                       . Html::rawElement( 'div', array(
+                       ), '' );
+               $html[] = Html::closeElement( 'a' );
+               if ( $prev ) {
+                       $linkContents = array();
+                   $linkContents[] = Html::element( 'img', array(
+                                       'class' => 'mw-bookmanagerv2-nav-prev',
+                                       'src' => $imagePath . 
'Angle_left_font_awesome.png'
+                               ), '' );
+                       $linkContents[] = $prev->title;
+                       $html[] = Linker::link(
+                               Title::newFromText( $prev->link ),
+                               implode( $linkContents ),
+                               array( 'class' => 'mw-bookmanagerv2-nav-prev' )
+                       );
+               }
+               if ( $next ) {
+                       $linkContents = array();
+                   $linkContents[] = $next->title;
+                       $linkContents[] = Html::element( 'img', array(
+                                       'class' => 'mw-bookmanagerv2-nav-next',
+                                       'src' => $imagePath . 
'Angle_right_font_awesome.png'
+                               ), '' );
+                       $html[] = Linker::link(
+                               Title::newFromText( $next->link ),
+                               implode( $linkContents ),
+                               array( 'class' => 'mw-bookmanagerv2-nav-next' )
+                       );
+               }
+               $html[] = Html::closeElement( 'div' );
+               $html[] = Html::rawElement( 'div', array(
                                'class' => array(
                                        'mw-bookmanagerv2-nav-dropdown',
                                        'mw-bookmanagerv2-nav-data' )
                                ),
                                $metadata
-                       )
-                       . Html::rawElement( 'div', array(
+                       );
+               $html[] = Html::rawElement( 'div', array(
                                'class' => array(
                                        'mw-bookmanagerv2-nav-dropdown',
                                        'mw-bookmanagerv2-nav-toc' )
                                ),
                                $chapterList
-                       )
-                       . Html::closeElement( 'div' )
-                       . Html::closeElement( 'div' );
-
-                       $out->prependHTML( $html );
+                       );
+               $html[] = Html::closeElement( 'div' );
+               $html[] = Html::closeElement( 'div' );
+               return implode( $html );
        }
 
+       /**
+        * Pulls the text from an indicated page, decodes it as JSON.
+        *
+        * @param Title $title Title of the page from which the JSON is pulled
+        * @return object JSON object
+        */
+       public static function getJson( Title $title ) {
+               if ( !$title->exists() ) {
+                       return false;
+               }
+               $jsonPage = WikiPage::factory( $title );
+               return json_decode( $jsonPage->getText( Revision::FOR_PUBLIC ) 
);
+       }
+
+       /**
+        * Creates a list item element with a comma-separated list of the array 
values
+        *
+        * @param string $key Name of the JSON property
+        * @param array $array Array of strings
+        * @return string HTML list item element
+        */
+       public static function addArray( $key, $array ) {
+               global $wgContLang;
+               $output = Html::element( 'li', array(),
+                       wfMessage( 'bookmanagerv2-' . $key )
+                               ->numParams( count( $array ) )
+                               ->params( $wgContLang->commaList( $array ) )
+                               ->text() );
+               return $output;
+       }
+
+       /**
+        * Creates a list item element with a string
+        *
+        * @param string $key Name of the JSON property
+        * @param string $string Name of the string value
+        * @return string HTML list item element
+        */
+       public static function addString( $key, $string ) {
+               $output = Html::element( 'li', array(),
+                       wfMessage( 'bookmanagerv2-' . $key, $string )->text() );
+               return $output;
+       }
+
+       /**
+        * Creates a list item element with a date.
+        *
+        * @param int|null $year Year
+        * @param int|null $month Month
+        * @param int|null $day Day
+        * @return string HTML list item element
+        */
+       public static function addDate( $year, $month, $day ) {
+               //TODO: This needs to be localized.
+               $output = array();
+               $output[] = Html::openElement( 'li', array() );
+               if ( $day && !$month ) {
+                       //Having a day without a month doesn't make much sense
+                       $date = $year;
+               } else {
+                       $date = array();
+                       $date[] = $day ? $day . "/" : "";
+                       $date[] = $month ? $month . "/" : "";
+                       $date[] = $year ? $year : "";
+                       $date = implode( $date );
+               }
+               $output[] = wfMessage( 'bookmanagerv2-publication-date',
+                       $date )->text();
+               $output[] = Html::closeElement( 'li' );
+               return implode( $output );
+       }
+
+       /**
+        * Generates HTML for the chapter list. All pages except the current one
+        * will be linked.
+        *
+        * @param object $sections Sections property of the JSON
+        * @param string $currentPageTitle Title of the page that's being viewed
+        * @return string HTML ordered list element
+        */
+       public static function formatChapterList( $sections, $currentPageTitle 
) {
+               $html = array();
+               $html[] = Html::openElement( 'ol', array() );
+               foreach ( $sections as $key => $val ) {
+                       if ( $val->link !== $currentPageTitle ) {
+                               $html[] = Html::openElement( 'li', array() );
+                               $html[] = Linker::link(
+                                               Title::newFromText( $val->link 
),
+                                               $val->name
+                                       );
+                               $html[] = Html::closeElement( 'li' );
+                       } else {
+                               $html[] = Html::element( 'li', array(), 
$val->name );
+                       }
+               }
+               $html[] = Html::closeElement( 'ol' );
+               return implode( $html );
+       }
+
+       /**
+        * Generates HTML for the metadata list.
+        *
+        * @param object $jsonBook JSON representation of the book
+        * @return string HTML unordered list element
+        */
+       public static function formatMetadata( $jsonBook ) {
+               $metadata = array();
+               $metadata[] = Html::openElement( 'ul', array() );
+               $metadata[] = Html::openElement( 'li', array() );
+               $metadata[] = wfMessage( 'bookmanagerv2-title',
+                       $jsonBook->title)->text();
+               $metadata[] = Html::closeElement( 'li' );
+               if ( isset( $jsonBook->alternate_titles ) ) {
+                       $metadata[] = self::addArray( "alternate-titles",
+                               $jsonBook->alternate_titles );
+               }
+               if ( isset( $jsonBook->authors ) ) {
+                       $metadata[] = self::addArray( "authors", 
$jsonBook->authors );
+               }
+               if ( isset( $jsonBook->translators ) ) {
+                       $metadata[] = self::addArray( "translators",
+                               $jsonBook->translators );
+               }
+               if ( isset( $jsonBook->editors ) ) {
+                       $metadata[] = self::addArray( "editors", 
$jsonBook->editors );
+               }
+               if ( isset( $jsonBook->illustrators ) ) {
+                       $metadata[] = self::addArray( "illustrators",
+                               $jsonBook->illustrators );
+               }
+               if ( isset( $jsonBook->subtitle ) ) {
+                       $metadata[] = self::addString( "subtitle", 
$jsonBook->subtitle );
+               }
+               if ( isset( $jsonBook->series_title ) ) {
+                       $metadata[] = self::addString( "series-title",
+                               $jsonBook->series_title );
+               }
+               if ( isset( $jsonBook->volume ) ) {
+                       $metadata[] = self::addString( "volume",
+                               (string)$jsonBook->volume );
+               }
+               if ( isset( $jsonBook->edition ) ) {
+                       $metadata[] = self::addString( "edition",
+                               (string)$jsonBook->edition );
+               }
+               if ( isset( $jsonBook->publisher ) ) {
+                       $metadata[] = self::addString( "publisher", 
$jsonBook->publisher );
+               }
+               if ( isset( $jsonBook->publication_city ) ) {
+                       $metadata[] = self::addString( "publication-city",
+                               $jsonBook->publication_city );
+               }
+               if ( isset( $jsonBook->publication_year ) ) {
+                       $year = isset( $jsonBook->publication_year ) ?
+                               $jsonBook->publication_year : null;
+                       $month = isset( $jsonBook->publication_month ) ?
+                               $jsonBook->publication_month : null;
+                       $day = isset( $jsonBook->publication_day ) ?
+                               $jsonBook->publication_day : null;
+                       $metadata[] = self::addDate( $year, $month, $day );
+               }
+               if ( isset( $jsonBook->printer ) ) {
+                       $metadata[] = self::addString( "printer", 
$jsonBook->printer );
+               }
+               if ( isset( $jsonBook->language ) ) {
+                       //TODO: Transform the language code to the correct 
long-form language
+                       $metadata[] = self::addString( "language", 
$jsonBook->language );
+               }
+               if ( isset( $jsonBook->description ) ) {
+                       $metadata[] = self::addString( "description",
+                               $jsonBook->description );
+               }
+               if ( isset( $jsonBook->isbn ) ) {
+                       $metadata[] = self::addString( "isbn", $jsonBook->isbn 
);
+               }
+               if ( isset( $jsonBook->lccn ) ) {
+                       $metadata[] = self::addString( "lccn", $jsonBook->lccn 
);
+               }
+               if ( isset( $jsonBook->oclc ) ) {
+                       $metadata[] = self::addString( "oclc", $jsonBook->oclc 
);
+               }
+               $metadata[] = Html::closeElement( 'ul' );
+
+               return implode( $metadata );
+       }
+
+       /**
+        * Adds the navigation bar if the page is in the mainspace, and if it 
contains
+        * a category of the format [[Category:Book:Book Title]], where
+        * [[Book:Book Title]] is an existing page that contains a valid JSON
+        * block.
+        */
        public static function onBeforePageDisplay( OutputPage &$out, Skin 
&$skin ) {
                // Check that the navigation bar is only added to mainspace 
pages.
-               if ( $out->getTitle()->getNamespace() == NS_MAIN ) {
-                       if ( $out->getRevisionId() != null ) {
-                               $out->addModules( "ext.BookManagerv2" );
-                               $prev = (object) array( "link" => "/prev.html", 
"title" => "Previous" );
-                               $next = (object) array( "link" => "/next.html", 
"title" => "Next" );
-                               $chapterList = Html::element( 'p', array(), 
'Chapter 1' )
-                                       . Html::element( 'p', array(), 'Chapter 
2' )
-                                       . Html::element( 'p', array(), 'Chapter 
3' );
-                               $metadata = Html::openElement( 'p', array() )
-                                       . 'Title: '
-                                       . Html::element( 'span', array( 'class' 
=> 'title' ), 'Title' )
-                                       . Html::closeElement( 'p' )
-                                       . Html::element( 'p', array(), 'Author: 
Author' );
-                               self::readingInterfaceUX( $out, $prev, $next, 
$chapterList, $metadata );
+               if ( $out->getTitle()->getNamespace() === NS_MAIN ) {
+                       if ( $out->getRevisionId() !== null ) {
+                               global $wgContLang;
+                               $categories = $out->getCategories();
+                               $namespace = $wgContLang->convertNamespace( 
NS_BOOK ) . ":";
+                               foreach ( $categories as $cat ) {
+                                       if ( substr( $cat, 0, 
strlen($namespace) ) === $namespace ) {
+                                               $jsonPageTitle = 
Title::newFromText( $cat );
+                                               $jsonBook = self::getJson( 
$jsonPageTitle );
+                                               if ( $jsonBook ) {
+                                                       $out->addModules( 
"ext.BookManagerv2" );
+                                                       $currentPageTitle = 
$out->getTitle()->getText();
+                                                       $prev = (object) 
array();
+                                                       $next = (object) 
array();
+
+                                                       //Get the previous/next 
pages
+                                                       foreach ( 
$jsonBook->sections as $key => $val ) {
+                                                               if ( $val->link 
=== $currentPageTitle ) {
+                                                                       if ( 
$key !== 0 ) {
+                                                                               
$prev->title =
+                                                                               
        $jsonBook->sections[ $key - 1 ]->name;
+                                                                               
$prev->link =
+                                                                               
        $jsonBook->sections[ $key - 1 ]->link;
+                                                                       } else {
+                                                                               
$prev = null;
+                                                                       }
+                                                                       if ( 
$key !== count( $jsonBook->sections ) ) {
+                                                                               
$next->title =
+                                                                               
        $jsonBook->sections[ $key + 1 ]->name;
+                                                                               
$next->link =
+                                                                               
        $jsonBook->sections[ $key + 1 ]->link;
+                                                                       } else {
+                                                                               
$next = null;
+                                                                       }
+                                                                       break;
+                                                               }
+                                                       }
+
+                                                       $chapterList = 
self::formatChapterList(
+                                                               
$jsonBook->sections, $currentPageTitle );
+                                                       $metadata = 
self::formatMetadata( $jsonBook );
+
+                                                       $navbar = 
self::readingInterfaceUX( $prev, $next,
+                                                               $chapterList, 
$metadata );
+                                                       $out->prependHtml( 
$navbar );
+                                                       return true;
+                                               }
+                                       }
+                               }
                        }
                }
                return true;
        }
-
 }
diff --git a/BookManagerv2.i18n.php b/BookManagerv2.i18n.php
index 226724e..454b7a2 100644
--- a/BookManagerv2.i18n.php
+++ b/BookManagerv2.i18n.php
@@ -15,6 +15,28 @@
 $messages['en'] = array(
        'bookmanagerv2-desc' => 'Adds functionality to enter and store book 
metadata and structure',
        'bookmanagerv2-invalid-json' => 'Invalid JSON',
+       'bookmanagerv2-title' => 'Title: $1',
+       'bookmanagerv2-alternate-titles' => '{{PLURAL:$1|Alternate 
title|Alternate titles}}: $2',
+       'bookmanagerv2-authors' => '{{PLURAL:$1|Author|Authors}}: $2',
+       'bookmanagerv2-translators' => '{{PLURAL:$1|Translator|Translators}}: 
$2',
+       'bookmanagerv2-editors' => '{{PLURAL:$1|Editor|Editors}}: $2',
+       'bookmanagerv2-illustrators' => 
'{{PLURAL:$1|Illustrator|Illustrators}}: $2',
+       'bookmanagerv2-subtitle' => 'Subtitle: $1',
+       'bookmanagerv2-series-title' => 'Series title: $1',
+       'bookmanagerv2-volume' => 'Volume: $1',
+       'bookmanagerv2-edition' => 'Edition: $1',
+       'bookmanagerv2-publisher' => 'Publisher: $1',
+       'bookmanagerv2-printer' => 'Printer: $1',
+       'bookmanagerv2-publication-date' => 'Publication date: $1',
+       'bookmanagerv2-publication-city' => 'Publication city: $1',
+       'bookmanagerv2-language' => 'Language: $1',
+       'bookmanagerv2-description' => 'Description: $1',
+       'bookmanagerv2-source' => 'Source: $1',
+       'bookmanagerv2-permission' => 'Permission: $1',
+       'bookmanagerv2-other-versions' => '{{PLURAL:$1|Other version|Other 
versions}}: $2',
+       'bookmanagerv2-isbn' => 'ISBN: $1',
+       'bookmanagerv2-lccn' => 'LCCN: $1',
+       'bookmanagerv2-oclc' => 'OCLC: $1',
 );
 
 /** Message documentation (Message documentation)
@@ -25,6 +47,28 @@
        'bookmanagerv2-desc' => 
'{{desc|name=BookManagerv2|url=http://www.mediawiki.org/wiki/Extension:BookManagerv2}}',
        'bookmanagerv2-invalid-json' => 'Error message shown when an editor 
tries to save an invalid JSON block.
 {{Identical|Invalid JSON}}',
+       'bookmanagerv2-title' => 'Label in the navigation bar metadata 
dropdown. See [[File:BookManagerv2 navigation bar metadata dropdown.png]] for 
an example of this dropdown. ',
+       'bookmanagerv2-alternate-titles' => 'Label in the navigation bar 
metadata dropdown. See [[File:BookManagerv2 navigation bar metadata 
dropdown.png]] for an example of this dropdown. $1 is the length of the array 
of titles',
+       'bookmanagerv2-authors' => 'Label in the navigation bar metadata 
dropdown. See [[File:BookManagerv2 navigation bar metadata dropdown.png]] for 
an example of this dropdown. $1 is the length of the array of authors',
+       'bookmanagerv2-translators' => 'Label in the navigation bar metadata 
dropdown. See [[File:BookManagerv2 navigation bar metadata dropdown.png]] for 
an example of this dropdown. $1 is the length of the array of translators',
+       'bookmanagerv2-editors' => 'Label in the navigation bar metadata 
dropdown. See [[File:BookManagerv2 navigation bar metadata dropdown.png]] for 
an example of this dropdown. $1 is the length of the array of editors',
+       'bookmanagerv2-illustrators' => 'Label in the navigation bar metadata 
dropdown. See [[File:BookManagerv2 navigation bar metadata dropdown.png]] for 
an example of this dropdown. $1 is the length of the array of illustrators',
+       'bookmanagerv2-subtitle' => 'Label in the navigation bar metadata 
dropdown. See [[File:BookManagerv2 navigation bar metadata dropdown.png]] for 
an example of this dropdown',
+       'bookmanagerv2-series-title' => 'Label in the navigation bar metadata 
dropdown. See [[File:BookManagerv2 navigation bar metadata dropdown.png]] for 
an example of this dropdown',
+       'bookmanagerv2-volume' => 'Label in the navigation bar metadata 
dropdown. See [[File:BookManagerv2 navigation bar metadata dropdown.png]] for 
an example of this dropdown',
+       'bookmanagerv2-edition' => 'Label in the navigation bar metadata 
dropdown. See [[File:BookManagerv2 navigation bar metadata dropdown.png]] for 
an example of this dropdown',
+       'bookmanagerv2-publisher' => 'Label in the navigation bar metadata 
dropdown. See [[File:BookManagerv2 navigation bar metadata dropdown.png]] for 
an example of this dropdown',
+       'bookmanagerv2-printer' => 'Label in the navigation bar metadata 
dropdown. See [[File:BookManagerv2 navigation bar metadata dropdown.png]] for 
an example of this dropdown',
+       'bookmanagerv2-publication-date' => 'Label in the navigation bar 
metadata dropdown. See [[File:BookManagerv2 navigation bar metadata 
dropdown.png]] for an example of this dropdown. The value following may be just 
a year, a month and a year, or a year, month, and day.',
+       'bookmanagerv2-publication-city' => 'Label in the navigation bar 
metadata dropdown. See [[File:BookManagerv2 navigation bar metadata 
dropdown.png]] for an example of this dropdown',
+       'bookmanagerv2-language' => 'Label in the navigation bar metadata 
dropdown. See [[File:BookManagerv2 navigation bar metadata dropdown.png]] for 
an example of this dropdown',
+       'bookmanagerv2-description' => 'Label in the navigation bar metadata 
dropdown. See [[File:BookManagerv2 navigation bar metadata dropdown.png]] for 
an example of this dropdown',
+       'bookmanagerv2-source' => 'Label in the navigation bar metadata 
dropdown. See [[File:BookManagerv2 navigation bar metadata dropdown.png]] for 
an example of this dropdown',
+       'bookmanagerv2-permission' => 'Label in the navigation bar metadata 
dropdown. See [[File:BookManagerv2 navigation bar metadata dropdown.png]] for 
an example of this dropdown',
+       'bookmanagerv2-other-versions' => 'Label in the navigation bar metadata 
dropdown. See [[File:BookManagerv2 navigation bar metadata dropdown.png]] for 
an example of this dropdown',
+       'bookmanagerv2-isbn' => 'Label for the International Standard Book 
Number, in the navigation bar metadata dropdown. See [[File:BookManagerv2 
navigation bar metadata dropdown.png]] for an example of this dropdown',
+       'bookmanagerv2-lccn' => 'Label for the Library of Congress Control 
Number, in the navigation bar metadata dropdown. See [[File:BookManagerv2 
navigation bar metadata dropdown.png]] for an example of this dropdown',
+       'bookmanagerv2-oclc' => 'Label for the Online Computer Library Center, 
in the navigation bar metadata dropdown. See [[File:BookManagerv2 navigation 
bar metadata dropdown.png]] for an example of this dropdown',
 );
 
 /** German (Deutsch)

-- 
To view, visit https://gerrit.wikimedia.org/r/73150
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings

Gerrit-MessageType: merged
Gerrit-Change-Id: I9c2d77ce649c678ae34343032ef68b2b673dc92e
Gerrit-PatchSet: 7
Gerrit-Project: mediawiki/extensions/BookManagerv2
Gerrit-Branch: master
Gerrit-Owner: Mollywhite <[email protected]>
Gerrit-Reviewer: Helder.wiki <[email protected]>
Gerrit-Reviewer: Mollywhite <[email protected]>
Gerrit-Reviewer: Mwalker <[email protected]>
Gerrit-Reviewer: Nikerabbit <[email protected]>
Gerrit-Reviewer: Raylton P. Sousa <[email protected]>
Gerrit-Reviewer: jenkins-bot

_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits

Reply via email to