MediaWiki:Gadget-importUtility/table.js

Hinweis: Leere nach dem Veröffentlichen den Browser-Cache, um die Änderungen sehen zu können.

  • Firefox/Safari: Umschalttaste drücken und gleichzeitig Aktualisieren anklicken oder entweder Strg+F5 oder Strg+R (⌘+R auf dem Mac) drücken
  • Google Chrome: Umschalttaste+Strg+R (⌘+Umschalttaste+R auf dem Mac) drücken
  • Internet Explorer/Edge: Strg+F5 drücken oder Strg drücken und gleichzeitig Aktualisieren anklicken
  • Opera: Strg+F5
/// Gadget-importUtility/table.js
//  Maintain maintenance table
/// 2019-09-24 PerfektesChaos@de.wikipedia
//  ResourceLoader: compatible;
//    dependencies: mediawiki.user, mediawiki.util, mediawiki.api
//                  .batch. .cnf. .utl.
//  Namespaces:     4
//  Build:          .table
//  Documentation:  [[w:de:Wikipedia:Technik/Skin/Gadgets/importUtility]]
/// Fingerprint:    #0#0#
/// @license:       CC-by-sa/4.0 GPLv3
// <nowiki>
/* global window: false                                                */
/* jshint forin: false,
          bitwise:true, curly:true, eqeqeq:true, latedef:true,
          laxbreak:true,
          nocomma:true, strict:true, undef:true, unused:true           */



( function ( mw, $ ) {
   "use strict";
   var Version    =  0.905,
       Self       =  "table",
       IUTIL      =  "importUtility",
       SIG        =  "ext.gadget." + IUTIL,
       SIGNATURE  =  SIG + "." + Self,
       TBL        =  { };
   if ( typeof mw.libs[ IUTIL ]  !==  "object"   ||
        ! mw.libs[ IUTIL ] ) {
      mw.libs[ IUTIL ]  =  { };
   }
   mw.libs[ IUTIL ].type  =  IUTIL;
   IUTIL                  =  mw.libs[ IUTIL ];
   if ( typeof IUTIL.vsn  ===  "string" ) {
      IUTIL.vsn  =  IUTIL.vsn + " ";
   } else {
      IUTIL.vsn  =  "";
   }
   IUTIL.vsn  =  IUTIL.vsn + Self.substr( 0, 1 ) + "=" + Version;



//-----------------------------------------------------------------------



   if ( typeof IUTIL.table  !==  "object" ) {
      // Utilities for HTML form fields
      // Dependencies: mediawiki.util JSON
      IUTIL.table  =  { };



      TBL.factory  =  function ( assign, ahead ) {
         // Create marker comment
         // Precondition:
         //    assign  -- keyword
         //    ahead   -- true: "begin"   else "end"
         // Postcondition:
         //    Return comment
         // 2013-01-19 PerfektesChaos@de.wikipedia
         return  "<!--importUtility " + assign
                + ( ahead ? " begin" : " end" )
                + " -->";
      };   // TBL.factory()



      TBL.fault  =  function ( arrived ) {
         // Show API failure on maintenance page updating
         // Precondition:
         //    arrived  -- JSON info of ajax query, or false
         // Uses:
         //    >  TBL.$i
         //    >  TBL.$n
         //    .utl.fault()
         //    mw.log()
         // 2015-07-09 PerfektesChaos@de.wikipedia
         IUTIL.utl.fault( false );
         mw.log( {loud:true},
                 "IUTIL.table fault() " + TBL.$i.text() + TBL.$n.text(),
                 2,
                 arrived );
      };   // TBL.fault()



      TBL.feed  =  function ( arrived ) {
         // Retrieve one category member entry for this user
         // Precondition:
         //    arrived  -- JSON info of ajax query, or false, or null
         // Uses:
         //    >  TBL.$i
         //    >< TBL.item
         //    >< TBL.pages
         //    >< TBL.query
         //     < TBL.max
         //    jQuery().text()
         //    mw.Api()
         //    TBL.feed()
         //    TBL.fetch()
         //    (TBL.feed)
         //    (TBL.fault)
         // 2018-06-21 PerfektesChaos@de.wikipedia
         var i, p, q, s;
         if ( arrived ) {
            if ( arrived.limits ) {
               TBL.max            =  arrived.limits.revisions;
               TBL.query.rvlimit  =  TBL.max;
            }
            i  =  -1;
            p  =  TBL.pages[ TBL.item ];
            q  =  arrived.query;
            if ( q && p ) {
               if ( q.pageids ) {
                  i       =  q.pageids[ 0 ];
                  p[ 0 ]  =  i;
               }
               q  =  q.pages;
               if ( q  &&  i > 0 ) {
                  q  =  q[ i ];
                  if ( q ) {
                     q  =  q.revisions;
                     if ( q ) {
                        p[ 5 ]  =  q[ 0 ].timestamp.substr( 0, 10 );
                        i       =  q.length - 1;
                        if ( i ) {
                           p[ 4 ]  =  q[ i ].timestamp.substr( 0, 10 );
                        } else {
                           p[ 4 ]  =  "(1)";
                        }
                     } else {
                        p[ 5 ]  =  "-.-";
                     }
                  }
               }
            }
         } else if ( arrived === false ) {   // setup
            TBL.item   =  -1;
            TBL.max    =  "max";
            TBL.query  =  { action:       "query",
                            "continue":   "",
                            prop:         "revisions",
                            indexpageids: true,
                            rvlimit:      TBL.max,
                            rvprop:       "timestamp" };
         }
         TBL.item++;
         if ( TBL.item < TBL.pages.length ) {
            i  =  -9;
            TBL.$i.text( "#" + TBL.item );
            s  =  TBL.pages[ TBL.item ];
            if ( s ) {
               s  =  s.title;
               if ( s ) {
                  TBL.pages[ TBL.item ]  =
                                        [ false,   // [0] curid
                                          s,       // [1] user space path
                                          false,   // [2] log entry
                                          false,   // [3] title
                                          false,   // [4] first user edit
                                          false,   // [5] last user edit
                                          false ]; // [6] last edit
                  i                      =  s.indexOf( "/" );
               }
            }
            if ( i > 0 ) {
               TBL.query.titles            =  s;
               TBL.pages[ TBL.item ][ 3 ]  =  s.substr( i + 1 );
               s                           =  s.substr( 0, i );
               i                           =  s.indexOf( ":" );
               if ( i > 0 ) {
                  TBL.query.rvuser  =  s.substr( i + 1 );
                  q                 =  new mw.Api();
                  q.get( TBL.query ).done( TBL.feed )
                                    .fail( TBL.fault );
               }
            } else {
               TBL.feed( null );
            }
         } else {
            TBL.fetch( false );
         }
      };   // TBL.feed()



      TBL.fetch  =  function ( arrived ) {
         // Retrieve logbook entries one by one
         // Precondition:
         //    arrived  -- JSON info of ajax query, or false
         // Uses:
         //    >  TBL.$n
         //    >  TBL.$i
         //    >< TBL.item
         //    >< TBL.pages
         //    >< TBL.query
         //    jQuery().text()
         //    mw.Api()
         //    TBL.fetch()
         //    TBL.flow()
         //    (TBL.fetch)
         //    (TBL.fault)
         // 2015-06-11 PerfektesChaos@de.wikipedia
         var q;
         if ( arrived ) {
            q  =  arrived.query;
            if ( q ) {
               q  =  q.logevents;
               if ( q ) {
                  if ( q.length ) {
                     TBL.pages[ TBL.item ][ 2 ]  =
                               q[ 0 ].timestamp.substr( 0, 10 )  +  "/*";
                  }
               }
            }
         } else if ( arrived === false ) {   // setup
            TBL.item   =  -1;
            TBL.query  =  { action:     "query",
                            "continue": "",
                            list:       "logevents",
                            letype:     "import",
                            lelimit:    1,
                            leprop:     "timestamp" };
            TBL.$n.text( "/" + TBL.pages.length );
         }
         TBL.item++;
         if ( TBL.item < TBL.pages.length ) {
            TBL.$i.text( "log " + TBL.item );
            q  =  TBL.pages[ TBL.item ];
            if ( q ) {
               TBL.query.letitle  =  q[ 1 ];
               q                  =  new mw.Api();
               q.get( TBL.query ).done( TBL.fetch )
                                 .fail( TBL.fault );
            } else {
               TBL.fetch( null );
            }
         } else {
            TBL.flow( false );
         }
      };   // TBL.fetch()



      TBL.fiat  =  function () {
         // Update table on maintenance page
         // Uses:
         //    >  .cnf.project.table.support
         //    >< .$msg
         //     < TBL.$i
         //     < TBL.$n
         //    mw.Api()
         //    .batch.fired()
         //    jQuery().append()
         //    jQuery().find()
         //    (TBL.fill)
         //    (TBL.fault)
         // 2015-07-09 PerfektesChaos@de.wikipedia
         var q  =  new mw.Api(),
             w  =  { action:       "query",
                     "continue":   "",
                     indexpageids: true,
                     prop:         "revisions",
                     rvlimit:      1,
                     rvprop:       "content",
                     titles:       "Project:"
                                   + IUTIL.cnf.project.table.support };
         IUTIL.batch.fired( false );
         IUTIL.$msg.append( "<span>&nbsp; &nbsp;</span>"
                            + "<span id='IUTIL-table-i' />"
                            + "<span id='IUTIL-table-n' />" );
         TBL.$i  =  IUTIL.$msg.find( "#IUTIL-table-i" );
         TBL.$n  =  IUTIL.$msg.find( "#IUTIL-table-n" );
         q.get( w ).done( TBL.fill )
                   .fail( TBL.fault );
      };   // TBL.fiat()



      TBL.fill  =  function ( arrived ) {
         // Retrieve content of maintenance page
         // Precondition:
         //    arrived  -- JSON info of ajax query
         // Uses:
         //     < TBL.story
         //    TBL.fresh()
         //    TBL.fault()
         // 2013-01-08 PerfektesChaos@de.wikipedia
         var i,
             q  =  arrived.query,
             w  =  q.pageids;
         TBL.story  =  false;
         if ( w ) {
            i  =  w[ 0 ];
         }
         if ( i ) {
            w  =  q.pages;
            if ( w ) {
               w  =  w[ i ];
               if ( w ) {
                  w  =  w.revisions;
                  if ( w ) {
                     w  =  w[ 0 ];
                     if ( w ) {
                        TBL.story  =  w[ "*" ];
                     }
                  }
               }
            }
         }
         if ( TBL.story ) {
            TBL.fresh();
         } else {
            TBL.fault();
         }
      };   // TBL.fill()



      TBL.fine  =  function () {
         // Show API success on table page updating
         // Precondition:
         //    arrived  -- JSON info of ajax query, or false
         // Uses:
         //    .batch.fine()
         // 2013-01-05 PerfektesChaos@de.wikipedia
         IUTIL.batch.fine( "PageUpdated" );
      };   // TBL.fine()



      TBL.finish  =  function ( arrived ) {
         // Retrieve last edit one by one
         // Precondition:
         //    arrived  -- JSON info of ajax query, or false
         // Uses:
         //    >  TBL.$i
         //    >< TBL.item
         //    >< TBL.pages
         //    >< TBL.query
         //    TBL.format()
         //    jQuery().text()
         //    mw.Api()
         //    (TBL.finish)
         //    (TBL.fault)
         // 2015-06-11 PerfektesChaos@de.wikipedia
         var q, s;
         if ( arrived ) {
            q  =  arrived.query;
            if ( q ) {
               q  =  q.pages;
               if ( q ) {
                  q  =  q[ TBL.pages[ TBL.item ][ 0 ] ];
                  if ( q ) {
                     q  =  q.revisions;
                     if ( q ) {
                        s  =  q[ 0 ].timestamp.substr( 0, 10 );
                        if ( s === TBL.pages[ TBL.item ][ 5 ] ) {
                           s  =  "===";
                        }
                        TBL.pages[ TBL.item ][ 6 ]  =  s;
                     }
                  }
               }
            }
         } else if ( arrived === false ) {   // setup
            TBL.item   =  -1;
            TBL.query  =  { action:     "query",
                            "continue": "",
                            prop:       "revisions",
                            rvlimit:    1,
                            rvprop:     "timestamp" };
         }
         TBL.item++;
         if ( TBL.item < TBL.pages.length ) {
            TBL.$i.text( "... " + TBL.item );
            TBL.query.pageids  =  TBL.pages[ TBL.item ][ 0 ];
            q                  =  new mw.Api();
            q.get( TBL.query ).done( TBL.finish )
                              .fail( TBL.fault );
         } else {
            TBL.format();
         }
      };   // TBL.finish()



      TBL.flow  =  function ( arrived ) {
         // Analyze revisions comments for missing log entry
         // Precondition:
         //    arrived  -- JSON info of ajax query, or false
         // Uses:
         //    >  TBL.max
         //    >  TBL.$i
         //    >< TBL.item
         //    >< TBL.reVsn
         //    >< TBL.pages
         //    >< TBL.query
         //    TBL.flow()
         //    jQuery().text()
         //    mw.Api()
         //    TBL.finish()
         //    (TBL.flow)
         //    (TBL.fault)
         // Remark: Used as event handler -- 'this' is not IUTIL.table
         // 2015-06-11 PerfektesChaos@de.wikipedia
         var e, i, j, k, n, p, q;
         if ( arrived ) {
            q  =  arrived.query;
            if ( q ) {
               q  =  q.pages;
               if ( q ) {
                  q  =  q[ TBL.pages[ TBL.item ][ 0 ] ];
                  if ( q ) {
                     q  =  q.revisions;
                     if ( q ) {
                        n  =  q.length;
                        if ( n ) {
                           e  =  q[ 0 ];
                           k  =  e.size;
                           for ( i = 1;  i < n;  i++ ) {
                              p  =  q[ i ];
                              j  =  p.size;
                              if ( k - j  ===  0 ) {
                                 if ( TBL.reVsn.test( e.comment ) ) {
                                    TBL.pages[ TBL.item ][ 2 ]  =
                                              e.timestamp.substr( 0, 10 )
                                                                 +  "/-";
                                    break;   // for i
                                 }
                              }
                              e  =  p;
                              k  =  j;
                           }   // for i
                        }
                     }
                  }
               }
            }
         } else if ( arrived === false ) {   // setup
            TBL.item       =  -1;
            TBL.query      =  { action:     "query",
                                "continue": "",
                                prop:       "revisions",
                                rvlimit:    TBL.max,
                                rvprop:     "size|comment|timestamp" };
            TBL.reVsn  =  new RegExp( "^[0-9]+ Versionen\\b" );
         }
         TBL.item++;
         if ( TBL.item < TBL.pages.length ) {
            if ( TBL.pages[ TBL.item ][ 2 ] ) {
               TBL.flow( null );
            } else {
               TBL.$i.text( "q " + TBL.item );
               TBL.query.titles  =  TBL.pages[ TBL.item ][ 1 ];
               q                 =  new mw.Api();
               q.get( TBL.query ).done( TBL.flow )
                                 .fail( TBL.fault );
            }
         } else {
            TBL.finish( false );
         }
      };   // TBL.flow()



      TBL.fold  =  function ( amount ) {
         // Integrate collected data into page
         // Precondition:
         //    amount  -- wikitable with all entries
         // Uses:
         //    this
         //    >  .type
         //    >  .vsn
         //    >  .cnf.project.table.support
         //    >  TBL.$n
         //    >  TBL.story
         //    mw.Api()
         //    TBL.folder()
         //    jQuery().text()
         //    mw.user.tokens.get()
         //    (TBL.fine)
         //    (TBL.fault)
         // 2019-09-24 PerfektesChaos@de.wikipedia
         var d  =  new Date(),
             i  =  0,
             q  =  new mw.Api(),
             w  =  { action:  "edit",
                     token:   mw.user.tokens.get( "csrfToken" ),
                     minor:   false,
                     summary: "Updated; " + IUTIL.type + " " + IUTIL.vsn,
                     title:   "Project:"
                              + IUTIL.cnf.project.table.support };
         TBL.folder( "TABLE", amount );
         TBL.folder( "TIMESTAMP", d.toLocaleString() );
         d  =  0;
         do {
            i  =  amount.indexOf( "\n|-",  i + 2 );
            d++;
         } while ( i > 0 );
         TBL.folder( "COUNT", d );
         TBL.$n.text( "UPDATING" );
         w.text  =  TBL.story;
         q.post( w ).done( TBL.fine )
                    .fail( TBL.fault );
      };   // TBL.fold()



      TBL.folder  =  function ( at, against ) {
         // Exchange
         // Precondition:
         //    at       --  wikitable with all entries
         //    against  --  wikitable with all entries
         // Uses:
         //    >< TBL.story
         //    TBL.factory()
         // 2013-01-19 PerfektesChaos@de.wikipedia
         var i, j, s,
             start  =  TBL.factory( at, true );
         i  =  TBL.story.indexOf( start );
         if ( i > 0 ) {
            i  +=  start.length;
            s   =  TBL.factory( at, false );
            j   =  TBL.story.indexOf( s, i );
            if ( j > 0 ) {
               TBL.story  =  TBL.story.substr( 0, i )
                             +  against
                             +  TBL.story.substr( j );
            }
         }
      };   // TBL.folder()



      TBL.format  =  function () {
         // Format collected data as wikitable
         // Precondition:
         //    arrived  -- JSON info of ajax query, or false
         // Uses:
         //    >  TBL.max
         //    >  TBL.pages
         //    >  TBL.$i
         //    >  TBL.$n
         //    jQuery().text()
         //    TBL.fold()
         // 2013-01-19 PerfektesChaos@de.wikipedia
         var d, e, i, j, u,
             p  =  TBL.pages,
             n  =  p.length,
             s  =  "";
         TBL.$i.text( "" );
         TBL.$n.text( "format" );
         for ( i = 0;  i < n;  i++ ) {
            e  =  p[ i ];
            s  =  s + "\n\n|-\n| <!--" + e[ 0 ] + "-->";   // [0] curid
            d  =  e[ 1 ];
            if ( d ) {   // [1] user space path
               j  =  d.indexOf( ":" );
               if ( j > 1 ) {
                  u  =  d.substr( j + 1 );
                  j  =  u.indexOf( "/" );
                  if ( j > 1 ) {
                     u  =  "'''"  +  u.substr( 0 , j )  +  "''' "
                           +  u.substr( j );
                  }
                  d  =  "[[" + d + "|" + u + "]]";
               }
            } else {
               d  =  "";
            }
            s  =  s + "\n" + d;
            d  =  e[ 2 ];   // [2] log entry
            s  =  s   +   "\n|"   +   ( d  ?  " " + d  :  "" );
            d  =  e[ 4 ];   // [4] first user edit
            if ( d ) {
               j  =  e[ 2 ];
               if ( j  &&  d.length === 10 ) {
                  if ( d  <  j.substr( 0, 10 ) ) {
                     d  =  "<s>" + d + "</s>";
                  }
               }
               d  =  " " + d;
            } else {
               d  =  "";
            }
            s  =  s + "\n|" + d;
            d  =  e[ 5 ];   // [5] last user edit
            s  =  s   +   "\n|"   +   ( d  ?  " " + d  :  "" );
            d  =  e[ 6 ];   // [6] last edit
            s  =  s   +   "\n|"   +   ( d  ?  " " + d  :  "" );
            d  =  e[ 3 ];
            if ( d ) {  // [3] title
               s  =  s + "\n| [[" + d + "]]";
            }
         }   // for i
         s  =  s + "\n\n|}\n";
         TBL.$n.text( "completed" );
         TBL.fold( s );
      };   // TBL.format()



      TBL.fresh  =  function ( arrived ) {
         // Retrieve list of category members
         // Precondition:
         //    arrived  -- JSON info of ajax query, or false
         // Uses:
         //    >  .cnf.project.table.source
         //    >  TBL.$n
         //    >< TBL.pages
         //    >< TBL.query
         //    >< TBL.api
         //     < TBL.pages
         //    mw.Api()
         //    jQuery().text()
         //    TBL.feed()
         //    (TBL.fresh)   -- self
         //    (TBL.fault)
         // Remark: Used as event handler -- 'this' is not TBL
         // 2015-07-09 PerfektesChaos@de.wikipedia
         if ( arrived ) {
            if ( typeof arrived.query  ===  "object" ) {
               TBL.pages  =
                       TBL.pages.concat( arrived.query.categorymembers );
               if ( typeof arrived[ "continue" ]  ===  "object" ) {
                  $.extend( TBL.query,  arrived[ "continue" ] );
               } else {
                  TBL.query  =  false;
               }
            } else {
               TBL.query  =  false;
            }
         } else {   // setup
            TBL.api    =  new mw.Api();
            TBL.pages  =  [ ];
            TBL.query  =
                        { action:       "query",
                          "continue":   "",
                          list:         "categorymembers",
                          indexpageids: true,
                          cmlimit:      15,//      "max",
                          cmnamespace:  2,
                          cmprop:       "title|timestamp",
                          cmtitle:      "Category:"
                                         + IUTIL.cnf.project.table.source
                        };
         }
         if ( TBL.query ) {
            TBL.$n.text( "/" + TBL.pages.length );
            TBL.api.get( TBL.query ).done( TBL.fresh )
                                    .fail( TBL.fault );
         } else {
            TBL.feed( false );
         }
      };   // TBL.fresh()



//-----------------------------------------------------------------------



      TBL.furnish  =  function () {
         // Equip maintenance page with update control
         // Precondition:
         //    id="IUTIL-button-update" expected in maintenance page
         // Uses:
         //    >  mw.util.$content
         //    >  .type
         //    .utl.furnish()
         //    jQuery().find()
         //    jQuery().empty()
         //    jQuery()
         //    jQuery().attr()
         //    jQuery().text()
         //    jQuery().click()
         //    .cnf.feature()
         //    jQuery().append()
         //    (.table.fiat)
         // 2014-10-10 PerfektesChaos@de.wikipedia
         var $btn, $d;
         IUTIL.utl.furnish();
         $d  =  mw.util.$content.find( "#IUTIL-button-update" );
         if ( $d.length ) {
            $d.empty();
            $btn  =  $( "<button />" );
            $btn.attr( { id:   "IUTIL-button-update",
                         type: "button"
                       } );
            $btn.text( IUTIL.cnf.feature( "Update" ) );
            $btn.click( IUTIL.table.fiat );
            $d.append( $btn );
         }
      };   // TBL.furnish()



      IUTIL.table.fiat  =  function () {
         // Update control has been triggered
         // Uses:
         //    mw.loader.using()
         //    (TBL.fiat)
         // 2015-07-09 PerfektesChaos@de.wikipedia
         mw.loader.using( [ "mediawiki.api",
                            "mediawiki.user",
                            "mediawiki.util",
                            "user" ],
                          TBL.fiat );
      };   // .table.fiat()



      IUTIL.table.fire  =  function () {
         // Initialize maintenance page
         // Precondition:
         //    Current page is maintenance page
         // Uses:
         //    >< .start
         //    mw.hook()
         //    (TBL.furnish)
         // 2018-04-09 PerfektesChaos@de.wikipedia
         if ( typeof IUTIL.start  ===  "string"
              &&     IUTIL.start  ===  Self ) {
            IUTIL.start  =  false;
            mw.hook( "wikipage.content" ).add( TBL.furnish );
         }
      };   // .table.fire()
   }   // .table



//-----------------------------------------------------------------------



   function fire() {
      // Script unit has been loaded
      // Uses:
      //    >  SIGNATURE
      //    >  .type
      //    >  Self
      //    >  Version
      //    mw.loader.getState()
      //    mw.loader.state()
      //    mw.hook()
      // 2018-08-24 PerfektesChaos@de.wikipedia
      var rls, sign;
      if ( mw.loader.getState( SIGNATURE )  !==  "ready" ) {
         rls  =  { };
         rls[ SIGNATURE ]  =  "ready";
         mw.loader.state( rls );
         sign  =  IUTIL.type + "." + Self;
         mw.hook( sign + ".ready" ).fire( { type: sign,
                                            vsn:  Version } );
         mw.hook( IUTIL.type + ".utl.ready" ).add( IUTIL[ Self ].fire );
      }
   }   // fire()



   fire();
}( window.mediaWiki, window.jQuery ) );



// Emacs
// Local Variables:
// End:

/// EOF   importUtility/table.js    </nowiki>