public function execute( $par ) {
        global $wgRequest, $wgOut, $wgUser;
		$this->setHeaders();
		if( $wgUser->isAllowed( 'feedback' ) ) {
			if( $wgUser->isBlocked() ) {
				$wgOut->blockedPage();
				return;
			}
		} else {
			$wgOut->permissionRequired( 'feedback' );
			return;
		}
		if( wfReadOnly() ) {
			$wgOut->readOnlyPage();
			return;
		}
		// Purge expired entries on one in every 10 queries
		if( 0 == mt_rand( 0, 10 ) ) {
			ReaderFeedback::purgeExpiredAverages();
		}
		$this->skin = $wgUser->getSkin();
		# Check if there is a featured level
		$this->namespace = $wgRequest->getInt( 'namespace' );
		$this->tag = $wgRequest->getVal( 'ratingtag' );
		$this->tier = $wgRequest->getInt( 'ratingtier' );

		$this->showForm();
		$this->showPageList();
	}
	private function submit() {
		global $wgUser;
		$dbw = wfGetDB( DB_MASTER );
		# Get date timestamp...
		$now = wfTimestampNow();
		$date = str_pad( substr( $now, 0, 8 ), 14, '0' );
		if( count($this->dims) == 0 )
			return self::REVIEW_ERROR;
		$ratings = $this->flattenRatings( $this->dims );
		# Make sure revision is valid!
		$rev = Revision::newFromId( $this->oldid );
		if( !$rev || !$rev->getTitle()->equals( $this->page ) ) {
			return self::REVIEW_ERROR; // opps!
		}
		$ip = wfGetIP();
		if( !$wgUser->getId() && !$ip ) {
			return self::REVIEW_ERROR; // we need to keep track somehow
		}
		$article = new Article( $this->page );
		# Check if the user is spamming reviews...
		if( $wgUser->pingLimiter( 'feedback' ) || $wgUser->pingLimiter() ) {
			return self::REVIEW_ERROR;
		}
		# Check if user already voted before...
		if( self::userAlreadyVoted( $this->page, $this->oldid ) ) {
			return self::REVIEW_DUP;
		}
		# Update review records to limit double voting!
		$insertRow = array( 
			'rfb_rev_id'    => $this->oldid,
			'rfb_user'      => $wgUser->getId(),
			'rfb_ip'        => $ip,
			'rfb_timestamp' => $dbw->timestamp( $now ),
			'rfb_ratings'   => $ratings
		);
		# Make sure initial page data is there to begin with...
		$insertRows = array();
		foreach( $this->dims as $tag => $val ) {
			if( $val < 0 ); // don't store "unsure" votes
			$insertRows[] = array(
				'rfh_page_id' => $rev->getPage(),
				'rfh_tag'     => $tag,
				'rfh_total'   => 0,
				'rfh_count'   => 0,
				'rfh_date'    => $date
			);
		}
		$dbw->insert( 'reader_feedback', $insertRow, __METHOD__, 'IGNORE' );
		$dbw->insert( 'reader_feedback_history', $insertRows, __METHOD__, 'IGNORE' );
		# Update aggregate data for this page over time...
		$touched = $dbw->timestamp( $now );
		$insertRows = array();
		foreach( $this->dims as $tag => $val ) {
			if( $val < 0 ) continue; // don't store "unsure" votes
			# Update daily averages
			$dbw->update( 'reader_feedback_history',
				array( 'rfh_total = rfh_total + '.intval($val), 
					'rfh_count = rfh_count + 1'),
				array( 'rfh_page_id' => $rev->getPage(), 
					'rfh_tag' => $tag,
					'rfh_date' => $date ),
				__METHOD__
			);
			# Get effective tag values for this page..
			list($aveVal,$n) = ReaderFeedback::getAverageRating( $article, $tag, true );
			$insertRows[] = array( 
				'rfp_page_id' => $rev->getPage(),
				'rfp_tag'     => $tag,
				'rfp_ave_val' => $aveVal,
				'rfp_count'   => $n,
				'rfp_touched' => $touched
			);
		}
		# Update recent averages
		$dbw->replace( 'reader_feedback_pages', array( 'PRIMARY' ), $insertRows, __METHOD__ );
		# For logged in users, box should disappear
		if( $wgUser->getId() ) {
			$this->page->invalidateCache();
		}
		# Prune expired page aggregate data
		if( 0 == mt_rand( 0, 99 ) ) {
			ReaderFeedback::purgeExpiredAverages();
		}
		return self::REVIEW_OK;
	}