Legoktm has uploaded a new change for review.

  https://gerrit.wikimedia.org/r/315640

Change subject: [WIP] Initial commit
......................................................................

[WIP] Initial commit

Change-Id: Ie0776aecf145eb1c87c2a539ddf3ea8d35a899f5
---
A .gitignore
A README
A composer.json
A extension.json
A includes/ApiRecordLint.php
A includes/Database.php
A includes/Hooks.php
A includes/LintError.php
A linter.sql
9 files changed, 360 insertions(+), 0 deletions(-)


  git pull ssh://gerrit.wikimedia.org:29418/mediawiki/extensions/Linter 
refs/changes/40/315640/1

diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..b4919db
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,7 @@
+.svn
+*~
+*.kate-swp
+.*.swp
+composer.lock
+vendor
+node_modules/
diff --git a/README b/README
new file mode 100644
index 0000000..f0a4b76
--- /dev/null
+++ b/README
@@ -0,0 +1,3 @@
+Extension to help lint wiki pages. Currently designed to take advantage
+of Parsoid's linter, could also be extended to linting JS or CSS in the
+future.
diff --git a/composer.json b/composer.json
new file mode 100644
index 0000000..fdb2f55
--- /dev/null
+++ b/composer.json
@@ -0,0 +1,15 @@
+{
+       "require-dev": {
+               "jakub-onderka/php-parallel-lint": "0.9",
+               "mediawiki/mediawiki-codesniffer": "0.8.0-alpha.1"
+       },
+       "scripts": {
+               "test": [
+                       "parallel-lint . --exclude vendor",
+                       "phpcs -p -s"
+               ],
+               "fix": [
+                       "phpcbf"
+               ]
+       }
+}
diff --git a/extension.json b/extension.json
new file mode 100644
index 0000000..54f8b9c
--- /dev/null
+++ b/extension.json
@@ -0,0 +1,16 @@
+{
+       "name": "Linter",
+       "AutoloadClasses": {
+               "MediaWiki\\Linter\\Hooks": "includes/Hooks.php",
+               "MediaWiki\\Linter\\Database": "includes/Database.php",
+               "MediaWiki\\Linter\\LintError": "includes/LintError.php",
+               "MediaWiki\\Linter\\ApiRecordLint": "includes/ApiRecordLint.php"
+       },
+       "Hooks": {
+               "LoadExtensionSchemaUpdates": 
"MediaWiki\\Linter\\Hooks::onLoadExtensionSchemaUpdates"
+       },
+       "APIModules": {
+               "record-lint": "MediaWiki\\Linter\\ApiRecordLint"
+       },
+       "manifest_version": 1
+}
diff --git a/includes/ApiRecordLint.php b/includes/ApiRecordLint.php
new file mode 100644
index 0000000..a616647
--- /dev/null
+++ b/includes/ApiRecordLint.php
@@ -0,0 +1,70 @@
+<?php
+/**
+ * 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.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @file
+ */
+
+
+namespace MediaWiki\Linter;
+use ApiBase;
+use FormatJson;
+use Title;
+
+class ApiRecordLint extends ApiBase {
+
+       public function execute() {
+               // FIXME Add some IP-based restrictions so only
+               // our Parsoid can submit lint errors
+               $params = $this->extractRequestParams();
+               // Anomie won't like this, but I can't think of a better way 
right now
+               $data = FormatJson::decode( $params['data'], true );
+               if ( !is_array( $data ) ) {
+                       $this->dieUsage( 'Invalid data', 'invalid-data' );
+               }
+
+               $errors = [];
+               $title = Title::newFromText( $params['page'] );
+               if ( !$title || !$title->getArticleID()
+                       || $title->getLatestRevID() != $params['revision']
+               ) {
+                       $this->dieUsage( 'Invalid, non-existent, or outdated 
title', 'invalid-title' );
+               }
+               foreach ( $data as $info ) {
+                       $errors[] = new LintError(
+                               $info['type'],
+                               [ $info['dsr'][0], $info['dsr'][1] ]
+                       );
+               }
+
+               $lintDb = new Database( $title->getArticleID() );
+               $lintDb->setForPage( $errors );
+               $this->getResult()->addValue( $this->getModuleName(), 
'success', true );
+       }
+
+       public function isInternal() {
+               return true;
+       }
+
+       public function getAllowedParams( /* $flags = 0 */ ) {
+               return [
+                       'data' => 'string',
+                       'page' => 'string',
+                       'revision' => 'int',
+               ];
+       }
+
+}
diff --git a/includes/Database.php b/includes/Database.php
new file mode 100644
index 0000000..d9d12cf
--- /dev/null
+++ b/includes/Database.php
@@ -0,0 +1,133 @@
+<?php
+/**
+ * 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.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @file
+ */
+
+
+namespace MediaWiki\Linter;
+
+use DBAccessObjectUtils;
+use IDBAccessObject;
+
+class Database implements IDBAccessObject {
+       /**
+        * @var int
+        */
+       private $pageId;
+
+       /**
+        * @param int $pageId
+        */
+       public function __construct( $pageId ) {
+               $this->pageId = $pageId;
+       }
+
+       /**
+        * @param int $flags
+        * @return LintError[]
+        */
+       public function getForPage( $flags = 0 ) {
+               list( $index, $options ) = DBAccessObjectUtils::getDBOptions( 
$flags );
+               $rows = wfGetDB( $index )->select(
+                       'linter',
+                       [ 'linter_id', 'linter_cat', 'linter_location' ],
+                       [ 'linter_page' => $this->pageId ],
+                       __METHOD__,
+                       $options
+               );
+               $result = [];
+               foreach ( $rows as $row ) {
+                       $error = new LintError(
+                               $row->linter_cat,
+                               array_map( 'intval', explode( '|', 
$row->linter_location ) ),
+                               (int)$row->linter_id
+                       );
+                       $result[$error->id()] = $error;
+               }
+
+               return $result;
+       }
+
+       /**
+        * @param LintError $error
+        * @return array
+        */
+       private function serializeError( LintError $error ) {
+               if ( $error->lintId !== 0 ) {
+                       return [
+                               'linter_id' => $error->lintId,
+                       ];
+               } else {
+                       return [
+                               'linter_page' => $this->pageId,
+                               'linter_cat' => $error->category,
+                               'linter_location' => implode( '|', array_map( 
'strval', $error->location ) ),
+                       ];
+               }
+       }
+
+       /**
+        * @param LintError[] $errors
+        */
+       public function setForPage( $errors ) {
+               $previous = $this->getForPage( self::READ_LATEST );
+               $dbw = wfGetDB( DB_MASTER );
+               if ( !$previous && !$errors ) {
+                       return;
+               } elseif ( !$previous && $errors ) {
+                       $toInsert = $errors;
+                       $toDelete = [];
+               } elseif ( $previous && !$errors ) {
+                       $dbw->delete(
+                               'linter',
+                               [ 'linter_page' => $this->pageId ],
+                               __METHOD__
+                       );
+                       return;
+               } else {
+                       $toInsert = [];
+                       $toDelete = $previous;
+                       // Diff previous and errors
+                       foreach ( $errors as $error ) {
+                               $uniqueId = $error->id();
+                               if ( isset( $previous[$uniqueId] ) ) {
+                                       unset( $toDelete[$uniqueId] );
+                               } else {
+                                       $toInsert[] = $error;
+                               }
+                       }
+               }
+
+               if ( $toDelete ) {
+                       $dbw->delete(
+                               'linter',
+                               array_map( [ $this, 'serializeError'], 
array_values( $toDelete ) ),
+                               __METHOD__
+                       );
+               }
+
+               if ( $toInsert ) {
+                       $dbw->insert(
+                               'linter',
+                               array_map( [ $this, 'serializeError' ], 
$toInsert ),
+                               __METHOD__
+                       );
+               }
+       }
+
+}
diff --git a/includes/Hooks.php b/includes/Hooks.php
new file mode 100644
index 0000000..44e46a1
--- /dev/null
+++ b/includes/Hooks.php
@@ -0,0 +1,32 @@
+<?php
+/**
+ * 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.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @file
+ */
+
+
+namespace MediaWiki\Linter;
+
+use DatabaseUpdater;
+
+class Hooks {
+       public static function onLoadExtensionSchemaUpdates( DatabaseUpdater 
$updater ) {
+               $updater->addExtensionTable(
+                       'linter', dirname( __DIR__ ) . '/linter.sql'
+               );
+       }
+}
diff --git a/includes/LintError.php b/includes/LintError.php
new file mode 100644
index 0000000..9579269
--- /dev/null
+++ b/includes/LintError.php
@@ -0,0 +1,71 @@
+<?php
+/**
+ * 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.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @file
+ */
+
+
+namespace MediaWiki\Linter;
+
+
+class LintError {
+       /**
+        * @var string
+        */
+       public $category;
+
+       /**
+        * @var int[] [ start, end ]
+        */
+       public $location;
+
+       /**
+        * @var int
+        */
+       public $lintId;
+
+       /**
+        * @param string $category
+        * @param int[] $location
+        * @param int $lintId linter_id
+        */
+       public function __construct( $category, $location, $lintId = 0 ) {
+               $this->category = $category;
+               $this->location = $location;
+               $this->lintId = $lintId;
+       }
+
+       /**
+        * @param LintError $other
+        * @return bool
+        */
+       public function equals( LintError $other ) {
+               return $this->category === $other->category
+                       && $this->location === $other->location;
+       }
+
+       /**
+        * Unique id to identify this error, for internal
+        * purposes
+        *
+        * @return string
+        */
+       public function id() {
+               return $this->category . implode( '|', $this->location );
+       }
+
+}
diff --git a/linter.sql b/linter.sql
new file mode 100644
index 0000000..ff07bb0
--- /dev/null
+++ b/linter.sql
@@ -0,0 +1,13 @@
+CREATE TABLE /*_*/linter (
+       -- primary key
+  linter_id int UNSIGNED AUTO_INCREMENT PRIMARY KEY not null,
+       -- page id
+       linter_page int UNSIGNED not null,
+       -- error category
+       linter_cat VARCHAR(30) not null,
+       -- location of error, currently first 2 numbers in DSR
+       linter_location blob NOT NULL
+) /*$wgDBTableOptions*/;
+
+-- Query by page
+CREATE INDEX /*i*/linter_page ON /*_*/linter (linter_page);

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

Gerrit-MessageType: newchange
Gerrit-Change-Id: Ie0776aecf145eb1c87c2a539ddf3ea8d35a899f5
Gerrit-PatchSet: 1
Gerrit-Project: mediawiki/extensions/Linter
Gerrit-Branch: master
Gerrit-Owner: Legoktm <legoktm.wikipe...@gmail.com>

_______________________________________________
MediaWiki-commits mailing list
MediaWiki-commits@lists.wikimedia.org
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits

Reply via email to