Index: trunk/extensions/MoodBar/MoodBar.i18n.php |
— | — | @@ -18,6 +18,22 @@ |
19 | 19 | 'tooltip-p-moodbar-trigger-using' => '', |
20 | 20 | 'moodbar-trigger-feedback' => 'Feedback', |
21 | 21 | 'tooltip-p-moodbar-trigger-feedback' => '', |
| 22 | + 'right-moodbar-view' => 'View and export MoodBar feedback', |
| 23 | + 'moodbar-admin-title' => 'MoodBar feedback', |
| 24 | + 'moodbar-admin-intro' => 'This page allows you to view feedback submitted with the MoodBar', |
| 25 | + 'moodbar-admin-download' => 'Download as CSV', |
| 26 | + 'moodbar-header-id' => 'Feedback ID', |
| 27 | + 'moodbar-header-timestamp' => 'Timestamp', |
| 28 | + 'moodbar-header-type' => 'Type', |
| 29 | + 'moodbar-header-page' => 'Page', |
| 30 | + 'moodbar-header-usertype' => 'User type', |
| 31 | + 'moodbar-header-user' => 'User', |
| 32 | + 'moodbar-header-editmode' => 'Edit mode', |
| 33 | + 'moodbar-header-bucket' => 'Testing bucket', |
| 34 | + 'moodbar-header-system' => 'System type', |
| 35 | + 'moodbar-header-locale' => 'Locale', |
| 36 | + 'moodbar-header-useragent' => 'User-Agent', |
| 37 | + 'moodbar-header-comment' => 'Comments', |
22 | 38 | ); |
23 | 39 | |
24 | 40 | /** Message documentation |
Index: trunk/extensions/MoodBar/MoodBar.php |
— | — | @@ -25,6 +25,10 @@ |
26 | 26 | $wgHooks['BeforePageDisplay'][] = 'MoodBarHooks::onPageDisplay'; |
27 | 27 | $wgHooks['LoadExtensionSchemaUpdates'][] = 'MoodBarHooks::onLoadExtensionSchemaUpdates'; |
28 | 28 | |
| 29 | +// Special page |
| 30 | +$wgAutoloadClasses['SpecialMoodBar'] = dirname(__FILE__).'/SpecialMoodBar.php'; |
| 31 | +$wgSpecialPages['MoodBar'] = 'SpecialMoodBar'; |
| 32 | + |
29 | 33 | // Internationalisation |
30 | 34 | $wgExtensionMessagesFiles['MoodBar'] = dirname(__FILE__).'/MoodBar.i18n.php'; |
31 | 35 | |
— | — | @@ -45,3 +49,5 @@ |
46 | 50 | ), |
47 | 51 | 'position' => 'top', |
48 | 52 | ); |
| 53 | + |
| 54 | +$wgGroupPermissions['moodbar']['moodbar-view'] = true; |
Index: trunk/extensions/MoodBar/SpecialMoodBar.php |
— | — | @@ -0,0 +1,184 @@ |
| 2 | +<?php |
| 3 | + |
| 4 | +class SpecialMoodBar extends SpecialPage { |
| 5 | + protected $fields = array( |
| 6 | + 'id', |
| 7 | + 'timestamp', |
| 8 | + 'type', |
| 9 | + 'page', |
| 10 | + 'usertype', |
| 11 | + 'user', |
| 12 | + 'editmode', |
| 13 | + 'bucket', |
| 14 | + 'system', |
| 15 | + 'locale', |
| 16 | + 'useragent', |
| 17 | + 'comment', |
| 18 | + ); |
| 19 | + |
| 20 | + function __construct() { |
| 21 | + parent::__construct( 'MoodBar', 'moodbar-view' ); |
| 22 | + } |
| 23 | + |
| 24 | + function execute($par) { |
| 25 | + global $wgUser, $wgOut; |
| 26 | + |
| 27 | + if ( !$this->userCanExecute( $wgUser ) ) { |
| 28 | + $this->displayRestrictionError(); |
| 29 | + return; |
| 30 | + } |
| 31 | + |
| 32 | + $wgOut->setPageTitle( wfMsg( 'moodbar-admin-title' ) ); |
| 33 | + $wgOut->addWikiMsg( 'moodbar-admin-intro' ); |
| 34 | + |
| 35 | + $sk = $wgUser->getSkin(); |
| 36 | + $downloadTitle = $this->getTitle('csv'); |
| 37 | + $downloadText = wfMsgExt( 'moodbar-admin-download', 'parseinline' ); |
| 38 | + $downloadLink = $sk->link( $downloadTitle, $downloadText ); |
| 39 | + $wgOut->addHTML( $downloadLink ); |
| 40 | + |
| 41 | + $dbr = wfGetDB( DB_SLAVE ); |
| 42 | + |
| 43 | + $res = $dbr->select( 'moodbar_feedback', '*', 1, __METHOD__, |
| 44 | + array( 'order by' => 'mb_timestamp desc' ) ); |
| 45 | + |
| 46 | + if ( $par == 'csv' ) { |
| 47 | + $this->csvOutput( $res ); |
| 48 | + } else { |
| 49 | + $this->tableOutput( $res ); |
| 50 | + } |
| 51 | + } |
| 52 | + |
| 53 | + function tableOutput( $res ) { |
| 54 | + global $wgOut; |
| 55 | + $html = $this->tableHeader(); |
| 56 | + $rows = ''; |
| 57 | + |
| 58 | + foreach( $res as $row ) { |
| 59 | + $rows .= $this->showEntry( $row ); |
| 60 | + } |
| 61 | + |
| 62 | + $html .= Xml::tags( 'tbody', null, $rows ); |
| 63 | + |
| 64 | + $html = Xml::tags( 'table', array( 'class' => 'wikitable' ), $html ); |
| 65 | + |
| 66 | + $wgOut->addHTML( $html ); |
| 67 | + } |
| 68 | + |
| 69 | + function csvOutput( $res ) { |
| 70 | + global $wgOut, $wgRequest; |
| 71 | + |
| 72 | + $ts = wfTimestampNow(); |
| 73 | + $filename = "moodbar_feedback_$ts.csv"; |
| 74 | + $wgOut->disable(); |
| 75 | + wfResetOutputBuffers(); |
| 76 | + $wgRequest->response()->header( "Content-disposition: attachment;filename={$filename}" ); |
| 77 | + $wgRequest->response()->header( "Content-type: text/csv; charset=utf-8" ); |
| 78 | + $fh = fopen( 'php://output', 'w' ); |
| 79 | + |
| 80 | + $this->csvHeader( $fh ); |
| 81 | + |
| 82 | + foreach( $res as $row ) { |
| 83 | + $data = MBFeedbackItem::load( $row ); |
| 84 | + $outData = array(); |
| 85 | + |
| 86 | + foreach( $this->fields as $field ) { |
| 87 | + switch( $field ) { |
| 88 | + case 'usertype': |
| 89 | + $user = $data->getProperty('user'); |
| 90 | + if ( $data->getProperty('anonymize') ) { |
| 91 | + $outData[] = 'anonymized'; |
| 92 | + } else if ( $user->isAnon() ) { |
| 93 | + $outData[] = 'ip'; |
| 94 | + } else { |
| 95 | + $outData[] = 'user'; |
| 96 | + } |
| 97 | + break; |
| 98 | + case 'user': |
| 99 | + $user = $data->getProperty('user'); |
| 100 | + if ( $data->getProperty('anonymize') ) { |
| 101 | + $outData[] = ''; |
| 102 | + } else { |
| 103 | + $outData[] = $user->getName(); |
| 104 | + } |
| 105 | + break; |
| 106 | + case 'page': |
| 107 | + $outData[] = $data->getProperty('page')->getPrefixedText(); |
| 108 | + break; |
| 109 | + default: |
| 110 | + $outData[] = $data->getProperty($field); |
| 111 | + } |
| 112 | + } |
| 113 | + |
| 114 | + fputcsv( $fh, $outData ); |
| 115 | + } |
| 116 | + |
| 117 | + fclose( $fh ); |
| 118 | + } |
| 119 | + |
| 120 | + function csvHeader( $fh ) { |
| 121 | + fputcsv( $fh, $this->fields ); |
| 122 | + } |
| 123 | + |
| 124 | + function tableHeader( ) { |
| 125 | + $html = "<thead>"; |
| 126 | + $row = ''; |
| 127 | + foreach( $this->fields as $field ) { |
| 128 | + $msg = wfMsgExt( 'moodbar-header-'.$field, 'parseinline' ); |
| 129 | + $row .= Xml::tags( 'th', null, $msg ); |
| 130 | + } |
| 131 | + |
| 132 | + $html .= Xml::tags( 'tr', null, $row ) . '</thead>'; |
| 133 | + |
| 134 | + return $html; |
| 135 | + } |
| 136 | + |
| 137 | + function showEntry( $row ) { |
| 138 | + $out = ''; |
| 139 | + |
| 140 | + $data = MBFeedbackItem::load( $row ); |
| 141 | + $outData = null; |
| 142 | + |
| 143 | + foreach( $this->fields as $field ) { |
| 144 | + switch( $field ) { |
| 145 | + case 'usertype': |
| 146 | + $user = $data->getProperty('user'); |
| 147 | + if ( $data->getProperty('anonymize') ) { |
| 148 | + $outData = 'anonymized'; |
| 149 | + } else if ( $user->isAnon() ) { |
| 150 | + $outData = 'ip'; |
| 151 | + } else { |
| 152 | + $outData = 'user'; |
| 153 | + } |
| 154 | + break; |
| 155 | + case 'user': |
| 156 | + $user = $data->getProperty('user'); |
| 157 | + if ( $data->getProperty('anonymize') ) { |
| 158 | + $outData = ''; |
| 159 | + } else { |
| 160 | + $outData = $user->getName(); |
| 161 | + } |
| 162 | + break; |
| 163 | + case 'page': |
| 164 | + $title = $data->getProperty('page'); |
| 165 | + |
| 166 | + global $wgUser; |
| 167 | + $linker = $wgUser->getSkin(); |
| 168 | + $outData = $linker->link( $title ); |
| 169 | + break; |
| 170 | + case 'timestamp': |
| 171 | + global $wgLang; |
| 172 | + $outData = $wgLang->timeanddate( $data->getProperty('timestamp') ); |
| 173 | + break; |
| 174 | + default: |
| 175 | + $outData = $data->getProperty($field); |
| 176 | + break; |
| 177 | + } |
| 178 | + |
| 179 | + $out .= Xml::tags( 'td', null, $outData ); |
| 180 | + } |
| 181 | + |
| 182 | + return $out; |
| 183 | + } |
| 184 | +} |
| 185 | + |