tosfos has uploaded a new change for review. ( 
https://gerrit.wikimedia.org/r/399772 )

Change subject: Initial commit
......................................................................

Initial commit

Change-Id: Ibd6b185e30aa769b66f0649886e732e2cef651de
---
A .gitignore
A Gruntfile.js
A Makefile
A PreferencesList.class.php
A PreferencesList.i18n.alias.php
A PreferencesList.php
A PreferencesListPreferences.php
A PreferencesListUtils.php
A README.md
A composer.json
A composer.lock
A extension.json
A i18n/en.json
A i18n/qqq.json
A nbproject/project.properties
A nbproject/project.xml
A package.json
A phpcs.xml
A specials/SpecialPreferencesList.php
19 files changed, 1,072 insertions(+), 0 deletions(-)


  git pull 
ssh://gerrit.wikimedia.org:29418/mediawiki/extensions/PreferencesList 
refs/changes/72/399772/1

diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..2e0eacb
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,2 @@
+/vendor/
+/nbproject/private/
\ No newline at end of file
diff --git a/Gruntfile.js b/Gruntfile.js
new file mode 100755
index 0000000..36b41e8
--- /dev/null
+++ b/Gruntfile.js
@@ -0,0 +1,35 @@
+/*jshint node:true */
+module.exports = function ( grunt ) {
+       grunt.loadNpmTasks( 'grunt-contrib-jshint' );
+       grunt.loadNpmTasks( 'grunt-jsonlint' );
+       grunt.loadNpmTasks( 'grunt-banana-checker' );
+       grunt.loadNpmTasks( 'grunt-jscs' );
+
+       grunt.initConfig( {
+               jshint: {
+                       options: {
+                               jshintrc: true
+                       },
+                       all: [
+                               '*.js',
+                               'modules/**/*.js'
+                       ]
+               },
+               jscs: {
+                       src: '<%= jshint.all %>'
+               },
+               banana: {
+                       all: 'i18n/'
+               },
+               jsonlint: {
+                       all: [
+                               '**/*.json',
+                               '!node_modules/**',
+                               '!vendor/**'
+                       ]
+               }
+       } );
+
+       grunt.registerTask( 'test', [ 'jshint', 'jscs', 'jsonlint', 'banana' ] 
);
+       grunt.registerTask( 'default', 'test' );
+};
diff --git a/Makefile b/Makefile
new file mode 100755
index 0000000..84f6ed8
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,48 @@
+# Used elements
+# http://marmelab.com/blog/2016/02/29/auto-documented-makefile.html
+# 
http://unix.stackexchange.com/questions/217295/phony-all-rules-in-gnu-make-file
+
+.DEFAULT_GOAL := help
+
+.PHONY: install
+install: _npm _composer  ## Updates PHP / JS dependencies
+       @npm install
+       @composer install
+
+.PHONY: update
+update: _npm _composer ## Updates PHP / JS dependencies (writes composer.lock)
+       @npm update
+       @composer update
+
+# See https://www.mediawiki.org/wiki/Continuous_integration/Entry_points
+.PHONY: test
+test: _npm _composer ## Runs tests (see composer.json / Gruntfile.js)
+       @npm test
+       @composer test
+
+fix: _phpcbf
+       @vendor/bin/phpcbf
+
+################################################################################
+_COMPOSER := $(shell composer -V)
+_NPM := $(shell npm -v)
+_PHPCBF := $(shell vendor/bin/phpcbf --version)
+
+_npm:
+ifndef _COMPOSER
+       @printf "You can get npm @ https://nodejs.org/en/download/\n";
+endif
+
+_composer:
+ifndef _NPM
+       @printf "You can get composer @ https://getcomposer.org/\n";
+endif
+
+_phpcbf:
+ifndef _PHPCBF
+       @printf "Please run composer install first\n"
+endif
+
+.PHONY: help
+help:
+       @grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | awk 'BEGIN 
{FS = ":.*?## "}; {printf "\033[36m%-10s\033[0m %s\n", $$1, $$2}'
diff --git a/PreferencesList.class.php b/PreferencesList.class.php
new file mode 100755
index 0000000..f8d5924
--- /dev/null
+++ b/PreferencesList.class.php
@@ -0,0 +1,251 @@
+<?php
+/*
+ * Copyright (C) 2017 Ike Hecht <[email protected]>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+
+/**
+ * Description of PreferencesList
+ *
+ * @author Ike Hecht <[email protected]>
+ */
+class PreferencesList {
+       /**
+        *
+        * @var IContextSource
+        */
+       protected $context;
+
+       /**
+        * List of all preferences in the wiki in Form Field style
+        *
+        * @var array
+        */
+       protected $allPreferences;
+
+       /**
+        * Display options
+        */
+       const CSV = 1;
+       const TABLE = 2;
+
+       /**
+        * Constructor
+        *
+        * @param IContextSource $context
+        * @param array $allPreferences
+        */
+       function __construct( IContextSource $context, array $allPreferences ) {
+               $this->context = $context;
+               $this->allPreferences = $allPreferences;
+       }
+
+       /**
+        * Fetch the Preferences for all Users in the wiki, and return a Form 
Fields style array
+        *
+        *
+        * @param string $preferenceName
+        * @param IContextSource $context
+        * @return array
+        */
+       private static function getAllUsersPreferences( $preferenceName, 
IContextSource $context ) {
+               $dbr = wfGetDB( DB_SLAVE );
+               $res = $dbr->select(
+                       'user', User::selectFields(), '', __METHOD__
+               );
+               $users = new UserArrayFromResult( $res );
+               $preferencesArray = [];
+               foreach ( $users as $user ) {
+                       $preferences = 
PreferencesListPreferences::getPreferences( $user, $context );
+                       // For some reason this is not always set. If it isn't, 
assume 0.
+                       if ( isset( $preferences[$preferenceName]['default'] ) 
) {
+                               $preferencesArray[$user->getName()] = 
$preferences[$preferenceName]['default'];
+                       } else {
+                               $preferencesArray[$user->getName()] = 0;
+                       }
+                       /** @todo is it safe to use User Name as Key? Maybe ID 
would be better. */
+               }
+               return $preferencesArray;
+       }
+
+       /**
+        * Get a list of preference fields that should not be displayed in the 
Preferences List
+        *
+        * @return array
+        */
+       protected function getSkipFields() {
+               return [ 'username', 'csv', 'password', 'emailauthentication', 
'editwatchlist' ];
+       }
+
+       /**
+        * Based on the FormOptions, send back an array of Form Fields
+        *
+        * @param FormOptions $opts
+        * @return array
+        */
+       public function getFormFields( FormOptions $opts ) {
+               $skipFields = $this->getSkipFields();
+               $allOptions = $opts->getAllValues();
+               $formFields = [];
+               $attributesWeWant = [ 'label', 'label-message', 'label-raw', 
'section' ];
+               foreach ( $allOptions as $key => $value ) {
+                       if ( in_array( $key, $skipFields ) ) {
+                               continue;
+                       }
+                       /** @todo It may save processing to do this in an 
overloading filterDataForSubmit() */
+                       $preferencesField = $this->allPreferences[$key];
+
+                       $formFields[$key]['type'] = 'check';
+                       $formFields[$key]['default'] = false;
+
+                       // Now take data from the standard field to suit our 
purposes.
+                       foreach ( $attributesWeWant as $field ) {
+                               if ( isset( $preferencesField[$field] ) ) {
+                                       $formFields[$key][$field] = 
$preferencesField[$field];
+                               }
+                       }
+
+                       if ( isset( $preferencesField['label'] ) && 
$preferencesField['label'] == '&#160;' ) {
+                               // If the label is not set, use this 
preference's subsection as its label
+                               $sectionInfo = explode( '/', 
$preferencesField['section'] );
+                               /** @todo Use this skin's prefix */
+                               $formFields[$key]['label-message'] = 'prefs-' . 
$sectionInfo[1];
+                       }
+               }
+
+               // Add a CSV checkbox. This isn't a Preference.
+               $formFields['csv'] = [ 'type' => 'check', 'label-message' => 
'preferenceslist-csv' ];
+
+               return $formFields;
+       }
+
+       /**
+        * Download a CSV of the results
+        *
+        * @param array $preferences Preference keys to be displayed
+        * @param array $allUsersPreferences The data to be displayed
+        * @return boolean
+        */
+       protected function downloadCSV( array $preferences, array 
$allUsersPreferences ) {
+               $rows = $this->getRows( $preferences, $allUsersPreferences );
+
+               // Take the $userName key and prepend it to the value array
+               foreach ( $rows as $userName => &$userPrefs ) {
+                       if ( $userName !== 0 ) { // Special handling for the 
header row
+                               array_unshift( $userPrefs, $userName );
+                       }
+               }
+
+               PreferencesListUtils::arrayToCsvDownload( $rows );
+
+               /** @todo Only return true if this worked */
+               return true;
+       }
+
+       /**
+        * Get the rows of usernames and preference values to be displayed, 
including the header as
+        * the first row
+        *
+        * @param array $preferences Preference keys to be displayed
+        * @return array
+        */
+       private function getRows( array $preferences, $allUsersPreferences ) {
+               $rows = [];
+               /** @todo i18n */
+               $rows[0][] = 'username';
+               foreach ( $preferences as $preferenceToShow ) {
+                       $rows[0][] = $preferenceToShow;/** @todo i18n or 
something */
+                       foreach ( $allUsersPreferences[$preferenceToShow] as 
$userName => $userPref ) {
+                               $rows[$userName][$preferenceToShow] = 
$this->formatText( $userPref, $preferenceToShow );
+                       }
+               }
+               return $rows;
+       }
+
+       /**
+        * Do special formatting for certain fields
+        *
+        * @param string $userPref What this preference was set to
+        * @param string $preferenceKey
+        */
+       protected function formatText( $userPref, $preferenceKey ) {
+               $preferenceDescriptor = $this->allPreferences[$preferenceKey];
+               // Make true/false preferences human-readable
+               if ( isset( $preferenceDescriptor['type'] ) && 
$preferenceDescriptor['type'] === 'toggle' ) {
+                       if ( $userPref == '1' ) {
+                               return 'yes';/** @todo i18n */
+                       } else {
+                               return 'no';
+                       }
+               }
+               # print_r( $preferenceDescriptor );
+               if ( $preferenceKey === 'emailaddress' ) {
+                       // Strip change/add email address links
+                       // From https://stackoverflow.com/a/33865191
+                       $matches = [];
+                       if ( preg_match( 
"/[\._a-zA-Z0-9-]+@[\._a-zA-Z0-9-]+/i", $userPref, $matches ) ) {
+                               return $matches[0];
+                       } else {
+                               return '';
+                       }
+               }
+               return $userPref;
+       }
+
+       /**
+        * Show the subpage with correct preferences
+        *
+        */
+       protected function getTable( array $preferences, array 
$allUsersPreferences ) {
+               $rows = $this->getRows( $preferences, $allUsersPreferences );
+
+               $html = Html::openElement( 'table', [ 'class' => 'wikitable' ] 
);
+
+               $labels = $rows[0];
+               unset( $rows[0] );
+               # print_r( $bodyRows );
+
+               $html .= Html::openElement( 'tr' );
+               foreach ( $labels as $label ) {
+                       $html .= Html::rawElement( 'th', [], $label );
+               }
+               $html .= Html::closeElement( 'tr' );
+
+               foreach ( $rows as $userName => $userPrefs ) {
+                       $html .= Html::openElement( 'tr' );
+                       $html .= Html::element( 'th', [], $userName );
+                       foreach ( $userPrefs as $userPref ) {
+                               $html .= Html::rawElement( 'td', [], $userPref 
);
+                       }
+                       $html .= Html::closeElement( 'tr' );
+               }
+               $html .= Html::closeElement( 'table' );
+
+               return $html;
+       }
+
+       public function getResults( $preferencesToShow, $format, $context ) {
+               foreach ( $preferencesToShow as $preferenceToShow ) {
+                       $allUsersPreferences[$preferenceToShow] = 
PreferencesList::getAllUsersPreferences(
+                                       $preferenceToShow, $context );
+               }
+               if ( $format === self::CSV ) {
+                       return $this->downloadCSV( $preferencesToShow, 
$allUsersPreferences );
+               } elseif ( $format === self::TABLE ) {
+                       return $this->getTable( $preferencesToShow, 
$allUsersPreferences );
+               }
+       }
+}
diff --git a/PreferencesList.i18n.alias.php b/PreferencesList.i18n.alias.php
new file mode 100755
index 0000000..c4b02ce
--- /dev/null
+++ b/PreferencesList.i18n.alias.php
@@ -0,0 +1,15 @@
+<?php
+/**
+ * Aliases for special pages of the PreferencesList extension
+ *
+ * @file
+ * @ingroup Extensions
+ */
+
+$specialPageAliases = [];
+
+/** English (English) */
+$specialPageAliases['en'] = [
+       'PreferencesList' => [ 'PreferencesList' ],
+];
+
diff --git a/PreferencesList.php b/PreferencesList.php
new file mode 100755
index 0000000..197a45e
--- /dev/null
+++ b/PreferencesList.php
@@ -0,0 +1,16 @@
+<?php
+
+if ( function_exists( 'wfLoadExtension' ) ) {
+       wfLoadExtension( 'PreferencesList' );
+       // Keep i18n globals so mergeMessageFileList.php doesn't break
+       $wgMessagesDirs['PreferencesList'] = __DIR__ . '/i18n';
+       $wgExtensionMessagesFiles['PreferencesListAlias'] = __DIR__ . 
'/PreferencesList.i18n.alias.php';
+       $wgExtensionMessagesFiles['PreferencesListMagic'] = __DIR__ . 
'/PreferencesList.i18n.magic.php';
+       wfWarn(
+               'Deprecated PHP entry point used for PreferencesList extension. 
Please use wfLoadExtension ' .
+               'instead, see 
https://www.mediawiki.org/wiki/Extension_registration for more details.'
+       );
+       return true;
+} else {
+       die( 'This version of the PreferencesList extension requires MediaWiki 
1.25+' );
+}
diff --git a/PreferencesListPreferences.php b/PreferencesListPreferences.php
new file mode 100644
index 0000000..72bc954
--- /dev/null
+++ b/PreferencesListPreferences.php
@@ -0,0 +1,51 @@
+<?php
+/*
+ * Copyright (C) 2017 Ike Hecht <[email protected]>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+
+/**
+ * Description of PreferencesListPreferences
+ *
+ * @author Ike Hecht <[email protected]>
+ */
+class PreferencesListPreferences extends Preferences {
+
+       /**
+        * Gets the Preferences for the user requested. Basically does the same 
thing as
+        * the parent, except it makes sure it's not returning the cached 
current user's preferences.
+        *
+        * @throws MWException
+        * @param User $user
+        * @param IContextSource $context
+        * @return array|null
+        */
+       static function getPreferences( $user, IContextSource $context ) {
+               # This is the parent's line that results in the need for this 
function. MediaWiki expects that
+               # all preferences being looked up belong to one user. This 
function is based on REL1_25.
+               # if ( self::$defaultPreferences ) {
+               # return self::$defaultPreferences;
+               # }
+
+               $defaultPreferences = self::$defaultPreferences;
+               self::$defaultPreferences = null;
+               $preferences = parent::getPreferences( $user, $context );
+               // Be nice and set this back to the way it was.
+               self::$defaultPreferences = $defaultPreferences;
+
+               return $preferences;
+       }
+}
diff --git a/PreferencesListUtils.php b/PreferencesListUtils.php
new file mode 100644
index 0000000..2e426d9
--- /dev/null
+++ b/PreferencesListUtils.php
@@ -0,0 +1,48 @@
+<?php
+/*
+ * Copyright (C) 2017 Ike Hecht <[email protected]>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+
+/**
+ * Some utilities for PreferencesList
+ *
+ * @author Ike Hecht <[email protected]>
+ */
+class PreferencesListUtils {
+       /**
+        * Convert an array to a CSV
+        * From https://stackoverflow.com/a/16251849
+        *
+        * @param array $array Numbered array where each element is an array 
that will be converted
+        * to a row
+        * @param string $filename
+        * @param string $delimiter
+        */
+       public static function arrayToCsvDownload(
+       array $array, $filename = 'export.csv', $delimiter = ';' ) {
+               /** @todo Should the filename get i18n? */
+               header( 'Content-Type: application/csv' );
+               header( 'Content-Disposition: attachment; filename="' . 
$filename . '";' );
+
+               $f = fopen( 'php://output', 'w' );
+
+               foreach ( $array as $line ) {
+                       fputcsv( $f, $line, $delimiter );
+               }
+               /** @todo return success or failure */
+       }
+}
diff --git a/README.md b/README.md
new file mode 100755
index 0000000..a6eccf5
--- /dev/null
+++ b/README.md
@@ -0,0 +1,22 @@
+# PreferencesList
+
+Generates a list of all user settings for a particular preference. The full 
documentation is at
+https://www.mediawiki.org/wiki/Extension:PreferencesList
+
+## Features
+
+ * [Special page](https://www.mediawiki.org/wiki/Manual:Special_pages) 
(specials/SpecialPreferencesList.php)
+
+## Development on Linux (OS X anyone?)
+To take advantage of this automation, use the Makefile: `make help`. To start,
+run `make install` and follow the instructions.
+
+## Development on Windows
+Since you cannot use the `Makefile` on Windows, do the following:
+
+  # Install nodejs, npm, and PHP composer
+  # Change to the extension's directory
+  # npm install
+  # composer install
+
+Once set up, running `npm test` and `composer test` will run automated code 
checks.
diff --git a/composer.json b/composer.json
new file mode 100755
index 0000000..0d6fc0a
--- /dev/null
+++ b/composer.json
@@ -0,0 +1,19 @@
+{
+  "name": "preferenceslist/preferences-list",
+  "type": "mediawiki-extension",
+  "require-dev": {
+       "jakub-onderka/php-parallel-lint": "0.9.2",
+       "mediawiki/mediawiki-codesniffer": "0.7.2"
+  },
+  "scripts": {
+       "fix": "phpcbf",
+       "test": [
+         "parallel-lint . --exclude vendor",
+         "phpcs -p -s"
+       ]
+  },
+  "require": {
+       "php": ">=5.6",
+       "composer/installers": "~1.0"
+  }
+}
diff --git a/composer.lock b/composer.lock
new file mode 100644
index 0000000..1bfcb13
--- /dev/null
+++ b/composer.lock
@@ -0,0 +1,299 @@
+{
+    "_readme": [
+        "This file locks the dependencies of your project to a known state",
+        "Read more about it at 
https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file";,
+        "This file is @generated automatically"
+    ],
+    "content-hash": "b8b37ae524234169b431ca9411e4ec39",
+    "packages": [
+        {
+            "name": "composer/installers",
+            "version": "v1.4.0",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/composer/installers.git";,
+                "reference": "9ce17fb70e9a38dd8acff0636a29f5cf4d575c1b"
+            },
+            "dist": {
+                "type": "zip",
+                "url": 
"https://api.github.com/repos/composer/installers/zipball/9ce17fb70e9a38dd8acff0636a29f5cf4d575c1b";,
+                "reference": "9ce17fb70e9a38dd8acff0636a29f5cf4d575c1b",
+                "shasum": ""
+            },
+            "require": {
+                "composer-plugin-api": "^1.0"
+            },
+            "replace": {
+                "roundcube/plugin-installer": "*",
+                "shama/baton": "*"
+            },
+            "require-dev": {
+                "composer/composer": "1.0.*@dev",
+                "phpunit/phpunit": "4.1.*"
+            },
+            "type": "composer-plugin",
+            "extra": {
+                "class": "Composer\\Installers\\Plugin",
+                "branch-alias": {
+                    "dev-master": "1.0-dev"
+                }
+            },
+            "autoload": {
+                "psr-4": {
+                    "Composer\\Installers\\": "src/Composer/Installers"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/";,
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Kyle Robinson Young",
+                    "email": "[email protected]",
+                    "homepage": "https://github.com/shama";
+                }
+            ],
+            "description": "A multi-framework Composer library installer",
+            "homepage": "https://composer.github.io/installers/";,
+            "keywords": [
+                "Craft",
+                "Dolibarr",
+                "Eliasis",
+                "Hurad",
+                "ImageCMS",
+                "Kanboard",
+                "Lan Management System",
+                "MODX Evo",
+                "Mautic",
+                "Maya",
+                "OXID",
+                "Plentymarkets",
+                "Porto",
+                "RadPHP",
+                "SMF",
+                "Thelia",
+                "WolfCMS",
+                "agl",
+                "aimeos",
+                "annotatecms",
+                "attogram",
+                "bitrix",
+                "cakephp",
+                "chef",
+                "cockpit",
+                "codeigniter",
+                "concrete5",
+                "croogo",
+                "dokuwiki",
+                "drupal",
+                "eZ Platform",
+                "elgg",
+                "expressionengine",
+                "fuelphp",
+                "grav",
+                "installer",
+                "itop",
+                "joomla",
+                "kohana",
+                "laravel",
+                "lavalite",
+                "lithium",
+                "magento",
+                "mako",
+                "mediawiki",
+                "modulework",
+                "moodle",
+                "osclass",
+                "phpbb",
+                "piwik",
+                "ppi",
+                "puppet",
+                "reindex",
+                "roundcube",
+                "shopware",
+                "silverstripe",
+                "sydes",
+                "symfony",
+                "typo3",
+                "wordpress",
+                "yawik",
+                "zend",
+                "zikula"
+            ],
+            "time": "2017-08-09T07:53:48+00:00"
+        }
+    ],
+    "packages-dev": [
+        {
+            "name": "jakub-onderka/php-parallel-lint",
+            "version": "v0.9.2",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/JakubOnderka/PHP-Parallel-Lint.git";,
+                "reference": "2ead2e4043ab125bee9554f356e0a86742c2d4fa"
+            },
+            "dist": {
+                "type": "zip",
+                "url": 
"https://api.github.com/repos/JakubOnderka/PHP-Parallel-Lint/zipball/2ead2e4043ab125bee9554f356e0a86742c2d4fa";,
+                "reference": "2ead2e4043ab125bee9554f356e0a86742c2d4fa",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=5.3.3"
+            },
+            "require-dev": {
+                "jakub-onderka/php-console-highlighter": "~0.3",
+                "nette/tester": "~1.3"
+            },
+            "suggest": {
+                "jakub-onderka/php-console-highlighter": "Highlight syntax in 
code snippet"
+            },
+            "bin": [
+                "parallel-lint"
+            ],
+            "type": "library",
+            "autoload": {
+                "classmap": [
+                    "./"
+                ]
+            },
+            "notification-url": "https://packagist.org/downloads/";,
+            "license": [
+                "BSD-2-Clause"
+            ],
+            "authors": [
+                {
+                    "name": "Jakub Onderka",
+                    "email": "[email protected]"
+                }
+            ],
+            "description": "This tool check syntax of PHP files about 20x 
faster than serial check.",
+            "homepage": "https://github.com/JakubOnderka/PHP-Parallel-Lint";,
+            "time": "2015-12-15T10:42:16+00:00"
+        },
+        {
+            "name": "mediawiki/mediawiki-codesniffer",
+            "version": "v0.7.2",
+            "source": {
+                "type": "git",
+                "url": 
"https://github.com/wikimedia/mediawiki-tools-codesniffer.git";,
+                "reference": "6b713bcbb9c20a3bdad76f9477458c9b4ae0773b"
+            },
+            "dist": {
+                "type": "zip",
+                "url": 
"https://api.github.com/repos/wikimedia/mediawiki-tools-codesniffer/zipball/6b713bcbb9c20a3bdad76f9477458c9b4ae0773b";,
+                "reference": "6b713bcbb9c20a3bdad76f9477458c9b4ae0773b",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">= 5.5.9",
+                "squizlabs/php_codesniffer": "2.6.0"
+            },
+            "require-dev": {
+                "jakub-onderka/php-parallel-lint": "0.9.*",
+                "mikey179/vfsstream": "~1.6",
+                "phpunit/phpunit": "~4.1"
+            },
+            "type": "library",
+            "notification-url": "https://packagist.org/downloads/";,
+            "license": [
+                "GPL-2.0+"
+            ],
+            "description": "MediaWiki CodeSniffer Standards",
+            "homepage": 
"https://www.mediawiki.org/wiki/Manual:Coding_conventions/PHP";,
+            "keywords": [
+                "codesniffer",
+                "mediawiki"
+            ],
+            "time": "2016-05-28T01:08:59+00:00"
+        },
+        {
+            "name": "squizlabs/php_codesniffer",
+            "version": "2.6.0",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/squizlabs/PHP_CodeSniffer.git";,
+                "reference": "1bcdf03b068a530ac1962ce671dead356eeba43b"
+            },
+            "dist": {
+                "type": "zip",
+                "url": 
"https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/1bcdf03b068a530ac1962ce671dead356eeba43b";,
+                "reference": "1bcdf03b068a530ac1962ce671dead356eeba43b",
+                "shasum": ""
+            },
+            "require": {
+                "ext-simplexml": "*",
+                "ext-tokenizer": "*",
+                "ext-xmlwriter": "*",
+                "php": ">=5.1.2"
+            },
+            "require-dev": {
+                "phpunit/phpunit": "~4.0"
+            },
+            "bin": [
+                "scripts/phpcs",
+                "scripts/phpcbf"
+            ],
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "2.x-dev"
+                }
+            },
+            "autoload": {
+                "classmap": [
+                    "CodeSniffer.php",
+                    "CodeSniffer/CLI.php",
+                    "CodeSniffer/Exception.php",
+                    "CodeSniffer/File.php",
+                    "CodeSniffer/Fixer.php",
+                    "CodeSniffer/Report.php",
+                    "CodeSniffer/Reporting.php",
+                    "CodeSniffer/Sniff.php",
+                    "CodeSniffer/Tokens.php",
+                    "CodeSniffer/Reports/",
+                    "CodeSniffer/Tokenizers/",
+                    "CodeSniffer/DocGenerators/",
+                    "CodeSniffer/Standards/AbstractPatternSniff.php",
+                    "CodeSniffer/Standards/AbstractScopeSniff.php",
+                    "CodeSniffer/Standards/AbstractVariableSniff.php",
+                    "CodeSniffer/Standards/IncorrectPatternException.php",
+                    "CodeSniffer/Standards/Generic/Sniffs/",
+                    "CodeSniffer/Standards/MySource/Sniffs/",
+                    "CodeSniffer/Standards/PEAR/Sniffs/",
+                    "CodeSniffer/Standards/PSR1/Sniffs/",
+                    "CodeSniffer/Standards/PSR2/Sniffs/",
+                    "CodeSniffer/Standards/Squiz/Sniffs/",
+                    "CodeSniffer/Standards/Zend/Sniffs/"
+                ]
+            },
+            "notification-url": "https://packagist.org/downloads/";,
+            "license": [
+                "BSD-3-Clause"
+            ],
+            "authors": [
+                {
+                    "name": "Greg Sherwood",
+                    "role": "lead"
+                }
+            ],
+            "description": "PHP_CodeSniffer tokenizes PHP, JavaScript and CSS 
files and detects violations of a defined set of coding standards.",
+            "homepage": "http://www.squizlabs.com/php-codesniffer";,
+            "keywords": [
+                "phpcs",
+                "standards"
+            ],
+            "time": "2016-04-03T22:58:34+00:00"
+        }
+    ],
+    "aliases": [],
+    "minimum-stability": "stable",
+    "stability-flags": [],
+    "prefer-stable": false,
+    "prefer-lowest": false,
+    "platform": {
+        "php": ">=5.6"
+    },
+    "platform-dev": []
+}
diff --git a/extension.json b/extension.json
new file mode 100755
index 0000000..2b4f4c7
--- /dev/null
+++ b/extension.json
@@ -0,0 +1,38 @@
+{
+       "name": "PreferencesList",
+       "version": "0.1.0",
+       "author": [
+               "Ike Hecht"
+       ],
+       "url": "https://www.mediawiki.org/wiki/Extension:PreferencesList";,
+       "descriptionmsg": "preferenceslist-desc",
+       "license-name": "GPL v2",
+       "type": "specialpage",
+       "AutoloadClasses": {
+               "PreferencesList": "PreferencesList.class.php",
+               "PreferencesListHooks": "PreferencesList.hooks.php",
+               "SpecialPreferencesList": "specials/SpecialPreferencesList.php",
+               "PreferencesListUtils": "PreferencesListUtils.php",
+               "PreferencesListPreferences": "PreferencesListPreferences.php"
+       },
+       "ExtensionMessagesFiles": {
+               "PreferencesListAlias": "PreferencesList.i18n.alias.php"
+       },
+       "MessagesDirs": {
+               "PreferencesList": [
+                       "i18n"
+               ]
+       },
+       "SpecialPages": {
+               "PreferencesList": "SpecialPreferencesList"
+       },      
+       "AvailableRights": [
+               "preferenceslist"
+       ],
+       "GroupPermissions": {
+               "sysop": {
+                       "preferenceslist": true
+               }
+       },
+       "manifest_version": 1
+}
diff --git a/i18n/en.json b/i18n/en.json
new file mode 100755
index 0000000..3f40888
--- /dev/null
+++ b/i18n/en.json
@@ -0,0 +1,15 @@
+{
+       "@metadata": {
+               "authors": [
+                       "tosfos"
+               ]
+       },
+       "preferenceslist-desc": "Generates a list of all user settings for a 
particular preference",
+       "preferenceslist-i18n-welcome": "Welcome to the localization file of 
the PreferencesList extension.",
+       "preferenceslist-preferenceslist": "Preferences List",
+       "preferenceslist-preferenceslist-intro": "Below is a list of 
Preferences. Choose one or more to see a list of all the users with their 
preference.",
+       "preferenceslist": "Preferences list",
+       "action-preferenceslist": "list all users' preferences",
+       "preferenceslist-csv": "Download a CSV",
+       "preferenceslist-nofields": "No fields were selected."
+}
diff --git a/i18n/qqq.json b/i18n/qqq.json
new file mode 100755
index 0000000..519aac4
--- /dev/null
+++ b/i18n/qqq.json
@@ -0,0 +1,15 @@
+{
+       "@metadata": {
+               "authors": [
+                       "tosfos"
+               ]
+       },
+       "preferenceslist-desc": 
"{{desc|name=PreferencesList|url=https://www.mediawiki.org/wiki/Extension:PreferencesList
 }}",
+       "preferenceslist-i18n-welcome": "Used to greet the user when reading 
the i18n/??.json file.",
+       "preferenceslist-preferenceslist": "Page title of the PreferencesList 
special page.",
+       "preferenceslist-preferenceslist-intro": "Text displayed as an 
intorduction on the PreferencesList SpecialPage.",
+       "preferenceslist": "Text of the link to the PreferencesList special 
page on SpecialPages.",
+       "action-preferenceslist": "Description of user privilege",
+       "preferenceslist-csv": "Checkbox label on bottom of the PreferencesList 
SpecialPage",
+       "preferenceslist-nofields": "Message shown to users who submit the form 
with no selected fields."
+}
diff --git a/nbproject/project.properties b/nbproject/project.properties
new file mode 100644
index 0000000..911a7b8
--- /dev/null
+++ b/nbproject/project.properties
@@ -0,0 +1,7 @@
+include.path=${php.global.include.path}
+php.version=PHP_70
+source.encoding=UTF-8
+src.dir=.
+tags.asp=false
+tags.short=false
+web.root=.
diff --git a/nbproject/project.xml b/nbproject/project.xml
new file mode 100644
index 0000000..1d8a0b2
--- /dev/null
+++ b/nbproject/project.xml
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://www.netbeans.org/ns/project/1";>
+    <type>org.netbeans.modules.php.project</type>
+    <configuration>
+        <data xmlns="http://www.netbeans.org/ns/php-project/1";>
+            <name>preferences-list</name>
+        </data>
+    </configuration>
+</project>
diff --git a/package.json b/package.json
new file mode 100755
index 0000000..d6d0f28
--- /dev/null
+++ b/package.json
@@ -0,0 +1,14 @@
+{
+  "private": true,
+  "scripts": {
+    "test": "grunt test"
+  },
+  "devDependencies": {
+    "grunt": "0.4.5",
+    "grunt-cli": "0.1.13",
+    "grunt-contrib-jshint": "0.11.3",
+    "grunt-banana-checker": "0.4.0",
+    "grunt-jscs": "2.5.0",
+    "grunt-jsonlint": "1.0.7"
+  }
+}
diff --git a/phpcs.xml b/phpcs.xml
new file mode 100755
index 0000000..d81a292
--- /dev/null
+++ b/phpcs.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0"?>
+<ruleset>
+       <rule ref="vendor/mediawiki/mediawiki-codesniffer/MediaWiki"/>
+       <file>.</file>
+       <arg name="extensions" value="php,php5,inc"/>
+       <arg name="encoding" value="utf8"/>
+       <exclude-pattern>vendor</exclude-pattern>
+</ruleset>
diff --git a/specials/SpecialPreferencesList.php 
b/specials/SpecialPreferencesList.php
new file mode 100755
index 0000000..fdb7097
--- /dev/null
+++ b/specials/SpecialPreferencesList.php
@@ -0,0 +1,160 @@
+<?php
+/*
+ * Copyright (C) 2017 Ike Hecht <[email protected]>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+
+/**
+ * PreferencesList SpecialPage for PreferencesList extension
+ *
+ * @file
+ * @ingroup Extensions
+ */
+class SpecialPreferencesList extends SpecialPage {
+       /** @var string */
+       protected $subpage;
+
+       /** @var FormOptions */
+       protected $options;
+
+       /** @var array Form Field descriptors */
+       protected $allPreferences;
+
+       /**
+        * Result message to be displayed to the user
+        *
+        * @var string
+        */
+       protected $resultMessage;
+
+       /**
+        * The PreferencesList object
+        *
+        * @var PreferencesList
+        */
+       protected $preferencesList;
+
+       public function __construct() {
+               parent::__construct( 'PreferencesList', 'preferenceslist' );
+       }
+
+       /**
+        * Show the page to the user
+        *
+        * @param string $subpage The subpage string argument (if any).
+        *  [[Special:PreferencesList/subpage]].
+        */
+       public function execute( $subpage ) {
+               parent::execute( $subpage );
+               $this->subpage = $subpage;
+
+               $out = $this->getOutput();
+
+               $out->setPageTitle( $this->msg( 
'preferenceslist-preferenceslist' ) );
+               // Use the current user's info to figure out which fields are 
usually shown on the
+               // Special:Preferences page
+               $this->allPreferences = Preferences::getPreferences( 
$this->getUser(), $this->getContext() );
+
+               $this->preferencesList = new PreferencesList( 
$this->getContext(), $this->allPreferences );
+               $formFields = $this->preferencesList->getFormFields( 
$this->getOptions() );
+
+               $htmlForm = new HTMLForm( $formFields, $this->getContext(), 
'prefs' );
+               $htmlForm->addHiddenField( 'submitted', true );
+               $htmlForm->setSubmitCallback( [ $this, 'tryUISubmit' ] );
+               $htmlForm->setMethod( 'get' );
+
+               //  Is there a better way to do this?
+               if ( !$this->getRequest()->getVal( 'submitted' ) ) {
+                       $out->addWikiMsg( 
'preferenceslist-preferenceslist-intro' );
+                       $htmlForm->displayForm( '' );
+               } else {
+                       $htmlForm->loadData();
+                       $htmlForm->trySubmit();
+                       $out->addHTML( $this->resultMessage );
+                       $out->addReturnTo( SpecialPage::getTitleFor( 
'PreferencesList' ) );
+               }
+       }
+
+       /**
+        * Do Submit
+        *
+        * @param array $formData
+        * @param HTMLForm $form
+        * @return boolean
+        */
+       public function tryUISubmit( $formData, HTMLForm $form ) {
+               // Special handling for the CSV field, which is not a preference
+               $showCSV = $formData['csv'];
+               unset( $formData['csv'] );
+
+               $filteredFormData = array_filter( $formData ); // Remove false 
values
+               $preferencesToShow = array_keys( $filteredFormData );
+
+               if ( empty( $preferencesToShow ) ) {
+                       $this->resultMessage = $this->msg( 
'preferenceslist-nofields' );
+                       return false;
+               }
+
+               if ( $showCSV ) {
+                       $this->getOutput()->disable();
+                       $this->preferencesList->getResults(
+                               $preferencesToShow, PreferencesList::CSV, 
$form->getContext() );
+                       return true;
+               } else {
+                       $this->resultMessage = 
$this->preferencesList->getResults( $preferencesToShow,
+                               PreferencesList::TABLE, $form->getContext() );
+                       return true;
+               }
+
+               // We should never get here.
+               return false;
+       }
+
+       protected function getGroupName() {
+               return 'users';
+       }
+
+       /**
+        * Get the FormOptions object
+        *
+        * @return FormOptions
+        */
+       protected function getOptions() {
+               if ( $this->options === null ) {
+                       $this->options = $this->setup();
+               }
+
+               return $this->options;
+       }
+
+       /**
+        * Set up the FormOptions object
+        *
+        * @return FormOptions
+        */
+       protected function setup() {
+               $opts = new FormOptions();
+               foreach ( $this->allPreferences as $key => $params ) {
+                       if ( isset( $params['type'] ) && $params['type'] === 
'api' ) {
+                               continue;
+                       }
+                       $opts->add( $key, false );
+               }
+               $opts->add( 'csv', false );
+
+               return $opts;
+       }
+}

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

Gerrit-MessageType: newchange
Gerrit-Change-Id: Ibd6b185e30aa769b66f0649886e732e2cef651de
Gerrit-PatchSet: 1
Gerrit-Project: mediawiki/extensions/PreferencesList
Gerrit-Branch: master
Gerrit-Owner: tosfos <[email protected]>

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

Reply via email to