r87154 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r87153‎ | r87154 | r87155 >
Date:00:25, 30 April 2011
Author:preilly
Status:deferred (Comments)
Tags:
Comment:
initial import of proof of concept
Modified paths:
  • /trunk/extensions/PatchOutputMobile (added) (history)
  • /trunk/extensions/PatchOutputMobile/PatchOutputMobile.php (added) (history)
  • /trunk/extensions/PatchOutputMobile/views (added) (history)
  • /trunk/extensions/PatchOutputMobile/views/layout (added) (history)
  • /trunk/extensions/PatchOutputMobile/views/layout/_footmenu_default.html.php (added) (history)
  • /trunk/extensions/PatchOutputMobile/views/layout/_search_webkit.html.php (added) (history)
  • /trunk/extensions/PatchOutputMobile/views/layout/application.html.php (added) (history)
  • /trunk/extensions/PatchOutputMobile/views/notices (added) (history)
  • /trunk/extensions/PatchOutputMobile/views/notices/_donate.html.php (added) (history)

Diff [purge]

Index: trunk/extensions/PatchOutputMobile/views/notices/_donate.html.php
@@ -0,0 +1,9 @@
 2+<?php
 3+
 4+$donate_html = <<<EOT
 5+ <div class='mwm-message mwm-notice'>
 6+ Text WIKI to <a href="sms:25383">25383</a> to donate $10.
 7+ <br />
 8+ <a href='http://wikimediafoundation.org/wiki/Mobile_Giving'>Msg & Data Rates May Apply</a>
 9+ </div>
 10+EOT;
Index: trunk/extensions/PatchOutputMobile/views/layout/_footmenu_default.html.php
@@ -0,0 +1,16 @@
 2+<?php
 3+
 4+$footer_html = <<<EOD
 5+ <div id='footer'>
 6+ <div class='nav' id='footmenu'>
 7+ <div class='mwm-notice'>
 8+ <a href="http://en.wikipedia.org/w/mobileRedirect.php?to=">View this page on regular Wikipedia</a>
 9+ <div id="perm">
 10+ <a href="https://www.mediawiki.org/disable/???">Permanently disable mobile site</a>
 11+ </div>
 12+ </div>
 13+ </div>
 14+ <div id='copyright'>Text is available under the <a href='http://en.wikipedia.org/wiki/Wikipedia:Text_of_Creative_Commons_Attribution-ShareAlike_3.0_Unported_License'>Creative Commons Attribution/Share-Alike License</a>; additional terms may apply. See <a href='http://wikimediafoundation.org/wiki/Terms_of_Use'>Terms of Use</a> for details. Wikipedia is a registered trademark of the <a href='http://www.wikimediafoundation.org/'>Wikimedia Foundation, Inc.</a>, a non-profit organization.</div>
 15+ </div>
 16+
 17+EOD;
Index: trunk/extensions/PatchOutputMobile/views/layout/application.html.php
@@ -0,0 +1,33 @@
 2+<?php
 3+$application_html = <<<EOT
 4+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
 5+<html lang='en' xml:lang='en' xmlns='http://www.w3.org/1999/xhtml'>
 6+ <head>
 7+ <title>{$title}</title>
 8+ <meta http-equiv="content-type" content="text/html; charset=utf-8" />
 9+ <link href='http://en.m.wikipedia.org/stylesheets/webkit.css' media='all' rel='Stylesheet' type='text/css' />
 10+ <meta name="ROBOTS" content="NOINDEX, NOFOLLOW" />
 11+ <meta name = "viewport" content = "width=device-width; initial-scale=1.0; maximum-scale=1.0; user-scalable=0;" />
 12+ <link rel="apple-touch-icon" href="http://en.m.wikipedia.org/apple-touch-icon.png" />
 13+ <script type='text/javascript'>
 14+ //<![CDATA[
 15+ var title = "{$title}";
 16+ var server = "http://en.wikipedia.org";
 17+ function shouldCache() {
 18+ return true;
 19+ }
 20+ //]]>
 21+ </script>
 22+ <script type="text/javascript" language="javascript" SRC="http://en.m.wikipedia.org/javascripts/jquery.js"></script>
 23+ <script type="text/javascript" language="javascript" SRC="http://en.m.wikipedia.org/javascripts/application.js"></script>
 24+ </head>
 25+ <body>
 26+ {$search_webkit_html}
 27+ <div class='show' id='content_wrapper'>
 28+ {$donate_html}
 29+ {$content_html}
 30+ </div>
 31+ {$footer_html}
 32+ </body>
 33+</html>
 34+EOT;
Index: trunk/extensions/PatchOutputMobile/views/layout/_search_webkit.html.php
@@ -0,0 +1,41 @@
 2+<?php
 3+/*
 4+$search_webkit_html = <<<EOD
 5+<div id='header'>
 6+ <div id='searchbox'>
 7+ <img alt='W logo' id='logo' src='http://en.m.wikipedia.org/images/w.gif' />
 8+ <form action='/wiki' class='search_bar' method='get'>
 9+ <input id='searchField' name='search' size='27' type='search' value='' />
 10+ <div id='clearButton'></div>
 11+ <button id='goButton' type='submit'></button>
 12+ </form>
 13+ </div>
 14+ <div class='nav' id='nav'>
 15+ <form method="get" action="/"><button type="submit" id="homeButton">Home</button></form>
 16+ <form method="get" action="/wiki/::Random"><button type="submit" id="randomButton">Random</button></form>
 17+ </div>
 18+</div>
 19+EOD;
 20+*/
 21+
 22+$search_field = (!empty($_GET['search'])) ? $_GET['search'] : '';
 23+
 24+$search_webkit_html = <<<EOD
 25+<div id='header'>
 26+ <div id='searchbox'>
 27+ <img alt='W logo' id='logo' src='http://en.m.wikipedia.org/images/w.gif' />
 28+ <form action='/index.php' class='search_bar' method='get'>
 29+ <input type="hidden" value="Special:Search" name="title" />
 30+ <input type="hidden" value="Search" name="fulltext" />
 31+ <input type="hidden" value="0" name="redirs" />
 32+ <input id='searchField' name='search' size='27' type='search' value='{$search_field}' />
 33+ <div id='clearButton'></div>
 34+ <button id='goButton' type='submit'></button>
 35+ </form>
 36+ </div>
 37+ <div class='nav' id='nav'>
 38+ <form method="get" action="/"><button type="submit" id="homeButton">Home</button></form>
 39+ <form method="get" action="/wiki/::Random"><button type="submit" id="randomButton">Random</button></form>
 40+ </div>
 41+</div>
 42+EOD;
Index: trunk/extensions/PatchOutputMobile/PatchOutputMobile.php
@@ -0,0 +1,252 @@
 2+<?php
 3+
 4+# Needs to be called within MediaWiki; not standalone
 5+if ( !defined('MEDIAWIKI') ) {
 6+ echo("This is an extension to the MediaWiki package and cannot be run standalone.\n" );
 7+ die(-1);
 8+}
 9+
 10+# Define the extension; allows us make sure the extension is used correctly
 11+DEFINE( 'PATCHOUTPUTMOBILE', 'PatchOutputMobile' );
 12+
 13+$wgExtensionCredits['other'][] = array(
 14+ 'name' => 'PatchOutputMobile',
 15+ 'version' => ExtPatchOutputMobile::VERSION,
 16+ 'author' => '[http://www.mediawiki.org/wiki/User:Preilly Preilly]',
 17+ 'url' => 'http://www.mediawiki.org/wiki/Extension:PatchOutputMobile',
 18+ 'description' => 'patch html output for mobile'
 19+);
 20+
 21+// default settings
 22+ExtPatchOutputMobile::$mTable = array(
 23+ 'accessed' => 'like viewed and stuff',
 24+ 'information' => 'more stuff about it',
 25+ 'Main Page' => 'First Page Dude');
 26+
 27+$wgExtPatchOutputMobile = new ExtPatchOutputMobile();
 28+
 29+$wgHooks['OutputPageBeforeHTML'][] = array(&$wgExtPatchOutputMobile,
 30+ 'onOutputPageBeforeHTML');
 31+
 32+class ExtPatchOutputMobile {
 33+ const VERSION = '0.2';
 34+
 35+ public static $mTable;
 36+
 37+ private $doc;
 38+
 39+ public $items_to_remove = array("#contentSub", #redirection notice
 40+ "div.messagebox", #cleanup data
 41+ "#siteNotice", #site notice
 42+ "#siteSub", #"From Wikipedia..."
 43+ "#jump-to-nav", #jump-to-nav
 44+ "div.editsection", #edit blocks
 45+ "div.infobox", # Infoboxes in the article
 46+ "table.toc", #table of contents
 47+ "#catlinks", #category links
 48+ "div.stub", #stub warnings
 49+ "table.metadata", #ugly metadata
 50+ "form",
 51+ "div.sister-project",
 52+ "script",
 53+ "div.magnify", #stupid magnify thing
 54+ ".editsection",
 55+ "span.t",
 56+ 'sup[style*="help"]',
 57+ ".portal",
 58+ "#protected-icon",
 59+ ".printfooter",
 60+ ".boilerplate",
 61+ "#id-articulo-destacado",
 62+ "#coordinates",
 63+ "#top",
 64+ ".hiddenStructure",
 65+ ".noprint",
 66+ ".medialist",
 67+ ".mw-search-createlink");
 68+
 69+ public function onOutputPageBeforeHTML(&$out, &$text) {
 70+ ob_start(array(&$this, 'parse'));
 71+ return true;
 72+ }
 73+
 74+ public function javascriptize($s) {
 75+ $s = preg_replace_callback('/<h2(.*)<span class="mw-headline" [^>]*>(.+)<\/span>\w*<\/h2>/', function ($matches) {
 76+ static $headings = 0;
 77+ $show = "Show";
 78+ $hide = "Hide";
 79+ $back_to_top = "Jump Back A Section";
 80+ ++$headings;
 81+ // Back to top link
 82+ $base = "<div class='section_anchors' id='anchor_" . intval($headings - 1) . "'><a href='#section_" . intval($headings - 1) . "' class='back_to_top'>&uarr; {$back_to_top}</a></div>";
 83+ // generate the HTML we are going to inject
 84+ $buttons = "<button class='section_heading show' section_id='{$headings}'>{$show}</button><button class='section_heading hide' section_id='{$headings}'>{$hide}</button>";
 85+ $base .= "<h2 class='section_heading' id='section_{$headings}'{$matches[1]}{$buttons} <span>{$matches[2]}</span></h2><div class='content_block' id='content_{$headings}'>";
 86+
 87+ if ($headings > 1) {
 88+ // Close it up here
 89+ $base = "</div>" . $base;
 90+ }
 91+
 92+ $GLOBALS['headings'] = $headings;
 93+
 94+ return $base;
 95+ }, $s);
 96+
 97+ // if we had any, make sure to close the whole thing!
 98+ if (isset($GLOBALS['headings']) && $GLOBALS['headings'] > 0) {
 99+ $s = str_replace('<div class="visualClear">', '</div><div class="visualClear">', $s);
 100+ }
 101+
 102+ return $s;
 103+ }
 104+
 105+ public function parse($s) {
 106+ // foreach(self::$mTable as $from => $to) {
 107+ // $s =& str_replace( $from, $to, $s );
 108+ // }
 109+
 110+ return $this->DOMParse($s);
 111+ }
 112+
 113+ private function parse_items_to_remove() {
 114+ $item_to_remove_records = array();
 115+
 116+ foreach ($this->items_to_remove as $item_to_remove) {
 117+ $type = '';
 118+ $raw_name = '';
 119+ CSS_detection::detect_id_css_or_tag($item_to_remove, $type, $raw_name);
 120+ $item_to_remove_records[$type][] = $raw_name;
 121+ }
 122+
 123+ return $item_to_remove_records;
 124+ }
 125+
 126+ public function DOMParse($html) {
 127+
 128+ libxml_use_internal_errors(true);
 129+ $this->doc = DOMDocument::loadHTML($html);
 130+ libxml_use_internal_errors(false);
 131+ $this->doc->preserveWhiteSpace = false;
 132+ $this->doc->strictErrorChecking = false;
 133+
 134+ $item_to_remove_records = $this->parse_items_to_remove();
 135+
 136+ //Tags
 137+
 138+ //You can't remove DOMNodes from a DOMNodeList as you're iterating over them
 139+ // in a foreach loop. It will seemingly leave the internal iterator on the foreach out of wack
 140+ // and results will be quite strange. Though, making a queue of items to remove
 141+ // seems to work. For example:
 142+
 143+ $title_node = $this->doc->getElementsByTagName('title');
 144+
 145+ if ($title_node->length > 0) {
 146+ $title = $title_node->item(0)->nodeValue;
 147+ }
 148+
 149+ $domElemsToRemove = array();
 150+ foreach ($item_to_remove_records['TAG'] as $tag_to_remove) {
 151+ $tag_to_remove_nodes = $this->doc->getElementsByTagName($tag_to_remove);
 152+
 153+ foreach($tag_to_remove_nodes as $tag_to_remove_node) {
 154+ if ($tag_to_remove_node) {
 155+ $domElemsToRemove[] = $tag_to_remove_node;
 156+ }
 157+ }
 158+ }
 159+
 160+ foreach($domElemsToRemove as $domElement){
 161+ $domElement->parentNode->removeChild($domElement);
 162+ }
 163+
 164+ //Elements with named Ids
 165+ foreach ($item_to_remove_records['ID'] as $item_to_remove) {
 166+ $item_to_remove_node = $this->doc->getElementById($item_to_remove);
 167+ if ($item_to_remove_node) {
 168+ $removed_item_to_remove = $item_to_remove_node->parentNode->removeChild($item_to_remove_node);
 169+ }
 170+ }
 171+
 172+ // CSS Classes
 173+ $xpath = new DOMXpath($this->doc);
 174+ foreach ($item_to_remove_records['CLASS'] as $class_to_remove) {
 175+
 176+ $elements = $xpath->query('//*[@class="'.$class_to_remove.'"]');
 177+
 178+ foreach($elements as $element) {
 179+ $removed_element = $element->parentNode->removeChild($element);
 180+ }
 181+ }
 182+
 183+ //Tags with CSS Classes
 184+ foreach ($item_to_remove_records['TAG_CLASS'] as $class_to_remove) {
 185+
 186+ $parts = explode(".", $class_to_remove);
 187+
 188+ $elements = $xpath->query('//'.$parts[0].'[@class="'.$parts[1].'"]');
 189+
 190+ foreach($elements as $element) {
 191+ $removed_element = $element->parentNode->removeChild($element);
 192+ }
 193+ }
 194+
 195+ $content = $this->doc->getElementById('content');
 196+
 197+ $content_html = $this->doc->saveXML($content, LIBXML_NOEMPTYTAG);
 198+
 199+ if (empty($title)) {
 200+ $title = 'Wikipedia';
 201+ }
 202+
 203+ require('views/notices/_donate.html.php');
 204+ require('views/layout/_search_webkit.html.php');
 205+ require('views/layout/_footmenu_default.html.php');
 206+ require('views/layout/application.html.php');
 207+
 208+ return (strlen($content_html) > 4000) ? $this->javascriptize($application_html) : $application_html; //$content_html;
 209+ }
 210+}
 211+
 212+class CSS_detection {
 213+
 214+ public static function detect_id_css_or_tag($snippet, &$type, &$raw_name) {
 215+ $output = '';
 216+
 217+ if (strpos($snippet, '.') === 0) {
 218+ $output = 'Class found: ';
 219+ $type = 'CLASS';
 220+ $raw_name = substr($snippet, 1);
 221+ }
 222+
 223+ if (strpos($snippet, '#') === 0) {
 224+ $output = 'ID found: ';
 225+ $type = 'ID';
 226+ $raw_name = substr($snippet, 1);
 227+ }
 228+
 229+ if (strpos($snippet, '.') !== 0 &&
 230+ strpos($snippet, '.') !== false) {
 231+ $output = 'Tag with Class found: ';
 232+ $type = 'TAG_CLASS';
 233+ $raw_name = $snippet;
 234+ }
 235+
 236+ if (strpos($snippet, '.') === false &&
 237+ strpos($snippet, '#') === false &&
 238+ strpos($snippet, '[') === false &&
 239+ strpos($snippet, ']') === false) {
 240+ $output = 'Tag found: ';
 241+ $type = 'TAG';
 242+ $raw_name = $snippet;
 243+ }
 244+
 245+ if (empty($output)) {
 246+ $output = 'Unknown HTML snippet found: ';
 247+ $type = 'UNKNOWN';
 248+ $raw_name = $snippet;
 249+ }
 250+
 251+ return $output;
 252+ }
 253+}
\ No newline at end of file

Comments

#Comment by Reedy (talk | contribs)   00:30, 30 April 2011

Need to fix your Subversion/auto-props

Also, have a look at our Manual:Coding conventions

#Comment by Catrope (talk | contribs)   11:26, 30 April 2011
+		$s = preg_replace_callback('/<h2(.*)<span class="mw-headline" [^>]*>(.+)<\/span>\w*<\/h2>/', function ($matches) {

Closures are a PHP 5.3 feature. MediaWiki currently requires PHP 5.2.3 or higher.

#Comment by MZMcBride (talk | contribs)   18:58, 15 August 2011

This revision introduced a very minor inconsistency in the footer HTML. <div id="perm"> is using quotation marks when the other code in the footer is using apostrophes.

I also have no idea why this revision was marked old. I thought that status was reserved for... old revisions.

Status & tagging log