Extension:IPaper/code/v0.5/IPaper.php

From MediaWiki.org
Jump to navigation Jump to search
<?php
/**
 * ***** BEGIN LICENSE BLOCK *****
 * This is the Mediawiki IPaper extension.
 * Copyright (c) 2009 Symbian Foundation - http://www.symbian.org/
 *
 * This 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 software 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.
 *
 * ***** END LICENSE BLOCK *****
 * 
 * MediaWiki iPaper extension
 * Parser extension to MediaWiki to react to the "<ipaper>" tag, 
 * rendering a Scribd iPaper document stored on their servers, using their standard flash app.
 * Needs CURL libraries for PHP to be installed (for scribd.php)
 * 
 * @internal	Uses the unofficial Scribd API PHP Library available from their website
 * 				For more information on iPaper, please see www.scribd.com
 *
 * @author		Nick Boultbee (MW user: declension)
 * @license		GNU General Public Licence 2.0 or later
 * @copyright	Symbian Foundation 2009. 
 * @copyright	iPaper and Scribd are (c) Scribd, Inc.
 * @link http://www.mediawiki.org/wiki/Extension:IPaper Documentation
 */
 
if ( !defined( 'MEDIAWIKI' ) ) {
	die("This file is a MediaWiki extension, it is not a valid entry point");
}

$wgExtensionCredits['parserhook'][] = array(
	'name' => 'iPaper',
	'version' => '0.5',
	'author' => 'Nick Boultbee (nick <at> declension <dot> net), for Symbian Foundation',
	'description' => 'Allows the embedding of iPaper files within a wiki using the <tt>&lt;ipaper&gt;</tt> tag',
	'descriptionmsg' => 'ipaper_desc',
	'url' => 'http://www.mediawiki.org/wiki/Extension:IPaper',
);

$wgExtensionMessagesFiles['IPaper'] = dirname( __FILE__ ) . '/IPaper.i18n.php';

// Use the scribd-supplied non-scribd client libraries (which use CURL)
require( 'scribd.php' );

$wgHooks['ParserFirstCallInit'][] = 'wfIPaper';
 
// Some global defaults. One day these might be confgurable from LocalSettings, but there doesn't seem that much point.
$defaults = array(
	'width'		=> '100%',
	'height'	=> '640',
	'title'		=> 'this document',
	'bgcolor'	=> '#FFFFFF',
);

/**
 * Main parser hook setup
 * @param $parser Object: instance of Parser class
 * @return true
 */
function wfIPaper( &$parser ) {
	$parser->setHook( 'ipaper', 'renderIPaperGlobal' );
	wfLoadExtensionMessages( 'IPaper' );
	return true;
}

/**
 * The master hook function. Wrapper for the class-based one. 
 * @see		IPaper::renderIPaper()	
 * @return	string
 */
function renderIPaperGlobal( $input, $argv ) {
	$iPaper = new IPaper();
	return $iPaper->renderIPaper( $input );
}

class IPaper {
	/**
	 * @var		string			The cached results from scribd->getList()
	 * Remember this is only useful on multiple ipaper calls PER page.
	 */
	protected static $_docListCache;

	/**
	 * The parameters used for this rendering of the iPaper document. 
	 * @var		array
	 */
	protected $params;

	/**
	 * Get a list of documents available (for the predefined user)
	 * 
	 * @return	string		The results from getList() call.
	 */
	static function getDocList() {
		global $wgIPaperScribdApiKey, $wgIPaperScribdApiSecret;

		if ( !isset( self::$_docListCache ) ) {
			// Some annoying value-add Exception passing (messages back from Scribd library are a little cryptic)
			try {
				$scribd = new Scribd( $wgIPaperScribdApiKey, $wgIPaperScribdApiSecret );
			} catch ( Exception $e ) {
				throw new Exception( 'ipaper_error_connection', $e->getMessage() );
			}

			// Get the list, if we can
			try {
				self::$_docListCache = $scribd->getList();
			} catch ( Exception $e ) {
				throw new Exception( wfMsg( 'ipaper_error_get_list', $e->getMessage() ) );
			}
		}

		return self::$_docListCache;
	}

	/**
	 * Get a scribd document access key, necessary for embedding a given doc
	 * Also updates some global metadata about this document where found
	 *
	 * @param $id Integer
	 * @param $metadata Array: Optional metadata to update
	 * @return String: The access key "key-xxxx"
	 */
	function getDocKeyById( $id, &$metadata = null ) {

		$docList = self::getDocList();
		foreach ( $docList as $doc ) {
			if ( $doc['doc_id'] == $id ) {
				if ( isset( $metadata ) ) {
					$metadata['title'] = '&ldquo;' . htmlentities( trim( $doc['title'] ) ) . '&rdquo;';
				}
				return $doc['access_key'];
			}
		}
		throw new Exception( wfMsg( 'ipaper_error_get_doc_key', $id ) ); 
	}

	/**
	 * Returns some HTML with embedded Flash from the Scribd site
	 * that displays an iPaper document specified in the parameters
	 * 
	 * @param $input String: The parameter input string (between the tags). Parameters are delimited by pipes ("|")
	 * @return string The HTML to be added to the page
	 */
	function renderIPaper( $input ) {
		global $defaults;

		$output = '';
		$this->params = array();

		try {
			$fields = explode( '|', $input );

			// First param is always ID
			$docId = array_shift( $fields );
			if ( !is_numeric( $docId ) ) {
				throw new Exception( wfMsg( 'ipaper_error_id_nonnumeric' ) );
			}

			foreach ( $fields as $field ) {
				list( $name, $value ) = explode( '=', $field );
				if ( !empty( $value ) ) {
					$this->params[$name] = $value;
				}
			}

			// Translate title TODO: do this in the constructor?
			$defaults['title'] = wfMsg( 'ipaper_this_document' );
			$this->params = array_merge( $defaults, $this->params );

			// Grab the key if not provided
			if ( empty( $this->params['key'] ) ) {
				$key = $this->getDocKeyById( $docId, $this->params );
				$output .= '<span style="color:#777">'
					. '<b><tt>&lt;ipaper&gt;</tt></b>: ' . wfMsg( 'ipaper_use_key', $key )
					. '</span>';
			} else { 
				$key = $this->params['key'];
			}
		} catch ( Exception $e ) {
			return '<div class="ipaper"><p class="error">'
				. '<b><tt>&lt;ipaper&gt;</tt></b>: ' . htmlspecialchars( $e->getMessage(), ENT_COMPAT, 'UTF-8' )
				. '</p></div>';
			// TODO: Intl'ise this debugging maybe.
			wfDebug( __METHOD__ . ": Failed to connect to Scribd due to '{$e->getMessage()}'. Check your \$wgIPaperScribdApiKey and \$wgIPaperScribdApiSecret variables" );
		}
		$title = $this->params['title'];

		// Generate the clickable link
		$viewString = wfMsg( 'ipaper_view_on', $title, 'Scribd.com' );

		$output .=<<<EOM
<div class="ipaper">
	<a title="$viewString" href="http://www.scribd.com/doc/$docId">$viewString</a><br />
	<object 
		codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=9,0,0,0" 
		classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" 
		align="middle" height="{$this->params['height']}" width="{$this->params['width']}" 
	>
		<param name="movie" value="http://d.scribd.com/ScribdViewer.swf?document_id=$docId&access_key=$key&page=1&version=1&viewMode=">
		<param name="quality" value="high">
		<param name="play" value="true">
		<param name="loop" value="true">
		<param name="scale" value="showall">
		<param name="wmode" value="opaque">
		<param name="devicefont" value="false">
		<param name="bgcolor" value="{$this->params['bgcolor']}">
		<param name="menu" value="true">
		<param name="allowFullScreen" value="true">
		<param name="allowScriptAccess" value="always">
		<param name="salign" value="">
		<embed
			type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer"   
			src="http://d.scribd.com/ScribdViewer.swf?document_id=$docId&access_key=$key&page=1&version=1&viewMode=" 
			quality="high" play="true" loop="true" scale="showall" wmode="opaque" devicefont="false"
			menu="true" allowfullscreen="true" allowscriptaccess="always" 
			bgcolor="{$this->params['bgcolor']}" salign="" align="middle" height="{$this->params['height']}" width="{$this->params['width']}" >
		</embed>
	</object>
</div>
EOM;

	     $output = str_replace( "\n", '', $output );
	     return $output;
	}
}