http://www.mediawiki.org/wiki/Special:Code/MediaWiki/90043
Revision: 90043 Author: werdna Date: 2011-06-14 13:43:05 +0000 (Tue, 14 Jun 2011) Log Message: ----------- First pass at http://www.mediawiki.org/wiki/MoodBar backend. Added Paths: ----------- trunk/extensions/MoodBar/ trunk/extensions/MoodBar/ApiMoodBar.php trunk/extensions/MoodBar/FeedbackItem.php trunk/extensions/MoodBar/Messages.php trunk/extensions/MoodBar/MoodBar.php trunk/extensions/MoodBar/moodbar.sql Added: trunk/extensions/MoodBar/ApiMoodBar.php =================================================================== --- trunk/extensions/MoodBar/ApiMoodBar.php (rev 0) +++ trunk/extensions/MoodBar/ApiMoodBar.php 2011-06-14 13:43:05 UTC (rev 90043) @@ -0,0 +1,83 @@ +<?php + +class ApiMoodBar extends ApiBase { + public function execute() { + $params = $this->extractRequestParams(); + + $params['page'] = Title::newFromText( $params['page'] ); + + // Params are deliberately named the same as the properties, + // just slurp them through. + $item = MBFeedbackItem::create( $params ); + + $item->save(); + + $result = array( 'result' => 'success' ); + $this->getResult()->addValue( null, $this->getModuleName(), + } + + public function needsToken() { + return true; + } + + public function getTokenSalt() { + return ''; + } + + public function getAllowedParams() { + return array( + 'page' => array( + ApiBase::PARAM_REQUIRED => true, + ), + 'type' => array( + ApiBase::PARAM_REQUIRED => true, + ApiBase::PARAM_TYPE => MBFeedbackItem::getValidTypes(), + ), + 'comment' => array( + ApiBase::PARAM_REQUIRED => true, + ), + 'anonymize' => array( + ApiBase::PARAM_TYPE => 'boolean', + ), + 'editmode' => array( + ApiBase::PARAM_TYPE => 'boolean', + ), + 'useragent' => null, + 'system' => null, + 'locale' => null, + 'bucket' => null, + ); + } + + public function mustBePosted() { + return true; + } + + public function isWriteMode() { + return true; + } + + public function getVersion() { + return __CLASS__ . ': $Id: ApiThreadAction.php 88574 2011-05-22 13:31:30Z werdna $'; + } + + public function getPossibleErrors() { + return array_merge( parent::getPossibleErrors(), array( + + ) ); + } + + public function getParamDescription() { + return array( + 'page' => 'The page the feedback is on', + 'type' => 'The type of feedback being provided', + 'comment' => 'The feedback text', + 'anonymize' => 'Whether to hide user information', + 'editmode' => 'Whether or not the feedback context is in edit mode', + 'bucket' => 'The testing bucket, if any', + 'useragent' => 'The User-Agent header of the browser', + 'system' => 'The operating system being used', + 'locale' => 'The locale in use', + ); + } +} Added: trunk/extensions/MoodBar/FeedbackItem.php =================================================================== --- trunk/extensions/MoodBar/FeedbackItem.php (rev 0) +++ trunk/extensions/MoodBar/FeedbackItem.php 2011-06-14 13:43:05 UTC (rev 90043) @@ -0,0 +1,237 @@ +<?php + +/** + * This class represents a single piece of MoodBar feedback. + */ +class MBFeedbackItem { + /** Container for the data **/ + protected $data; + /** Valid data keys **/ + protected $validMembers = array( + // Feedback essentials + 'id', // ID in the database + 'comment', // The feedback itself + 'page', // The page where it was submitted + 'type', + + // Housekeeping + 'timestamp', + 'user', // User object who submitted the feedback + 'anonymize', + + // Statistics + 'useragent', + 'system', + 'locale', + 'editmode', + 'bucket', + ); + + /** Valid values for the 'type' parameter. **/ + protected static $validTypes = array( 'happy', 'sad', 'confused' ); + + /** + * Default constructor. + * Don't use this, use either MBFeedbackItem::newFromRow or MBFeedbackItem::create + */ + protected function __construct() { + $this->data = array_fill_keys( $this->validMembers, null ); + + // Non-nullable boolean fields + $this->setProperty('anonymize', false); + $this->setProperty('editmode', false); + } + + /** + * Factory function to create a new MBFeedbackItem + * @param $info Associative array of values + * Valid keys: type, user, comment, page, flags, timestamp, + * useragent, system, locale, bucket, anonymize + * @return MBFeedback object. + */ + public static function create( $info ) { + $newObject = new self(); + $newObject->initialiseNew( $info ); + return $newObject; + } + + /** + * Initialiser for new MBFeedbackItems + * @param $info Associative array of values + * @see MBFeedbackItem::create + */ + protected function initialiseNew( $info ) { + global $wgUser; + + $template = array( + 'user' => $wgUser, + 'timestamp' => wfTimestampNow(), + ); + + $this->setProperties( $template ); + $this->setProperties( $info ); + } + + /** + * Factory function to load an MBFeedbackItem from a DB row. + * @param $row A row, from DatabaseBase::fetchObject + * @return MBFeedback object. + */ + public static function load( $row ) { + $newObject = new self(); + $newObject->initialiseFromRow( $row ); + return $newObject; + } + + /** + * Initialiser for MBFeedbackItems loaded from the database + * @param $row A row object from DatabaseBase::fetchObject + * @see MBFeedbackItem::load + */ + protected function initialiseFromRow( $row ) { + $properties = array( + 'id' => $row->mbf_id, + 'type' => $row->mbf_type, + 'comment' => $row->mbf_comment, + 'timestamp' => $row->mbf_timestamp, + 'anonymize' => $row->mbf_anonymous, + 'useragent' => $row->mbf_user_agent, + 'system' => $row->mbf_system_type, + 'locale' => $row->mbf_locale, + 'bucket' => $row->mbf_bucket, + 'editmode' => $row->mbf_editing, + ); + + $properties['page'] = Title::makeTitleSafe( $row->mbf_namespace, $row->mbf_title ); + + if ( $row->mbf_user_id > 0 ) { + $properties['user'] = User::newFromId( $row->mbf_user_id ); + } else { + $properties['user'] = User::newFromName( $row->mbf_user_ip ); + } + + $this->setProperties( $properties ); + } + + /** + * Set a group of properties. Throws an exception on invalid property. + * @param $values An associative array of properties to set. + */ + public function setProperties( $values ) { + foreach( $values as $key => $value ) { + if ( ! $this->isValidKey($key) ) { + throw new MWException( "Attempt to set invalid property $key" ); + } + + if ( ! $this->validatePropertyValue($key, $value) ) { + throw new MWException( "Attempt to set invalid value for $key" ); + } + + $this->data[$key] = $value; + } + } + + /** + * Set a group of values. + * @param $key The property to set. + * @param $value The value to give it. + */ + public function setProperty( $key, $value ) { + $this->setProperties( array( $key => $value ) ); + } + + /** + * Get a property. + * @param $key The property to get + * @return The property value. + */ + public function getProperty( $key ) { + if ( ! $this->isValidKey($key) ) { + throw new MWException( "Attempt to get invalid property $key" ); + } + + return $this->data[$key]; + } + + /** + * Check a property key for validity. + * If a property key is valid, it will be prefilled to NULL. + * @param $key The property key to check. + */ + public function isValidKey( $key ) { + return in_array( $key, $this->validMembers ); + } + + /** + * Check if a property value is valid for that property + * @param $key The key of the property to check. + * @param $value The value to check + * @return Boolean + */ + public function validatePropertyValue( $key, $value ) { + if ( $key == 'user' ) { + return $value instanceof User || $value instanceof StubUser; + } elseif ( $key == 'page' ) { + return $value instanceof Title || $value instanceof StubTitle; + } elseif ( $key == 'type' ) { + return in_array( $value, self::$validTypes ); + } + + return true; + } + + /** + * Writes this MBFeedbackItem to the database. + * Throws an exception if this it is already in the database. + * @return The MBFeedbackItem's new ID. + */ + public function save() { + + if ( $this->getProperty('id') != null ) { + throw new MWException( "This ".__CLASS__." is already in the database." ); + } + + $dbw = wfGetDB( DB_MASTER ); + + $row = array( + 'mbf_id' => $dbw->nextSequenceValue( 'moodbar_feedback_mbf_id' ), + 'mbf_type' => $this->getProperty('type'), + 'mbf_comment' => $this->getProperty('comment'), + 'mbf_timestamp' => $dbw->timestamp($this->getProperty('timestamp')), + 'mbf_anonymous' => $this->getProperty('anonymize'), + 'mbf_user_agent' => $this->getProperty('useragent'), + 'mbf_system_type' => $this->getProperty('system'), + 'mbf_locale' => $this->getProperty('locale'), + 'mbf_bucket' => $this->getProperty('bucket'), + 'mbf_editing' => $this->getProperty('editmode'), + ); + + $user = $this->getProperty('user'); + if ( $user->isAnon() ) { + $row['mbf_user_id'] = 0; + $row['mbf_user_ip'] = $user->getName(); + } else { + $row['mbf_user_id'] = $user->getId(); + } + + $page = $this->getProperty('page'); + if ( $page ) { + $row['mbf_namespace'] = $page->getNamespace(); + $row['mbf_title'] = $page->getDBkey(); + } + + $dbw->insert( 'moodbar_feedback', $row, __METHOD__ ); + + $this->setProperty( 'id', $dbw->insertId() ); + + return $this->getProperty('id'); + } + + /** + * Gets the valid types of a feedback item. + */ + public static function getValidTypes() { + return self::$validTypes; + } + +} Added: trunk/extensions/MoodBar/Messages.php =================================================================== --- trunk/extensions/MoodBar/Messages.php (rev 0) +++ trunk/extensions/MoodBar/Messages.php 2011-06-14 13:43:05 UTC (rev 90043) @@ -0,0 +1,5 @@ +<?php + +$messages['en'] = array( + 'moodbar-desc' => 'Allows specified users to send their "mood" back to the site operator.", +); Added: trunk/extensions/MoodBar/MoodBar.php =================================================================== --- trunk/extensions/MoodBar/MoodBar.php (rev 0) +++ trunk/extensions/MoodBar/MoodBar.php 2011-06-14 13:43:05 UTC (rev 90043) @@ -0,0 +1,37 @@ +<?php +/** + * MoodBar extension + * Allows specified users to send their "mood" back to the site operator. + */ + +$wgExtensionCredits['other'][] = array( + 'author' => array( 'Andrew Garrett', 'Timo Tijhof' ), + 'descriptionmsg' => 'moodbar-desc', + 'name' => 'MoodBar', + 'url' => 'http://www.mediawiki.org/wiki/MoodBar', + 'version' => '0.1', + 'path' => __FILE__, +); + +// Object model +$wgAutoloadClasses['MBFeedbackItem'] = dirname(__FILE__).'/FeedbackItem.php'; + +// API +$wgAutoloadClasses['ApiMoodBar'] = dirname(__FILE__).'/ApiMoodBar.php'; +$wgAPIModules['moodbar'] = 'ApiMoodBar'; + +// Internationalisation +$wgExtensionMessagesFiles = dirname(__FILE__).'/Messages.php'; + +// Resources +$mbResourceTemplate = array( + 'localBasePath' => dirname(__FILE__), + 'remoteExtPath' => 'MoodBar' +); + +$wgResourceModules['ext.moodBar'] = $mbResourceTemplate + array( + 'styles' => array( ), + 'scripts' => array( ), + 'dependencies' => array( ), + 'messages' => array( ), +); Added: trunk/extensions/MoodBar/moodbar.sql =================================================================== --- trunk/extensions/MoodBar/moodbar.sql (rev 0) +++ trunk/extensions/MoodBar/moodbar.sql 2011-06-14 13:43:05 UTC (rev 90043) @@ -0,0 +1,30 @@ +CREATE TABLE /*_*/moodbar_feedback ( + mbf_id int unsigned NOT NULL PRIMARY KEY auto_increment, -- Primary key + mbf_type varchar(32) binary NOT NULL, -- Type of feedback + + -- User who provided the feedback + mbf_user_id int unsigned NOT NULL, -- User ID, or zero + mbf_user_ip varchar(255) binary NULL, -- If anonymous, user's IP address + + -- Page where the feedback was received + -- Nullable. + mbf_namespace int, + mbf_title varchar(255) binary, + + -- The feedback itself + mbf_comment varchar(255) binary, + + -- Options and context + mbf_anonymous tinyint unsigned not null default 0, -- Anonymity + mbf_timestamp varchar(14) binary not null, -- When feedback was received + mbf_system_type varchar(64) binary null, -- Operating System + mbf_user_agent varchar(255) binary null, -- User-Agent header + mbf_locale varchar(32) binary null, -- The locale of the user's browser + mbf_editing tinyint unsigned not null, -- Whether or not the user was editing + mbf_bucket varchar(128) binary null -- Bucket, for A/B testing +) /*$wgDBtableOptions*/; + +-- A little overboard with the indexes perhaps, but we want to be able to dice this data a lot! +CREATE INDEX /*i*/type_timestamp ON /*_*/moodbar_feedback (mbf_type,mbf_timestamp); +CREATE INDEX /*i*/user_timestamp ON /*_*/moodbar_feedback (mbf_user_id,mbf_user_ip,mbf_timestamp); +CREATE INDEX /*i*/title_type ON /*_*/moodbar_feedback (mbf_namespace,mbf_title,mbf_type,mbf_timestamp); _______________________________________________ MediaWiki-CVS mailing list [email protected] https://lists.wikimedia.org/mailman/listinfo/mediawiki-cvs
