jenkins-bot has submitted this change and it was merged. (
https://gerrit.wikimedia.org/r/365197 )
Change subject: Resurrect this extension
......................................................................
Resurrect this extension
This is a complete rewrite. As per task, the special page does nothing for now.
Bug: T170354
Change-Id: I846cc5265d1dcb8ed7214177e3a6121c96df0353
---
A .eslintrc.json
M .gitignore
A ArticleCreationWorkflow.alias.php
D ArticleCreationWorkflow.php
A COPYING
A Gruntfile.js
A composer.json
A extension.json
A i18n/en.json
A i18n/qqq.json
A includes/Hooks.php
A includes/SpecialCreatePage.php
A includes/Workflow.php
A jsduck.json
A package.json
A phpcs.xml
A tests/phan/config.php
A tests/phan/issues/.gitkeep
A tests/phan/stubs/.gitkeep
A tests/phpunit/WorkflowTest.php
20 files changed, 548 insertions(+), 7 deletions(-)
Approvals:
jenkins-bot: Verified
Kaldari: Looks good to me, approved
diff --git a/.eslintrc.json b/.eslintrc.json
new file mode 100644
index 0000000..488ab05
--- /dev/null
+++ b/.eslintrc.json
@@ -0,0 +1,15 @@
+{
+ "extends": "wikimedia",
+ "env": {
+ "browser": true,
+ "jquery": true,
+ "qunit": true
+ },
+ "globals": {
+ "OO": false,
+ "mediaWiki": false
+ },
+ "rules": {
+ "dot-notation": [ "error", { "allowKeywords": true } ]
+ }
+}
diff --git a/.gitignore b/.gitignore
index 98b092a..98da5c0 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,4 +1,7 @@
-.svn
+node_modules
+vendor
+*.log
*~
*.kate-swp
.*.swp
+composer.lock
diff --git a/ArticleCreationWorkflow.alias.php
b/ArticleCreationWorkflow.alias.php
new file mode 100644
index 0000000..1abf9b5
--- /dev/null
+++ b/ArticleCreationWorkflow.alias.php
@@ -0,0 +1,15 @@
+<?php
+/**
+ * Aliases for special pages
+ *
+ * @file
+ * @ingroup Extensions
+ */
+// @codingStandardsIgnoreFile
+
+$specialPageAliases = array();
+
+/** English (English) */
+$specialPageAliases['en'] = array(
+ 'CreatePage' => array( 'CreatePage' ),
+);
diff --git a/ArticleCreationWorkflow.php b/ArticleCreationWorkflow.php
deleted file mode 100644
index c79b991..0000000
--- a/ArticleCreationWorkflow.php
+++ /dev/null
@@ -1,6 +0,0 @@
-<?php
-/**
- * MediaWiki ArticleCreation Extension
- * See https://www.mediawiki.org/wiki/Extension:ArticleCreationWorkflow
- * @Note This extension is archived. Do not use.
- */
diff --git a/COPYING b/COPYING
new file mode 100644
index 0000000..7bec2e3
--- /dev/null
+++ b/COPYING
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) 2017 Wikimedia contributors
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
diff --git a/Gruntfile.js b/Gruntfile.js
new file mode 100644
index 0000000..e0a034e
--- /dev/null
+++ b/Gruntfile.js
@@ -0,0 +1,52 @@
+/* eslint-env node */
+module.exports = function ( grunt ) {
+ var conf = grunt.file.readJSON( 'extension.json' );
+
+ grunt.loadNpmTasks( 'grunt-banana-checker' );
+ grunt.loadNpmTasks( 'grunt-contrib-watch' );
+ grunt.loadNpmTasks( 'grunt-eslint' );
+ grunt.loadNpmTasks( 'grunt-jsonlint' );
+ grunt.loadNpmTasks( 'grunt-stylelint' );
+
+ grunt.initConfig( {
+ eslint: {
+ src: [
+ '**/*.js',
+ '!node_modules/**',
+ '!vendor/**',
+ '!tests/externals/**',
+ '!docs/**'
+ ]
+ },
+ // Lint – Styling
+ stylelint: {
+ options: {
+ syntax: 'less'
+ },
+ all: [
+ 'modules/**/*.css',
+ 'modules/**/*.less'
+ ]
+ },
+ banana: conf.MessagesDirs,
+ watch: {
+ files: [
+ '.{stylelintrc,eslintrc.json}',
+ '<%= eslint.all %>',
+ '<%= stylelint.all %>'
+ ],
+ tasks: 'test'
+ },
+ jsonlint: {
+ all: [
+ '**/*.json',
+ '!node_modules/**',
+ '!docs/**'
+ ]
+ }
+ } );
+
+ grunt.registerTask( 'lint', [ 'eslint', 'stylelint', 'jsonlint',
'banana' ] );
+ grunt.registerTask( 'test', 'lint' );
+ grunt.registerTask( 'default', 'test' );
+};
diff --git a/composer.json b/composer.json
new file mode 100644
index 0000000..8763303
--- /dev/null
+++ b/composer.json
@@ -0,0 +1,21 @@
+{
+ "name" : "mediawiki/acw",
+ "type" : "mediawiki-extension",
+ "description": "MediaWiki extension ArtcleCreationWorkflow",
+ "license" : "MIT",
+ "minimum-stability": "dev",
+ "require" : {
+ },
+ "require-dev": {
+ "jakub-onderka/php-parallel-lint": "0.9.2",
+ "jakub-onderka/php-console-highlighter": "0.3.2",
+ "mediawiki/mediawiki-codesniffer": "0.10.1"
+ },
+ "scripts": {
+ "fix": "phpcbf",
+ "test": [
+ "parallel-lint . --exclude vendor",
+ "phpcs -p -s"
+ ]
+ }
+}
diff --git a/extension.json b/extension.json
new file mode 100644
index 0000000..a91621e
--- /dev/null
+++ b/extension.json
@@ -0,0 +1,37 @@
+{
+ "manifest_version": 2,
+ "name": "ArticleCreationWorkflow",
+ "type": "other",
+ "author": [ "Max Semenik" ],
+ "url":
"https://www.mediawiki.org/wiki/Extension:ArticleCreationWorkflow",
+ "descriptionmsg": "acw-desc",
+ "license-name": "MIT",
+ "requires": {
+ "MediaWiki": ">= 1.30.0-alpha"
+ },
+ "SpecialPages": {
+ "CreatePage": "ArticleCreationWorkflow\\SpecialCreatePage"
+ },
+ "Hooks": {
+ "AlternateEdit":
"ArticleCreationWorkflow\\Hooks::onAlternateEdit"
+ },
+ "AutoloadClasses": {
+ "ArticleCreationWorkflow\\Hooks": "includes/Hooks.php",
+ "ArticleCreationWorkflow\\SpecialCreatePage":
"includes/SpecialCreatePage.php",
+ "ArticleCreationWorkflow\\Workflow": "includes/Workflow.php"
+ },
+ "MessagesDirs": {
+ "ArticleCreationWorkflow": [
+ "i18n"
+ ]
+ },
+ "ExtensionMessagesFiles": {
+ "ArticleCreationWorkflowAliases":
"ArticleCreationWorkflow.alias.php"
+ },
+ "config": {
+ "ArticleCreationWorkflows": {
+ "description": "Describes conditions when new page
creation should be intercepted. See doc/config.txt for details.",
+ "value": []
+ }
+ }
+}
diff --git a/i18n/en.json b/i18n/en.json
new file mode 100644
index 0000000..19e030c
--- /dev/null
+++ b/i18n/en.json
@@ -0,0 +1,3 @@
+{
+ "acw-desc": "Customizes new page creation experience for new users"
+}
diff --git a/i18n/qqq.json b/i18n/qqq.json
new file mode 100644
index 0000000..dd5c782
--- /dev/null
+++ b/i18n/qqq.json
@@ -0,0 +1,3 @@
+{
+ "acw-desc": "{{desc}}"
+}
diff --git a/includes/Hooks.php b/includes/Hooks.php
new file mode 100644
index 0000000..61230ac
--- /dev/null
+++ b/includes/Hooks.php
@@ -0,0 +1,37 @@
+<?php
+
+namespace ArticleCreationWorkflow;
+
+use EditPage;
+use MediaWiki\MediaWikiServices;
+use SpecialPage;
+
+/**
+ * Hook handlers
+ */
+class Hooks {
+ /**
+ * AlternateEdit hook handler
+ * Redirects users attempting to create pages to Special:CreatePage,
based on configuration
+ *
+ * @see https://www.mediawiki.org/wiki/Manual:Hooks/AlternateEdit
+ *
+ * @param EditPage $editPage
+ * @return bool
+ */
+ public static function onAlternateEdit( EditPage $editPage ) {
+ $config = MediaWikiServices::getInstance()->getMainConfig();
+ $workflow = new Workflow( $config );
+
+ if ( $workflow->shouldInterceptEditPage( $editPage ) ) {
+ $title = $editPage->getTitle();
+ $redirTo = SpecialPage::getTitleFor( 'CreatePage',
$title->getPrefixedText() );
+ $output = $editPage->getContext()->getOutput();
+ $output->redirect( $redirTo->getFullURL() );
+
+ return false;
+ }
+
+ return true;
+ }
+}
diff --git a/includes/SpecialCreatePage.php b/includes/SpecialCreatePage.php
new file mode 100644
index 0000000..9dbdabb
--- /dev/null
+++ b/includes/SpecialCreatePage.php
@@ -0,0 +1,24 @@
+<?php
+
+namespace ArticleCreationWorkflow;
+
+use Exception;
+use UnlistedSpecialPage;
+
+/**
+ * Special:CreatePage code
+ */
+class SpecialCreatePage extends UnlistedSpecialPage {
+ public function __construct() {
+ parent::__construct( 'CreatePage' );
+ }
+
+ /**
+ * @param string|null $subPage
+ */
+ public function execute( $subPage ) {
+ parent::execute( $subPage );
+
+ throw new Exception( 'Not implemented' );
+ }
+}
diff --git a/includes/Workflow.php b/includes/Workflow.php
new file mode 100644
index 0000000..64a5abc
--- /dev/null
+++ b/includes/Workflow.php
@@ -0,0 +1,61 @@
+<?php
+
+namespace ArticleCreationWorkflow;
+
+use Config;
+use EditPage;
+
+/**
+ * Contains this extension's business logic
+ */
+class Workflow {
+ /** @var Config */
+ private $config;
+
+ /**
+ * @param Config $config Configuration to use
+ */
+ public function __construct( Config $config ) {
+ $this->config = $config;
+ }
+
+ /**
+ * Checks whether an attempt to edit a page should be intercepted and
redirected to our workflow
+ *
+ * @param EditPage $editPage
+ * @return bool
+ */
+ public function shouldInterceptEditPage( EditPage $editPage ) {
+ $title = $editPage->getTitle();
+ $user = $editPage->getContext()->getUser();
+ $request = $editPage->getContext()->getRequest();
+
+ $conditions = $this->config->get( 'ArticleCreationWorkflows' );
+
+ // We are only interested in creation
+ if ( $title->exists() ) {
+ return false;
+ }
+
+ foreach ( $conditions as $cond ) {
+ // Filter on namespace
+ if ( !in_array( $title->getNamespace(),
$cond['namespaces'] ) ) {
+ continue;
+ }
+
+ // Filter out users who don't have these rights
+ if ( isset( $cond['redirectRight'] ) &&
!$user->isAllowed( $cond['redirectRight'] ) ) {
+ continue;
+ }
+
+ // Filter out people who have these rights
+ if ( isset( $cond['excludeRight'] ) &&
$user->isAllowed( $cond['excludeRight'] ) ) {
+ continue;
+ }
+
+ return true;
+ }
+
+ return false;
+ }
+}
diff --git a/jsduck.json b/jsduck.json
new file mode 100644
index 0000000..82e333b
--- /dev/null
+++ b/jsduck.json
@@ -0,0 +1,10 @@
+{
+ "--title": "Echo - Documentation",
+ "--processes": "0",
+ "--warnings-exit-nonzero": true,
+ "--output": "docs",
+ "--": [
+ "modules",
+ "tests"
+ ]
+}
diff --git a/package.json b/package.json
new file mode 100644
index 0000000..44f5b07
--- /dev/null
+++ b/package.json
@@ -0,0 +1,19 @@
+{
+ "name": "ArticleCreationWorkflow",
+ "private": true,
+ "description": "Build tools for ACW",
+ "scripts": {
+ "test": "grunt test",
+ "doc": "jsduck"
+ },
+ "devDependencies": {
+ "eslint-config-wikimedia": "0.4.0",
+ "grunt": "1.0.1",
+ "grunt-banana-checker": "0.5.0",
+ "grunt-contrib-watch": "1.0.0",
+ "grunt-eslint": "19.0.0",
+ "grunt-jsonlint": "1.0.8",
+ "grunt-stylelint": "0.7.0",
+ "stylelint-config-wikimedia": "0.4.1"
+ }
+}
diff --git a/phpcs.xml b/phpcs.xml
new file mode 100644
index 0000000..60dda4e
--- /dev/null
+++ b/phpcs.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0"?>
+<ruleset name="MediaWiki">
+ <file>.</file>
+ <rule ref="./vendor/mediawiki/mediawiki-codesniffer/MediaWiki">
+ <exclude name="Generic.Files.LineLength.TooLong" />
+ <exclude name
="MediaWiki.Commenting.FunctionComment.MissingParamComment" />
+ </rule>
+ <arg name="encoding" value="utf8" />
+ <arg name="extensions" value="php,php5,inc" />
+ <arg name="colors" />
+ <exclude-pattern>vendor</exclude-pattern>
+</ruleset>
diff --git a/tests/phan/config.php b/tests/phan/config.php
new file mode 100644
index 0000000..bee8e39
--- /dev/null
+++ b/tests/phan/config.php
@@ -0,0 +1,126 @@
+<?php
+// @codingStandardsIgnore
+
+$directoryList = [];
+$excludeAnalysisDirectoryList = [];
+
+$IP = getenv( 'MW_INSTALL_PATH' );
+if ( $IP === false ) {
+ $IP = realpath( __DIR__ . '/../../../..' );
+}
+
+$ourDirs = [ 'includes', 'tests/phan/stubs' ];
+$otherDirs = [
+ 'includes', 'vendor', 'maintenance', 'languages',
+];
+// Use '.' if possible as the path to this extension to keep output filenames
short
+if ( getcwd() === realpath( __DIR__ . '/../../' ) ) {
+ $ourIP = '.';
+} else {
+ $ourIP = "$IP/extensions/ArticleCreationWorkflow";
+}
+foreach ( $ourDirs as $dir ) {
+ $directoryList[] = "$ourIP/$dir";
+}
+foreach ( $otherDirs as $dir ) {
+ $fullpath = "$IP/$dir";
+ // Some directories, like `vendor`, are optional. The
+ // required deps may have been installed at the top level of mediawiki
+ // or some such
+ if ( is_dir( $fullpath ) ) {
+ $directoryList[] = $fullpath;
+ $excludeAnalysisDirectoryList[] = $fullpath;
+ }
+}
+
+/**
+ * This configuration will be read and overlaid on top of the
+ * default configuration. Command line arguments will be applied
+ * after this file is read.
+ *
+ * @see src/Phan/Config.php
+ * See Config for all configurable options.
+ */
+return [
+ // A list of directories that should be parsed for class and
+ // method information. After excluding the directories
+ // defined in exclude_analysis_directory_list, the remaining
+ // files will be statically analyzed for errors.
+
+ // Thus, both first-party and third-party code being used by
+ // your application should be included in this list.
+ 'directory_list' => $directoryList,
+
+ // A directory list that defines files that will be excluded
+ // from static analysis, but whose class and method
+ // information should be included.
+
+ // Generally, you'll want to include the directories for
+ // third-party code (such as "vendor/") in this list.
+
+ // n.b.: If you'd like to parse but not analyze 3rd
+ // party code, directories containing that code
+ // should be added to the `directory_list` as
+ // to `excluce_analysis_directory_list`.
+ "exclude_analysis_directory_list" => $excludeAnalysisDirectoryList,
+
+ // Backwards Compatibility Checking. This is slow
+ // and expensive, but you should consider running
+ // it before upgrading your version of PHP to a
+ // new version that has backward compatibility
+ // breaks.
+ 'backward_compatibility_checks' => false,
+
+ // Run a quick version of checks that takes less
+ // time at the cost of not running as thorough
+ // an analysis. You should consider setting this
+ // to true only when you wish you had more issues
+ // to fix in your code base.
+ 'quick_mode' => false,
+
+ // If enabled, check all methods that override a
+ // parent method to make sure its signature is
+ // compatible with the parent's. This check
+ // can add quite a bit of time to the analysis.
+ 'analyze_signature_compatibility' => true,
+
+ // The minimum severity level to report on. This can be
+ // set to Issue::SEVERITY_LOW, Issue::SEVERITY_NORMAL or
+ // Issue::SEVERITY_CRITICAL. Setting it to only
+ // critical issues is a good place to start on a big
+ // sloppy mature code base.
+ 'minimum_severity' => 0,
+
+ // If true, missing properties will be created when
+ // they are first seen. If false, we'll report an
+ // error message if there is an attempt to write
+ // to a class property that wasn't explicitly
+ // defined.
+ 'allow_missing_properties' => false,
+
+ // Allow null to be cast as any type and for any
+ // type to be cast to null. Setting this to false
+ // will cut down on false positives.
+ 'null_casts_as_any_type' => false,
+
+ // If enabled, scalars (int, float, bool, string, null)
+ // are treated as if they can cast to each other.
+ 'scalar_implicit_cast' => false,
+
+ // If true, seemingly undeclared variables in the global
+ // scope will be ignored. This is useful for projects
+ // with complicated cross-file globals that you have no
+ // hope of fixing.
+ 'ignore_undeclared_variables_in_global_scope' => false,
+
+ // Add any issue types (such as 'PhanUndeclaredMethod')
+ // to this black-list to inhibit them from being reported.
+ 'suppress_issue_types' => [
+ ],
+
+ // If empty, no filter against issues types will be applied.
+ // If this white-list is non-empty, only issues within the list
+ // will be emitted by Phan.
+ 'whitelist_issue_types' => [
+ ],
+];
diff --git a/tests/phan/issues/.gitkeep b/tests/phan/issues/.gitkeep
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/phan/issues/.gitkeep
diff --git a/tests/phan/stubs/.gitkeep b/tests/phan/stubs/.gitkeep
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/phan/stubs/.gitkeep
diff --git a/tests/phpunit/WorkflowTest.php b/tests/phpunit/WorkflowTest.php
new file mode 100644
index 0000000..6d116aa
--- /dev/null
+++ b/tests/phpunit/WorkflowTest.php
@@ -0,0 +1,88 @@
+<?php
+
+namespace ArticleCreationWorkflow\Tests;
+
+use Article;
+use ArticleCreationWorkflow\Workflow;
+use DerivativeContext;
+use EditPage;
+use FauxRequest;
+use HashConfig;
+use MediaWikiTestCase;
+use RequestContext;
+use Title;
+use User;
+
+/**
+ * @group ArticleCreationWorkflow
+ */
+class WorkflowTest extends MediaWikiTestCase {
+ /**
+ * @dataProvider provideShouldInterceptEditPage
+ *
+ * @param User $user
+ * @param Title $title
+ * @param array $settings
+ * @param string $query
+ * @param bool $expected
+ */
+ public function testShouldInterceptEditPage( User $user, Title $title,
+ $settings, $expected
+ ) {
+ $context = new DerivativeContext( RequestContext::getMain() );
+ $context->setTitle( $title );
+ $context->setUser( $user );
+
+ $article = new Article( $title );
+ $article->setContext( $context );
+ $editPage = new EditPage( $article );
+ $config = new HashConfig( [ 'ArticleCreationWorkflows' =>
$settings ] );
+
+ $workflow = new Workflow( $config );
+
+ self::assertEquals( $expected,
$workflow->shouldInterceptEditPage( $editPage ) );
+ }
+
+ public function provideShouldInterceptEditPage() {
+ $anon = User::newFromId( 0 );
+ $newbie = $this->getMock( 'User' );
+ $newbie->method( 'isAllowed' )
+ ->with( 'autoconfirmed' )
+ ->willReturn( false );
+ $confirmed = $this->getMock( 'User' );
+ $confirmed->method( 'isAllowed' )
+ ->with( 'autoconfirmed' )
+ ->willReturn( true );
+
+ $mainspacePage = Title::newFromText( 'Some nonexistent page' );
+ $miscPage = Title::newFromText( 'Project:Nonexistent too' );
+ $existingPage = $this->getMock( 'Title' );
+ $existingPage->method( 'exists' )
+ ->willReturn( true );
+ $existingPage->method( 'getContentModel' )
+ ->willReturn( CONTENT_MODEL_WIKITEXT );
+
+ $config = [
+ [
+ 'namespaces' => [ NS_MAIN ],
+ 'excludeRight' => 'autoconfirmed',
+ ],
+ ];
+
+ return [
+ // No config, do nothing
+ [ $anon, $mainspacePage, [], false ],
+ // Wrong NS, do nothing
+ [ $anon, $miscPage, $config, false ],
+ // Page exists, do nothing
+ [ $anon, $existingPage, $config, false ],
+ // Confirmed user, do nothing
+ [ $confirmed, $mainspacePage, $config, false ],
+
+ // Anon attempting to create a page, intercept
+ [ $anon, $mainspacePage, $config, true ],
+ // Newbie attempting to create a page, intercept
+ [ $newbie, $mainspacePage, $config, true ],
+ ];
+ }
+}
--
To view, visit https://gerrit.wikimedia.org/r/365197
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings
Gerrit-MessageType: merged
Gerrit-Change-Id: I846cc5265d1dcb8ed7214177e3a6121c96df0353
Gerrit-PatchSet: 9
Gerrit-Project: mediawiki/extensions/ArticleCreationWorkflow
Gerrit-Branch: master
Gerrit-Owner: MaxSem <[email protected]>
Gerrit-Reviewer: Kaldari <[email protected]>
Gerrit-Reviewer: Legoktm <[email protected]>
Gerrit-Reviewer: MaxSem <[email protected]>
Gerrit-Reviewer: MusikAnimal <[email protected]>
Gerrit-Reviewer: Niharika29 <[email protected]>
Gerrit-Reviewer: Samwilson <[email protected]>
Gerrit-Reviewer: Siebrand <[email protected]>
Gerrit-Reviewer: jenkins-bot <>
_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits