r86105 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r86104‎ | r86105 | r86106 >
Date:06:54, 15 April 2011
Author:nad
Status:resolved (Comments)
Tags:
Comment:
Useful extension by Milan allowing files to be attached to pages
Modified paths:
  • /trunk/extensions/FileAttach (added) (history)
  • /trunk/extensions/FileAttach/FileAttach.i18n.php (added) (history)
  • /trunk/extensions/FileAttach/FileAttach.php (added) (history)

Diff [purge]

Index: trunk/extensions/FileAttach/FileAttach.i18n.php
@@ -0,0 +1,20 @@
 2+<?php
 3+/**
 4+ * Internationalisation for FileAttach extension
 5+ *
 6+ * @author Milan Holzapfel
 7+ * @file
 8+ * @ingroup Extensions
 9+ */
 10+
 11+$messages = array();
 12+
 13+/** English
 14+ * @author Milan Holzapfel
 15+ */
 16+$messages['en'] = array(
 17+ 'fileattach-attachments' => 'File attachments',
 18+ 'fileattach-attachfile' => 'Attach file',
 19+ 'fileattach-uploadheading' => 'Attach file to $1',
 20+ 'fileattach-editcomment' => 'File [[File:$1|$1]] attached',
 21+);
Index: trunk/extensions/FileAttach/FileAttach.php
@@ -0,0 +1,164 @@
 2+<?php
 3+/**
 4+ * FileAttach extension - Allows files to be uploaded to the current article
 5+ *
 6+ * @package MediaWiki
 7+ * @subpackage Extensions
 8+ * @author Milan Holzapfel
 9+ * @licence GNU General Public Licence 2.0 or later
 10+ *
 11+ */
 12+if ( !defined( 'MEDIAWIKI' ) ) die( 'Not an entry point.' );
 13+define( 'FILEATTCH_VERSION', '1.0.0, 2010-04-14' );
 14+
 15+$wgAttachmentHeading = 'Attachments';
 16+
 17+$dir = dirname( __FILE__ );
 18+$wgExtensionMessagesFiles['FileAttach'] = "$dir/FileAttach.i18n.php";
 19+$wgExtensionFunctions[] = 'wfSetupFileAttach';
 20+$wgExtensionCredits['other'][] = array(
 21+ 'name' => 'FileAttach',
 22+ 'author' => '[http://www.mediawiki.org/wiki/User:Milan Milan Holzapfel]',
 23+ 'description' => 'Adds class attributes to links based on their category',
 24+ 'url' => 'http://www.mediawiki.org/wiki/FileAttach',
 25+ 'version' => FILEATTCH_VERSION
 26+);
 27+
 28+class FileAttach {
 29+
 30+ var $uploadForm = false;
 31+ var $attachto = false;
 32+ var $wgOut = false;
 33+
 34+ function __construct() {
 35+ global $wgHooks;
 36+ $wgHooks['BeforePageDisplay'][] = $this;
 37+ $wgHooks['UploadForm:initial'][] = array( $this, 'onUploadFormInitial' );
 38+ $wgHooks['UploadForm:BeforeProcessing'][] = array( $this, 'onUploadFormBeforeProcessing' );
 39+ $wgHooks['SkinTemplateTabs'][] = $this;
 40+ $wgHooks['SkinTemplateNavigation'][] = $this;
 41+ }
 42+
 43+ /*
 44+ * Modify the upload form and attachment heading
 45+ */
 46+ function onBeforePageDisplay( &$out, &$skin ) {
 47+ global $wgParser, $wgAttachmentHeading;
 48+
 49+ # If the last section in the article is level 2 and "Attachments" then convert to file icons
 50+ $sections = $wgParser->mOutput->mSections;
 51+ if( is_array( $sections ) && count( $sections ) > 0 ) {
 52+ $last = $sections[count( $sections ) - 1];
 53+ if( $last['level'] == 2 && $last['anchor'] == $wgAttachmentHeading ) {
 54+ preg_match( "|<h2>.+?$wgAttachmentHeading.+?</h2>\s*<ul>(.+?)</ul>|s", $out->mBodytext, $files );
 55+ preg_match_all( "|<li>\s*<a.+?>(.+?)</a>\s*</li>|", $files[1], $files );
 56+ $html = "\n\n<!-- files attachments rendered by Extension:FileAttach -->\n<div class=\"file-attachments\" style=\"width:85%\">\n";
 57+ foreach( $files[1] as $file ) {
 58+ $title = Title::newFromText( $file, NS_FILE );
 59+ $name = $title->getText();
 60+ $alt = "title=\"$name\"";
 61+ if( strlen( $name ) > 15 ) $name = preg_replace( "|^(............).+(\.\w+$)|", "$1...$2", $name );
 62+ $icon = $this->getIcon( $file );
 63+ $url = wfFindFile( $title )->getURL();
 64+ $img = "<a $alt href=\"$url\"><img style=\"padding-bottom:30px\" src=\"$icon\" width=\"80px\" height=\"80px\" /></a>";
 65+ $text = "<a $alt href=\"$url\" style=\"color:black;font-size:10px;position:relative;left:-67px;top:30px;\">$name</a>";
 66+ $html .= "\t<span class=\"file-attachment\">$img$text</span>\n";
 67+ }
 68+ $html .= "</div>\n";
 69+ $out->mBodytext = preg_replace(
 70+ "|^(.+)<h2>.+?$wgAttachmentHeading.+?</h2>\s*<ul>(.+?)</ul>|s",
 71+ "$1<h2>" . wfMsg( 'fileattach-attachments' ) . "</h2>$html",
 72+ $out->mBodytext
 73+ );
 74+ }
 75+ }
 76+
 77+ # Modify the upload form
 78+ if( $this->uploadForm ) {
 79+ global $wgRequest;
 80+ if( $attachto = $wgRequest->getText( 'attachto' ) ) {
 81+ $out->mPagetitle = wfMsg( 'fileattach-uploadheading', $attachto );
 82+ $out->mBodytext = str_replace( "</form>", "<input type=\"hidden\" name=\"attachto\" value=\"$attachto\" /></form>", $out->mBodytext );
 83+ }
 84+ }
 85+
 86+ return true;
 87+ }
 88+
 89+ /*
 90+ * Note if this is the upload form so that we can modify it before page display
 91+ */
 92+ function onUploadFormInitial( $form ) {
 93+ $this->uploadForm = true;
 94+ return true;
 95+ }
 96+
 97+ /*
 98+ * Check if the upload should attach to an article
 99+ */
 100+ function onUploadFormBeforeProcessing( $form ) {
 101+ global $wgRequest, $wgAttachmentHeading, $wgHooks;
 102+ if( $attachto = $wgRequest->getText( 'attachto', '' ) ) {
 103+ $filename = $wgRequest->getText( 'wpDestFile' );
 104+ $title = Title::newFromText( $attachto );
 105+ $this->attachto = $article = new Article( $title );
 106+ $text = preg_replace( "|(\s+==\s*$wgAttachmentHeading\s*==)\s+|s", "$1\n*[[:File:$filename]]\n", $article->getContent(), 1, $count );
 107+ if( $count == 0 ) $text .= "\n\n== $wgAttachmentHeading ==\n*[[:File:$filename]]\n";
 108+ $article->doEdit( $text, wfMsg( 'fileattach-editcomment', $filename ), EDIT_UPDATE );
 109+ $wgHooks['SpecialUploadComplete'][] = $this;
 110+ }
 111+ return true;
 112+ }
 113+
 114+ /*
 115+ * Change the redirection after upload to the page the file attached to
 116+ * - see line 435 of SpecialUpload.php
 117+ */
 118+ function onSpecialUploadComplete( $upload ) {
 119+ global $wgOut;
 120+ $this->wgOut = $wgOut;
 121+ $wgOut = new FileAttachDummyOutput;
 122+ return true;
 123+ }
 124+
 125+ /*
 126+ * Return an icon path from passed filename
 127+ */
 128+ function getIcon( $filename ) {
 129+ global $wgStylePath, $wgStyleDirectory;
 130+ $ext = strtolower( preg_match( "|\.(\w+)$|", $filename, $ext ) ? "-$ext[1]" : "" );
 131+ $path = "common/images/icons/fileicon";
 132+ $icon = file_exists( "$wgStyleDirectory/$path$ext.png" ) ? "$wgStylePath/$path$ext.png" : "$wgStylePath/$path.png";
 133+ return $icon;
 134+ }
 135+
 136+ function onSkinTemplateTabs( $skin, &$actions ) {
 137+ global $wgTitle;
 138+ $attachto = $wgTitle->getPrefixedText();
 139+ $url = Title::newFromText( 'Upload', NS_SPECIAL )->getLocalURL( array( 'attachto' => $attachto ) );
 140+ $actions['attach'] = array( 'text' => wfMsg( 'fileattach-attachfile' ), 'class' => false, 'href' => $url );
 141+ return true;
 142+ }
 143+
 144+ function onSkinTemplateNavigation( $skin, &$actions ) {
 145+ global $wgTitle;
 146+ $attachto = $wgTitle->getPrefixedText();
 147+ $url = Title::newFromText( 'Upload', NS_SPECIAL )->getLocalURL( array( 'attachto' => $attachto ) );
 148+ $actions['views']['attach'] = array( 'text' => wfMsg( 'fileattach-attachfile' ), 'class' => false, 'href' => $url );
 149+ return true;
 150+ }
 151+
 152+}
 153+
 154+class FileAttachDummyOutput {
 155+ function redirect( $url ) {
 156+ global $wgFileAttach, $wgOut;
 157+ $wgOut = $wgFileAttach->wgOut;
 158+ $wgOut->redirect( $wgFileAttach->attachto->getTitle()->getFullURL() );
 159+ }
 160+}
 161+
 162+function wfSetupFileAttach() {
 163+ global $wgFileAttach;
 164+ $wgFileAttach = new FileAttach();
 165+}

Follow-up revisions

RevisionCommit summaryAuthorDate
r86114Followup r86105, svn:eol-style nativereedy11:24, 15 April 2011
r96613Fix XSS pointed out in r86105demon20:17, 8 September 2011

Comments

#Comment by P858snake (talk | contribs)   09:04, 15 April 2011

FileAttach.php:

+	'url'         => '[http://www.mediawiki.org/wiki/FileAttach', http://www.mediawiki.org/wiki/FileAttach',]

Ideally should be 'http://www.mediawiki.org/wiki/Extension:FileAttach', Yes we can do redirects to it in the main namespace but that is just messy.

Also the page should be created on wiki (which I might do in a moment).

#Comment by P858snake (talk | contribs)   09:06, 15 April 2011
+	'description' => 'Adds class attributes to links based on their category',

Also seems to be wrong.

#Comment by Reedy (talk | contribs)   11:25, 15 April 2011
+	function __construct() {
+		global $wgHooks;
+		$wgHooks['BeforePageDisplay'][] = $this;
+		$wgHooks['UploadForm:initial'][] = array( $this, 'onUploadFormInitial' );
+		$wgHooks['UploadForm:BeforeProcessing'][] = array( $this, 'onUploadFormBeforeProcessing' );
+		$wgHooks['SkinTemplateTabs'][] = $this;
+		$wgHooks['SkinTemplateNavigation'][] = $this;
+	}

Shouldn't all of those be arrays, rather than just passing a class reference and no target method?

#Comment by Nikerabbit (talk | contribs)   13:47, 15 April 2011

It works that way too. It will call $that->onHookName(). But more importantly those should be registered on the main level and use static methods.

+if( $attachto = $wgRequest->getText( 'attachto' ) ) {
+	$out->mBodytext = str_replace( "</form>", "<input type=\"hidden\" name=\"attachto\" value=\"$attachto\" /></form>", $out->mBodytext );

Somebody forgot the escaping?

Title::newFromText( 'Upload', NS_SPECIAL )

Should use SpecialPage::getTitleFor( 'Upload' ) or similar.

#Comment by G.Hagedorn (talk | contribs)   21:50, 27 November 2011

Please start documenting this extension. The documentation ( http://www.mediawiki.org/wiki/Extension:FileAttach ) points to here.

I tried the extension under 1.19svn, and it adds an "attach" tab at the top, pointing towards the standard upload action. However, no files where in the end "attached" to the page itself. Without documentation, I have no clue wether this is by design or a bug.

Status & tagging log