7. Install MediaWiki Extensions

  1. Start the virtual machine and log in:

    ssh -p 8015 hjc@dynamicshjc.case.edu
    
  2. Check for and install system updates on the virtual machine:

    sudo apt-get update
    sudo apt-get dist-upgrade
    sudo apt-get autoremove
    
  3. Install these new packages,

    Package Description
    phpCAS PHP implementation of Central Auth Service
    php-ldap LDAP module for PHP for looking up real names when wiki accounts are created
    parsoid Web service converting HTML+RDFa to MediaWiki wikitext and back (prereq for VisualEditor)
    dvipng convert DVI files to PNG graphics (prereq for Math)
    ocaml ML language implementation with a class-based object system (prereq for Math)
    texlive-latex-recommended TeX Live: LaTeX recommended packages (prereq for Math)
    texlive-latex-extra TeX Live: LaTeX additional packages (prereq for Math)
    texlive-fonts-recommended TeX Live: Recommended fonts (prereq for Math)
    texlive-lang-greek TeX Live: Greek (prereq for Math)

    using the following:

    sudo apt-get install php-cas php-ldap dvipng ocaml texlive-latex-recommended texlive-latex-extra texlive-fonts-recommended texlive-lang-greek
    sudo apt-key advanced --keyserver pgp.mit.edu --recv-keys 90E9F83F22250DD7
    sudo apt-add-repository "deb https://releases.wikimedia.org/debian jessie-mediawiki main"
    sudo apt-get update
    sudo apt-get install parsoid
    

    Todo

    Change parsoid install command to use a specific version known to work with MW 1.27 (version “0.5.3all” ?).

  4. Restart the web server:

    sudo apache2ctl restart
    
  5. Download these extensions,

    Extension Description
    CASAuthentication integration with university Single Sign-On
    EmbedVideo embed online videos in wiki pages
    ImportUsers [1] create user accounts from CSV files
    Lockdown restrict access to specific namespaces
    Math math typesetting
    MobileFrontend better wiki interface for smartphones
    NewArticleTemplate auto-fill new pages with template text
    Realnames replace user names with real names
    ScholasticGrading assign and report grades
    Scribunto embed scripts in Module namespace (prereq for citation and license templates)
    UserMerge merge contributions and delete users
    VisualEditor WYSIWYG editor for wiki atricles

    using the following:

    cd /var/www/mediawiki/extensions/
    
    # CASAuthentication
    git clone https://github.com/CWRUChielLab/CASAuth.git
    
    # EmbedVideo
    git clone https://github.com/HydraWiki/mediawiki-embedvideo.git EmbedVideo
    git -C EmbedVideo checkout -q v2.3.3  # latest release as of Aug 2016
    
    # ImportUsers
    git clone https://gerrit.wikimedia.org/r/p/mediawiki/extensions/ImportUsers.git
    git -C ImportUsers checkout -q REL1_27
    
    # Lockdown
    git clone https://gerrit.wikimedia.org/r/p/mediawiki/extensions/Lockdown.git
    git -C Lockdown checkout -q REL1_27
    
    # Math
    git clone https://gerrit.wikimedia.org/r/p/mediawiki/extensions/Math.git
    git -C Math checkout -q REL1_27
    make -C Math  # build texvc
    
    # MobileFrontend
    git clone https://gerrit.wikimedia.org/r/p/mediawiki/extensions/MobileFrontend.git
    git -C MobileFrontend checkout -q REL1_27
    
    # NewArticleTemplate
    git clone https://github.com/mathiasertl/NewArticleTemplates.git NewArticleTemplate
    git -C NewArticleTemplate checkout -q cff90b32  # latest commit as of Aug 2016
    
    # Realnames
    wget -O Realnames.tar.gz http://ofbeaton.com/releases/Realnames/Realnames_0.3.1_2011-12-25.tar.gz
    tar -xf Realnames.tar.gz && rm Realnames.tar.gz
    
    # ScholasticGrading
    git clone https://github.com/CWRUChielLab/ScholasticGrading.git
    
    # Scribunto
    git clone https://gerrit.wikimedia.org/r/p/mediawiki/extensions/Scribunto.git
    git -C Scribunto checkout -q REL1_27
    
    # UserMerge
    git clone https://gerrit.wikimedia.org/r/p/mediawiki/extensions/UserMerge.git
    git -C UserMerge checkout -q REL1_27
    
    # VisualEditor
    git clone https://gerrit.wikimedia.org/r/p/mediawiki/extensions/VisualEditor.git
    git -C VisualEditor checkout -q REL1_27
    git -C VisualEditor submodule update --init
    

    Todo

    Consider adding Mathoid installation instructions. In its current form, this instruction set utilizes the Math extension’s PNG mode. By changing $wgDefaultUserOptions['math'] to 'mathml' in LocalSettings.php, an alternate MathML mode can be used. This requires a Mathoid server for runtime equation rendering. The $wgMathFullRestbaseURL setting specifies a server in Germany that is free to use but is occasionally unresponsive, causing the wiki to either load slowly or fail to render equations. By building a local Mathoid server, responsiveness and reliability could be guarenteed. However, after much effort, Jeff has not been able to get a Mathoid installation working yet. Since MathML offers few advantages over PNG mode, getting this working is a low priority.

  6. Download and install the CAS (Single Sign-On) configuration file:

    wget -O /var/www/mediawiki/extensions/CASAuth/CASAuthSettings.php https://neurowiki-docs.readthedocs.io/en/latest/_downloads/CASAuthSettings.php
    

    Randomize the secret key inside the configuration file:

    sed -i '/^\$CASAuth\["PwdSecret"\]/s|=".*";|="'$(openssl rand -hex 32)'";|' /var/www/mediawiki/extensions/CASAuth/CASAuthSettings.php
    

    Protect the secret key:

    sudo chmod ug=rw,o= /var/www/mediawiki/extensions/CASAuth/CASAuthSettings.php*
    

    If you are curious about the contents of CASAuthSettings.php, you can view it here:

    CASAuthSettings.php

    Direct link

    <?php
    # This file controls the configuration of the CASAuth extension.  The defaults
    # for these options are defined in CASAuth.php, and are only defined here as
    # well for the sake of documentation.  It is highly suggested you should not
    # modify the CASAuth defaults unless you know what you are doing.
    
    # Location of the phpCAS library, which is required for this Extension.  For
    # more information, see https://wiki.jasig.org/display/CASC/phpCAS for more
    # information.
    #
    # Default: $CASAuth["phpCAS"]="$IP/extensions/CASAuth/CAS";
    $CASAuth["phpCAS"]="/usr/share/php";
    
    # Location of the CAS authentication server.  You must set this to the location
    # of your CAS server.  You have a CAS server right?
    #
    # Default: $CASAuth["Server"]="auth.example.com";
    $CASAuth["Server"]="login.case.edu";
    
    # An array of servers that are allowed to make use of the Single Sign Out
    # feature.  Leave to false if you do not support this feature, of if you dont
    # want to use it.  Otherwise, add servers on individual lines.
    #  Example:
    #    $CASAuth["LogoutServers"][]='cas-logout-01.example.com';
    #    $CASAuth["LogoutServers"][]='cas-logout-02.example.com';
    #
    # Default: $CASAuth["LogoutServers"]=false;
    $CASAuth["LogoutServers"]=false;
    
    # Server port for communicating with the CAS server.
    #
    # Default: $CASAuth["Port"]=443;
    $CASAuth["Port"]=443;
    
    # URI Path to the CAS authentication service
    #
    # Default: $CASAuth["Url"]="/cas/";
    $CASAuth["Url"]="/cas/";
    
    # CAS Version.  Available versions are "1.0" and "2.0".
    #
    # Default: $CASAuth["Version"]="2.0";
    $CASAuth["Version"]="2.0";
    
    # Enable auto-creation of users when signing in via CASAuth. This is required
    # if the users do not already exist in the MediaWiki use database.  If accounts
    # are not regularly being creating, it is recommended that this be set to false
    #
    # Default: $CASAuth["CreateAccounts"]=false
    $CASAuth["CreateAccounts"]=true;
    
    # If the "CreateAccounts" option is set "true", the string below is used as a
    # salt for generating passwords for the users.  This salt is not used by
    # the normal Mediawiki authentication and is only in place to prevent someone
    # from cracking passwords in the database.  This should be changed to something
    # long and horrendous to remember.
    #
    # Default: $CASAuth["PwdSecret"]="Secret";
    $CASAuth["PwdSecret"]="<random string>";
    
    # The email domain is appended to the end of the username when the user logs
    # in.  This does not affect their email address, and is for aesthetic purposes
    # only.
    #
    # Default: $CASAuth["EmailDomain"]="example.com";
    $CASAuth["EmailDomain"]="case.edu";
    
    # Restrict which users can login to the wiki?  If set to true, only the users
    # in the $CASAuth["AllowedUsers"] array can login.
    #
    # Default: $CASAuth["RestrictUsers"]=false
    $CASAuth["RestrictUsers"]=false;
    
    # Should CAS users be logged in with the "Remember Me" option?
    #
    # Default: $CASAuth["RememberMe"]=true;
    $CASAuth["RememberMe"]=true;
    
    # If $CASAuth["RestrictUsers"] is set to true, the list of users below are the
    # users that are allowed to login to the wiki.
    #
    # Default: $CASAuth["AllowedUsers"] = false;
    $CASAuth["AllowedUsers"] = false;
    
    # If a user is not allowed to login, where should we redirect them to?
    #
    # Default: $CASAuth["RestrictRedirect"]="http://www.example.com";
    $CASAuth["RestrictRedirect"]="http://www.example.com";
    
    # If you dont like the uid that CAS returns (ie. it returns a number) you can
    # modify the routine below to return a customized username instead.
    #
    # Default: Returns the username, untouched
    function casNameLookup($username) {
      return $username;
    }
    
    # If your users aren't all on the same email domain you can
    # modify the routine below to return their email address
    #
    # Default: Returns $username@EmailDomain
    function casEmailLookup($username) {
      global $CASAuth;
      return $username."@".$CASAuth["EmailDomain"];
    }
    
    # If you dont like the uid that CAS returns (ie. it returns a number) you can
    # modify the routine below to return a customized real name instead.
    #
    # Default: Returns the username, untouched
    #function casRealNameLookup($username) {
    #  return $username;
    #}
    
    # If you would like to use ldap to retrieve real names, you can use these
    # functions instead. Remember to fill in appropriate parameters for ldap.
    function casRealNameLookup($username) {
      return @casRealNameLookupFromLDAP($username);
    }
    
    function casRealNameLookupFromLDAP($username) {
      try {
        # login to the LDAP server
        $ldap = ldap_connect("ldap://ldap.case.edu");
        $bind = ldap_bind($ldap, "anonymous", "");
    
        # look up the user's name by user id
        $result = ldap_search($ldap, "ou=People,o=cwru.edu,o=isp", "(uid=$username)");
        $info = ldap_get_entries($ldap, $result);
    
        $first_name = $info[0]["givenname"][0];
        $last_name  = $info[0]["sn"][0];
    
        # log out of the server
        ldap_unbind($ldap);
    
        $realname = $first_name . " " . $last_name;
      } catch (Exception $e) {}
    
      if ($realname == " " || $realname == "" || $realname == NULL) {
        $realname = $username;
      }
    
      return $realname;
    }
    
  7. Modify the Parsoid configuration for the VisualEditor extension. The Parsoid server running on the virtual machine needs to communicate with the web server on the same machine. To simplify this, Parsoid is configured to connect simply to http://localhost.... For this to work, the protocol must be changed to HTTPS, and Parsoid must be permitted to ignore mismatched SSL certificates, since it will expect a certificate for “localhost”, rather than one for DynamicsHJC, NeuroWiki, or NeuroWikiDev. Make the changes by running these commands:

    sudo sed -i '/setMwApi/s|http://|https://|' /etc/mediawiki/parsoid/settings.js
    sudo sed -i '/strictSSL/s|\(\w*\)//\(.*\)|\1\2|' /etc/mediawiki/parsoid/settings.js
    sudo service parsoid restart
    
  8. Todo

    Update the patch for MobileFrontend. For now, skip this step during installation.

    Customizing the mobile site navigation menu by downloading a patch file and applying it:

    wget -O /var/www/mediawiki/extensions/MobileFrontend/MobileFrontend_customize-icons.patch https://neurowiki-docs.readthedocs.io/en/latest/_downloads/MobileFrontend_customize-icons.patch
    patch -d /var/www/mediawiki/extensions/MobileFrontend < /var/www/mediawiki/extensions/MobileFrontend/MobileFrontend_customize-icons.patch
    

    If you are curious about the contents of the patch file, you can view it here:

    MobileFrontend_customize-icons.patch

    Direct link

    diff --git a/includes/skins/SkinMinerva.php b/includes/skins/SkinMinerva.php
    index b17ada0..c83d489 100644
    --- a/includes/skins/SkinMinerva.php
    +++ b/includes/skins/SkinMinerva.php
    @@ -312,10 +312,30 @@ class SkinMinerva extends SkinTemplate {
                    global $wgMFNearby;
    
                    $items = array(
    -                       'home' => array(
    -                               'text' => wfMessage( 'mobile-frontend-home-button' )->escaped(),
    -                               'href' => Title::newMainPage()->getLocalUrl(),
    -                               'class' => 'icon-home',
    +                       'syllabus' => array(
    +                               'text' => 'Syllabus',
    +                               'href' => Title::newFromText( 'nw:Course syllabus' )->getLocalUrl(),
    +                               'class' => 'icon-syllabus',
    +                       ),
    +                       'policies' => array(
    +                               'text' => 'Policies',
    +                               'href' => Title::newFromText( 'nw:Course policies' )->getLocalUrl(),
    +                               'class' => 'icon-policies',
    +                       ),
    +                       'grades' => array(
    +                               'text' => 'Grades',
    +                               'href' => Title::newFromText( 'nw:Special:Grades' )->getLocalUrl(),
    +                               'class' => 'icon-grades',
    +                       ),
    +                       'labnotebook' => array(
    +                               'text' => 'Lab Notebook',
    +                               'href' => Title::newFromText( 'Special:UserLogin' )->getLocalUrl( 'returnto=nw:Special:MyPage' ),
    +                               'class' => 'icon-home',
    +                       ),
    +                       'termpapers' => array(
    +                               'text' => 'Term Papers',
    +                               'href' => Title::newFromText( 'nwp:Main Page' )->getLocalUrl(),
    +                               'class' => 'icon-termpapers',
                            ),
                            'random' => array(
                                    'text' => wfMessage( 'mobile-frontend-random-button' )->escaped(),
    diff --git a/less/common/hacks.less b/less/common/hacks.less
    index 59fb6b3..6496480 100644
    --- a/less/common/hacks.less
    +++ b/less/common/hacks.less
    @@ -16,10 +16,10 @@ FIXME: Review all of these hacks to see if they still apply.
     .content {
            // Hide cleanup templates by default to non-javascript users as these stop them from reading the article itself
            // Note not in issues.less as that is only loaded via JavaScript
    -       .ambox,
    +       .ambox:not(.simbox),
            #coordinates,
            // Hide article badges, clean-up notices, stub notices, and navigation boxes
    -       .navbox, .vertical-navbox, .topicon, .metadata {
    +       .navbox, .vertical-navbox, .topicon, .metadata:not(.simbox) {
                    // It's important as some of these are tables which become display: table on larger screens
                    display: none !important;
            }
    diff --git a/less/common/mainmenu.less b/less/common/mainmenu.less
    index 8ccf1ba..5a46631 100644
    --- a/less/common/mainmenu.less
    +++ b/less/common/mainmenu.less
    @@ -104,6 +104,22 @@
                            .background-image('images/menu/home.png');
                    }
    
    +               &.icon-syllabus a {
    +                       .background-image('/CourseMaterials/Images/mobile-icon-syllabus.png');
    +               }
    +
    +               &.icon-policies a {
    +                       .background-image('/CourseMaterials/Images/mobile-icon-policies.png');
    +               }
    +
    +               &.icon-grades a {
    +                       .background-image('/CourseMaterials/Images/mobile-icon-grades.png');
    +               }
    +
    +               &.icon-termpapers a {
    +                       .background-image('/CourseMaterials/Images/mobile-icon-termpapers.png');
    +               }
    +
                    &.icon-random a {
                            .background-image('images/menu/random.png');
                    }
    
  9. Todo

    Explain the function of NewArticleTemplate better here and in terms of the subpages actually used by students.

    Modify the NewArticleTemplate extension so that subpage templates will be used even if the parent page does not exist.

    For example, without this modification, a new page User:Foo/Bar will use the User namespace subpage template MediaWiki:NewArticleTemplate/User/Subpage if the parent page User:Foo already exists, but it will use the User namespace template MediaWiki:NewArticleTemplate/User if User:Foo does not already exist.

    This modification will force the subpage template to always be used for subpages, regardless of whether the parent page exists or not.

    Download a patch file and apply it:

    wget -O /var/www/mediawiki/extensions/NewArticleTemplate/NewArticleTemplate_always-use-subpage-template.patch https://neurowiki-docs.readthedocs.io/en/latest/_downloads/NewArticleTemplate_always-use-subpage-template.patch
    patch -d /var/www/mediawiki/extensions/NewArticleTemplate < /var/www/mediawiki/extensions/NewArticleTemplate/NewArticleTemplate_always-use-subpage-template.patch
    

    If you are curious about the contents of the patch file, you can view it here:

    NewArticleTemplate_always-use-subpage-template.patch

    Direct link

    --- a/NewArticleTemplate.php
    +++ b/NewArticleTemplate.php
    @@ -52,12 +52,13 @@ function newArticleTemplates( $newPage ) {
     	$isSubpage = false;
     
     	if ( $title->isSubpage() ) {
    -		$baseTitle = Title::newFromText(
    -			$title->getBaseText(),
    -			$title->getNamespace() );
    -		if ( $baseTitle->exists() ) {
    -			$isSubpage = true;
    -		}
    +		#$baseTitle = Title::newFromText(
    +		#	$title->getBaseText(),
    +		#	$title->getNamespace() );
    +		#if ( $baseTitle->exists() ) {
    +		#	$isSubpage = true;
    +		#}
    +		$isSubpage = true;
     	}
     
     	/* we might want to return if this is a subpage */
    

    Todo

    Add hooks to NewArticleTemplate so that it works with VisualEditor.

    Todo

    Fork NewArticleTemplate on GitHub and incorporate the “always use subpage template” patch and the hooks for VisualEditor.

  10. Fix a bug in the Realnames extension (version 0.3.1) [2]. The Realnames extension includes a bug that causes subpages in the User namespace to lack titles. Download a patch file and apply it:

    wget -O /var/www/mediawiki/extensions/Realnames/Realnames_ignore-subpage-titles.patch https://neurowiki-docs.readthedocs.io/en/latest/_downloads/Realnames_ignore-subpage-titles.patch
    patch -d /var/www/mediawiki/extensions/Realnames < /var/www/mediawiki/extensions/Realnames/Realnames_ignore-subpage-titles.patch
    

    If you are curious about the contents of the patch file, you can view it here:

    Realnames_ignore-subpage-titles.patch

    Direct link

    --- a/Realnames.body.php
    +++ b/Realnames.body.php
    @@ -265,7 +265,7 @@
           if (in_array($title->getNamespace(), array(NS_USER, NS_USER_TALK))) { // User:
             // swap out the specific username from title
             // this overcomes the problem lookForBare has with spaces and underscores in names
    -        $out->setPagetitle(static::lookForBare($out->getPageTitle(),'/'.static::getNamespacePrefixes().'\s*('.$title->getText().')(?:\/.+)?/'));
    +        $out->setPagetitle(static::lookForBare($out->getPageTitle(),'~'.static::getNamespacePrefixes().'\s*('.$title->getText().')(?:/.+)?~'));
           }
    
           // this should also affect the html head title
    @@ -331,7 +331,7 @@
         if (empty($pattern)) {
           // considered doing [^<]+ here to catch names with spaces or underscores,
           // which works for most titles but is not universal
    -      $pattern = '/'.static::getNamespacePrefixes().'([^ \t]+)(:\/.+)?/';
    +      $pattern = '~'.static::getNamespacePrefixes().'([^ \t]+)(:/.+)?~';
         }
         wfDebugLog('realnames', __METHOD__.": pattern: ".$pattern);
         return preg_replace_callback(
    

    Todo

    Fork Realnames on GitHub and incorporate the “ignore subpage titles” patch.

  11. Fix a bug in the MediaWiki core that causes Lockdown to conflict with certain API calls [3]. In particular, this patch is needed to prevent the “Marking as patrolled failed” error and a silent failure when using the action=userrights API module. Download a patch file and apply it:

    wget -O /var/www/mediawiki/includes/user/Lockdown_api-compatibility.patch https://neurowiki-docs.readthedocs.io/en/latest/_downloads/Lockdown_api-compatibility.patch
    patch -d /var/www/mediawiki/includes/user < /var/www/mediawiki/includes/user/Lockdown_api-compatibility.patch
    

    If you are curious about the contents of the patch file, you can view it here:

    Lockdown_api-compatibility.patch

    Direct link

    --- b/User.php
    +++ a/User.php
    @@ -1355,8 +1355,8 @@
     	 */
     	protected function loadFromUserObject( $user ) {
     		$user->load();
    -		$user->loadGroups();
    -		$user->loadOptions();
    +		#$user->loadGroups();
    +		#$user->loadOptions();
     		foreach ( self::$mCacheVars as $var ) {
     			$this->$var = $user->$var;
     		}
    
  12. Give the web server ownership of and access to the new files:

    sudo chown -R www-data:www-data /var/www/
    sudo chmod -R ug+rw /var/www/
    
  13. Download and install the extension configuration settings:

    wget -P ~ https://neurowiki-docs.readthedocs.io/en/latest/_downloads/LocalSettings_extensions.php
    cat ~/LocalSettings_extensions.php >> /var/www/mediawiki/LocalSettings.php
    rm ~/LocalSettings_extensions.php
    

    If you are curious about the contents of the configuration file, you can view it here:

    LocalSettings_extensions.php

    Direct link

    # EXTENSIONS
    
    # CASAuthentication
    require_once("$IP/extensions/CASAuth/CASAuth.php");
    
    # EmbedVideo
    wfLoadExtension( 'EmbedVideo' );
    
    # ImportUsers
    require_once("$IP/extensions/ImportUsers/ImportUsers.php");
    
    # Interwiki -- automatically enabled above
    $wgGroupPermissions['sysop']['interwiki'] = true;
    
    ######################################################################
    # Lockdown
    
    # Non-admin users (students) can be prevented from editing the wiki
    # after the final deadline for the term paper. Toggle between states
    # by running
    #   sudo lock-wiki
    # which will change the value of this variable.
    $wikiLocked = false;
    
    # These lines are included just to get these groups to appear among
    # the list of available user groups.
    $wgGroupPermissions['term-paper-author']['read'] = true;
    $wgGroupPermissions['term-paper-deadline-extension']['read'] = true;
    
    # Define custom namespaces for term papers and prevent their inclusion
    # in other pages as templates
    define('NS_PRIVATE', 100);
    define('NS_PRIVATE_TALK', 101);
    $wgExtraNamespaces[NS_PRIVATE] = 'Private';
    $wgExtraNamespaces[NS_PRIVATE_TALK] = 'Private_talk';
    $wgNonincludableNamespaces[] = NS_PRIVATE;
    $wgNonincludableNamespaces[] = NS_PRIVATE_TALK;
    
    # The VisualEditor extension and its companion Parsoid server will
    # fail if a combination of MediaWiki's core permission system
    # ($wgGroupPermissions) and the Lockdown extension are used to
    # restrict access to the wiki. Here we remove all restrictions by
    # making the entire wiki readable and writable by anyone (including
    # users not logged in), but we will create restrictions below using
    # Lockdown.
    $wgGroupPermissions['*']['read'] = true;
    $wgGroupPermissions['*']['edit'] = true;
    
    # Load the Lockdown extension unless the request to access the wiki
    # comes from localhost (IP address 127.0.0.1, i.e., the virtual
    # machine itself). This will load Lockdown for all users accessing the
    # wiki through the web but not for the Parsoid server running on the
    # virtual machine, which is used by the VisualEditor extension. If
    # Lockdown is loaded when Parsoid tries to access the wiki (even if no
    # configuration variables are set), VisualEditor will fail.
    if ( !(array_key_exists('REMOTE_ADDR',$_SERVER) && $_SERVER['REMOTE_ADDR'] == '127.0.0.1') ) {
    
        # Load the extension
        require_once("$IP/extensions/Lockdown/Lockdown.php");
    
        # Restrict reading of term paper pages to term paper authors and
        # admins (instructors)
        $wgNamespacePermissionLockdown[NS_PRIVATE]['read']      = array('sysop', 'term-paper-author', 'term-paper-deadline-extension');
        $wgNamespacePermissionLockdown[NS_PRIVATE_TALK]['read'] = array('sysop', 'term-paper-author', 'term-paper-deadline-extension');
    
        # Restrict editing of all pages to admins (instructors), with a
        # few exceptions if the wiki is unlocked or if a student has a
        # term paper extension ('user' includes all logged in users)
        $wgNamespacePermissionLockdown['*']['edit'] = array('sysop');
        if ( !$wikiLocked ) {
            $wgNamespacePermissionLockdown[NS_TALK]['edit']         = array('user');
            $wgNamespacePermissionLockdown[NS_USER]['edit']         = array('user');
            $wgNamespacePermissionLockdown[NS_USER_TALK]['edit']    = array('user');
            $wgNamespacePermissionLockdown[NS_FILE]['edit']         = array('user');
            $wgNamespacePermissionLockdown[NS_PRIVATE]['edit']      = array('sysop', 'term-paper-author');
            $wgNamespacePermissionLockdown[NS_PRIVATE_TALK]['edit'] = array('sysop', 'term-paper-author');
        } else {
            $wgNamespacePermissionLockdown[NS_PRIVATE]['edit']      = array('sysop', 'term-paper-deadline-extension');
        }
    
        # Restrict moving of all pages to sysop, with a few exceptions if
        # the wiki is unlocked ('user' includes all logged in users)
        $wgNamespacePermissionLockdown['*']['move'] = array('sysop');
        if ( !$wikiLocked ) {
            $wgNamespacePermissionLockdown[NS_USER]['move']    = array('user');
            $wgNamespacePermissionLockdown[NS_FILE]['move']    = array('user');
            $wgNamespacePermissionLockdown[NS_PRIVATE]['move'] = array('sysop', 'term-paper-author');
        } else {
            $wgNamespacePermissionLockdown[NS_PRIVATE]['move'] = array('sysop', 'term-paper-deadline-extension');
        }
    }
    
    # END Lockdown
    ##########################################################################
    
    # Math
    wfLoadExtension( 'Math' );
    $wgMathFullRestbaseURL = 'https://api.formulasearchengine.com/';
    $wgMathValidModes = array('mathml', 'png', 'source');
    $wgDefaultUserOptions['math'] = 'png';
    $wgHiddenPrefs[] = 'math';
    
    # MobileFrontend
    wfLoadExtension( 'MobileFrontend' );
    $wgMFAutodetectMobileView = true;
    
    # NewArticleTemplate
    require_once ("$IP/extensions/NewArticleTemplate/NewArticleTemplate.php");
    $wgNewArticleTemplatesEnable = true;
    $wgNewArticleTemplatesOnSubpages = true;
    $wgNewArticleTemplatesNamespaces = array(
        NS_USER      => 1,
        NS_USER_TALK => 1
    );
    $wgNewArticleTemplates_PerNamespace = array(
        NS_USER      => "MediaWiki:NewArticleTemplate/User",
        NS_USER_TALK => "MediaWiki:NewArticleTemplate/User Talk"
    );
    
    # Realnames
    require_once("$IP/extensions/Realnames/Realnames.php");
    
    # ScholasticGrading
    require_once("$IP/extensions/ScholasticGrading/ScholasticGrading.php");
    $wgGroupPermissions['grader']['editgrades'] = true;
    
    # Scribunto
    require_once("$IP/extensions/Scribunto/Scribunto.php");
    $wgScribuntoDefaultEngine = 'luastandalone';
    
    # UserMerge
    wfLoadExtension( 'UserMerge' );
    $wgGroupPermissions['*']['usermerge'] = false;
    $wgGroupPermissions['sysop']['usermerge'] = true;
    $wgUserMergeProtectedGroups = array('sysop');
    
    # VisualEditor
    wfLoadExtension( 'VisualEditor' );
    $wgDefaultUserOptions['visualeditor-enable'] = 0;
    $wgDefaultUserOptions['visualeditor-hidebetawelcome'] = 1;
    $wgVirtualRestConfig['modules']['parsoid'] = array(
        'url' => 'http://localhost:8142',   # use http, not https
        'prefix' => 'localhost',
        'domain' => 'localhost',
        'forwardCookies' => true,
    );
    $wgVisualEditorAvailableNamespaces = array(
        NS_MAIN         => true,
        NS_TALK         => true,
        NS_USER         => true,
        NS_USER_TALK    => true,
        NS_PRIVATE      => true,
        NS_PRIVATE_TALK => true,
        NS_HELP         => true,
        NS_PROJECT      => true,
    );
    
    # WikiEditor -- automatically enabled above
    $wgDefaultUserOptions['usebetatoolbar'] = true;
    $wgDefaultUserOptions['usebetatoolbar-cgd'] = true;
    $wgDefaultUserOptions['wikieditor-preview'] = true;
    

    Todo

    Post my solution for the VisualEditor + Lockdown extension conflict to the discussion board, and then provide a “This solution is documented here” footnote in these instructions.

  14. Create database tables for the Math and ScholasticGrading extensions:

    php /var/www/mediawiki/maintenance/update.php
    
  15. Create aliases for URLs to the surveys and simulations using “interwiki” links. Interwiki links allow MediaWiki sites to easily create links to one another. For example, using [[wikipedia:Neuron]] on our wiki will create a link directly to the Wikipedia article on neurons. Here we use this capability to create aliases, such as [[survey:1]], that make linking to the surveys and simulations easier.

    Run the following (you will be prompted for the MySQL password twice):

    echo "INSERT INTO interwiki (iw_prefix,iw_url,iw_api,iw_wikiid,iw_local,iw_trans) VALUES ('survey','/django/survey/\$1/','','',0,0)" | mysql -u root -p wikidb
    echo "INSERT INTO interwiki (iw_prefix,iw_url,iw_api,iw_wikiid,iw_local,iw_trans) VALUES ('sim','/JSNeuroSim/simulations/\$1.html','','',0,0)" | mysql -u root -p wikidb
    
  16. Create a script for toggling the locked state of the wiki by downloading and installing a file:

    sudo wget -O /usr/local/sbin/lock-wiki https://neurowiki-docs.readthedocs.io/en/latest/_downloads/lock-wiki
    sudo chmod +x /usr/local/sbin/lock-wiki
    

    If you are curious about the contents of the script, you can view it here:

    lock-wiki

    Direct link

    #!/bin/bash
    
    # Place this script in /usr/local/sbin and make it executable (chmod +x).
    #
    # This script will toggle the locked state of the wiki. When the wiki is locked,
    # only admins and term paper authors with a deadline extension can edit the
    # wiki.
    
    
    # Function for aborting with an error message
    
    die () {
        echo >&2 "$@"
        exit 1
    }
    
    
    # Require that the user is root.
    
    [ "$UID" -eq 0 ] || die "Aborted: superuser privileges needed (rerun with sudo)"
    
    
    # Get the current state of the $wikiLocked variable
    
    STATE=$(grep ^\$wikiLocked /var/www/mediawiki/LocalSettings.php | awk '{ print $3 }')
    
    
    # Determine the new state
    
    if [ "$STATE" == "true;" ]; then
        NEWSTATE="false;"
        echo "Wiki is now UNLOCKED. Non-admins CAN make edits."
    else
        NEWSTATE="true;"
        echo "Wiki is now LOCKED. Non-admins CANNOT make edits (unless they have a term paper deadline extension, set using Special:UserRights and listed at Special:ListUsers)."
    fi
    
    
    # Set the new state.
    
    sed -i '/^\$wikiLocked/s|= \(.*\);|= '$NEWSTATE'|' /var/www/mediawiki/LocalSettings.php
    
    exit 0
    
  17. At this point, individuals with CWRU accounts can log into the wiki, which will create a wiki account for them. Invite the TAs to do this now. After their accounts are created, you should visit (while logged in)

    https://dynamicshjc.case.edu:8014/wiki/Special:UserRights

    For each TA, enter their wiki user name (which should match their CWRU user name), and add them to the following groups:

    • administrator
      • Administrators have special powers on the wiki, such as moving, deleting, or protecting pages.
    • bureaucrat
      • Bureaucrats have the ability to change group membership (using the Special:UserRights page) for any user, including administrators and other bureaucrats (making this the most powerful group).
    • grader
      • Graders can view and edit all grades on the Special:Grades page.

    Add yourself to the grader group as well (you should already be a member of the other groups).

  18. Check that all extensions are installed and working properly. Visit Special:Version and compare the list of installed extensions to the list of extensions at the beginning of this section of the instructions.

    You can test each of the essential extensions by doing the following:

    Extension Test
    CASAuthentication log in using CWRU’s Single Sign-On
    EmbedVideo try adding {{#ev:youtube|8zRtXBrmvyc||center|Survival Guide}} to a page
    ImportUsers visit Special:ImportUsers
    Lockdown remove yourself from the administrator group using Special:UserRights and try editing a policy page (restore privileges when done!)
    Math try adding <math>x=\sqrt{2}</math> to a page
    MobileFrontend click the “Mobile view” link at the bottom of any page (click “Desktop” to return to normal)
    NewArticleTemplate will test later…
    Realnames log in and look for your full name in the top right of the page
    ScholasticGrading visit Special:Grades
    UserMerge visit Special:UserMerge
    VisualEditor enable VE under Preferences > Editing, and then try editing a page by clicking “Edit” (not “Edit source”)

    Todo

    Embedded videos don’t render in VisualEditor. Fix?

    Todo

    When attempting to upload files through VisualEditor, it thinks I’m not logged in. Fix!

  19. Shut down the virtual machine:

    sudo shutdown -h now
    
  20. Using VirtualBox, take a snapshot of the current state of the virtual machine. Name it “MediaWiki extensions installed”.

Footnotes

[1]

This extension creates a Special page, Special:ImportUsers. After using it, run

php /var/www/mediawiki/maintenance/initSiteStats.php

to update the user count displayed on the wiki statistics page, Special:Statistics (“Active users” will change to “-1” after the script is run, but this will correct itself the next time an edit is made on the wiki).

[2]This solution is documented here.
[3]This issue is described here, and this patch (used in these instructions) was proposed for fixing it. Later, another patch was proposed, but I have not tested it since the first one works for our purposes. One or both of these patches was expected to be included in 1.27.2+, but as of July 2017 the bug is reported to still be present.