Index: trunk/extensions/MoodBar/ApiMoodBar.php |
— | — | @@ -3,28 +3,28 @@ |
4 | 4 | class ApiMoodBar extends ApiBase { |
5 | 5 | public function execute() { |
6 | 6 | $params = $this->extractRequestParams(); |
7 | | - |
| 7 | + |
8 | 8 | $params['page'] = Title::newFromText( $params['page'] ); |
9 | | - |
| 9 | + |
10 | 10 | // Params are deliberately named the same as the properties, |
11 | 11 | // just slurp them through. |
12 | 12 | $item = MBFeedbackItem::create( array() ); |
13 | | - |
| 13 | + |
14 | 14 | $setParams = array(); |
15 | 15 | foreach( $params as $key => $value ) { |
16 | 16 | if ( $item->isValidKey( $key ) ) { |
17 | 17 | $setParams[$key] = $value; |
18 | 18 | } |
19 | 19 | } |
20 | | - |
| 20 | + |
21 | 21 | $item->setProperties( $setParams ); |
22 | | - |
| 22 | + |
23 | 23 | $item->save(); |
24 | | - |
| 24 | + |
25 | 25 | $result = array( 'result' => 'success' ); |
26 | 26 | $this->getResult()->addValue( null, $this->getModuleName(), $result ); |
27 | 27 | } |
28 | | - |
| 28 | + |
29 | 29 | public function needsToken() { |
30 | 30 | return true; |
31 | 31 | } |
— | — | @@ -70,13 +70,7 @@ |
71 | 71 | public function getVersion() { |
72 | 72 | return __CLASS__ . ': $Id$'; |
73 | 73 | } |
74 | | - |
75 | | - public function getPossibleErrors() { |
76 | | - return array_merge( parent::getPossibleErrors(), array( |
77 | | - |
78 | | - ) ); |
79 | | - } |
80 | | - |
| 74 | + |
81 | 75 | public function getParamDescription() { |
82 | 76 | return array( |
83 | 77 | 'page' => 'The page the feedback is on', |
— | — | @@ -91,7 +85,7 @@ |
92 | 86 | 'token' => 'An edit token', |
93 | 87 | ); |
94 | 88 | } |
95 | | - |
| 89 | + |
96 | 90 | public function getDescription() { |
97 | 91 | return 'Allows users to submit feedback about their experiences on the site'; |
98 | 92 | } |
Index: trunk/extensions/MoodBar/FeedbackItem.php |
— | — | @@ -13,12 +13,12 @@ |
14 | 14 | 'comment', // The feedback itself |
15 | 15 | 'page', // The page where it was submitted |
16 | 16 | 'type', |
17 | | - |
| 17 | + |
18 | 18 | // Housekeeping |
19 | 19 | 'timestamp', |
20 | 20 | 'user', // User object who submitted the feedback |
21 | 21 | 'anonymize', |
22 | | - |
| 22 | + |
23 | 23 | // Statistics |
24 | 24 | 'useragent', |
25 | 25 | 'system', |
— | — | @@ -27,22 +27,22 @@ |
28 | 28 | 'bucket', |
29 | 29 | 'user-editcount', |
30 | 30 | ); |
31 | | - |
| 31 | + |
32 | 32 | /** Valid values for the 'type' parameter. **/ |
33 | 33 | protected static $validTypes = array( 'happy', 'sad', 'confused' ); |
34 | | - |
| 34 | + |
35 | 35 | /** |
36 | 36 | * Default constructor. |
37 | 37 | * Don't use this, use either MBFeedbackItem::newFromRow or MBFeedbackItem::create |
38 | 38 | */ |
39 | 39 | protected function __construct() { |
40 | 40 | $this->data = array_fill_keys( $this->validMembers, null ); |
41 | | - |
| 41 | + |
42 | 42 | // Non-nullable boolean fields |
43 | 43 | $this->setProperty('anonymize', false); |
44 | 44 | $this->setProperty('editmode', false); |
45 | 45 | } |
46 | | - |
| 46 | + |
47 | 47 | /** |
48 | 48 | * Factory function to create a new MBFeedbackItem |
49 | 49 | * @param $info Associative array of values |
— | — | @@ -55,7 +55,7 @@ |
56 | 56 | $newObject->initialiseNew( $info ); |
57 | 57 | return $newObject; |
58 | 58 | } |
59 | | - |
| 59 | + |
60 | 60 | /** |
61 | 61 | * Initialiser for new MBFeedbackItems |
62 | 62 | * @param $info Associative array of values |
— | — | @@ -63,16 +63,16 @@ |
64 | 64 | */ |
65 | 65 | protected function initialiseNew( $info ) { |
66 | 66 | global $wgUser; |
67 | | - |
| 67 | + |
68 | 68 | $template = array( |
69 | 69 | 'user' => $wgUser, |
70 | 70 | 'timestamp' => wfTimestampNow(), |
71 | 71 | ); |
72 | | - |
| 72 | + |
73 | 73 | $this->setProperties( $template ); |
74 | 74 | $this->setProperties( $info ); |
75 | 75 | } |
76 | | - |
| 76 | + |
77 | 77 | /** |
78 | 78 | * Factory function to load an MBFeedbackItem from a DB row. |
79 | 79 | * @param $row A row, from DatabaseBase::fetchObject |
— | — | @@ -83,7 +83,7 @@ |
84 | 84 | $newObject->initialiseFromRow( $row ); |
85 | 85 | return $newObject; |
86 | 86 | } |
87 | | - |
| 87 | + |
88 | 88 | /** |
89 | 89 | * Initialiser for MBFeedbackItems loaded from the database |
90 | 90 | * @param $row A row object from DatabaseBase::fetchObject |
— | — | @@ -103,9 +103,9 @@ |
104 | 104 | 'editmode' => $row->mbf_editing, |
105 | 105 | 'user-editcount' => $row->mbf_user_editcount, |
106 | 106 | ); |
107 | | - |
| 107 | + |
108 | 108 | $properties['page'] = Title::makeTitleSafe( $row->mbf_namespace, $row->mbf_title ); |
109 | | - |
| 109 | + |
110 | 110 | if ( !empty($row->user_id) ) { |
111 | 111 | $properties['user'] = User::newFromRow( $row ); |
112 | 112 | } elseif ( $row->mbf_user_id > 0 ) { |
— | — | @@ -113,10 +113,10 @@ |
114 | 114 | } else { |
115 | 115 | $properties['user'] = User::newFromName( $row->mbf_user_ip ); |
116 | 116 | } |
117 | | - |
| 117 | + |
118 | 118 | $this->setProperties( $properties ); |
119 | 119 | } |
120 | | - |
| 120 | + |
121 | 121 | /** |
122 | 122 | * Set a group of properties. Throws an exception on invalid property. |
123 | 123 | * @param $values An associative array of properties to set. |
— | — | @@ -126,15 +126,15 @@ |
127 | 127 | if ( ! $this->isValidKey($key) ) { |
128 | 128 | throw new MWException( "Attempt to set invalid property $key" ); |
129 | 129 | } |
130 | | - |
| 130 | + |
131 | 131 | if ( ! $this->validatePropertyValue($key, $value) ) { |
132 | 132 | throw new MWException( "Attempt to set invalid value for $key" ); |
133 | 133 | } |
134 | | - |
| 134 | + |
135 | 135 | $this->data[$key] = $value; |
136 | 136 | } |
137 | 137 | } |
138 | | - |
| 138 | + |
139 | 139 | /** |
140 | 140 | * Set a group of values. |
141 | 141 | * @param $key The property to set. |
— | — | @@ -143,7 +143,7 @@ |
144 | 144 | public function setProperty( $key, $value ) { |
145 | 145 | $this->setProperties( array( $key => $value ) ); |
146 | 146 | } |
147 | | - |
| 147 | + |
148 | 148 | /** |
149 | 149 | * Get a property. |
150 | 150 | * @param $key The property to get |
— | — | @@ -153,10 +153,10 @@ |
154 | 154 | if ( ! $this->isValidKey($key) ) { |
155 | 155 | throw new MWException( "Attempt to get invalid property $key" ); |
156 | 156 | } |
157 | | - |
| 157 | + |
158 | 158 | return $this->data[$key]; |
159 | 159 | } |
160 | | - |
| 160 | + |
161 | 161 | /** |
162 | 162 | * Check a property key for validity. |
163 | 163 | * If a property key is valid, it will be prefilled to NULL. |
— | — | @@ -165,7 +165,7 @@ |
166 | 166 | public function isValidKey( $key ) { |
167 | 167 | return in_array( $key, $this->validMembers ); |
168 | 168 | } |
169 | | - |
| 169 | + |
170 | 170 | /** |
171 | 171 | * Check if a property value is valid for that property |
172 | 172 | * @param $key The key of the property to check. |
— | — | @@ -182,36 +182,36 @@ |
183 | 183 | } elseif ( $key == 'comment' ) { |
184 | 184 | return mb_strlen( $value ) <= 140; |
185 | 185 | } |
186 | | - |
| 186 | + |
187 | 187 | return true; |
188 | 188 | } |
189 | | - |
| 189 | + |
190 | 190 | /** |
191 | 191 | * Writes this MBFeedbackItem to the database. |
192 | 192 | * Throws an exception if this it is already in the database. |
193 | 193 | * @return The MBFeedbackItem's new ID. |
194 | 194 | */ |
195 | 195 | public function save() { |
196 | | - |
| 196 | + |
197 | 197 | if ( $this->getProperty('id') ) { |
198 | 198 | throw new MWException( "This ".__CLASS__." is already in the database." ); |
199 | 199 | } |
200 | | - |
| 200 | + |
201 | 201 | // Add edit count if necessary |
202 | 202 | if ( $this->getProperty('user-editcount') === null && |
203 | 203 | $this->getProperty('user') ) |
204 | 204 | { |
205 | 205 | $value = $this->getProperty('user'); |
206 | | - |
| 206 | + |
207 | 207 | if ( $value->isAnon() ) { |
208 | 208 | $this->setProperty( 'user-editcount', 0 ); |
209 | 209 | } else { |
210 | 210 | $this->setProperty( 'user-editcount', $value->getEditCount() ); |
211 | 211 | } |
212 | 212 | } |
213 | | - |
| 213 | + |
214 | 214 | $dbw = wfGetDB( DB_MASTER ); |
215 | | - |
| 215 | + |
216 | 216 | $row = array( |
217 | 217 | 'mbf_id' => $dbw->nextSequenceValue( 'moodbar_feedback_mbf_id' ), |
218 | 218 | 'mbf_type' => $this->getProperty('type'), |
— | — | @@ -225,7 +225,7 @@ |
226 | 226 | 'mbf_editing' => $this->getProperty('editmode'), |
227 | 227 | 'mbf_user_editcount' => $this->getProperty('user-editcount'), |
228 | 228 | ); |
229 | | - |
| 229 | + |
230 | 230 | $user = $this->getProperty('user'); |
231 | 231 | if ( $user->isAnon() ) { |
232 | 232 | $row['mbf_user_id'] = 0; |
— | — | @@ -233,25 +233,25 @@ |
234 | 234 | } else { |
235 | 235 | $row['mbf_user_id'] = $user->getId(); |
236 | 236 | } |
237 | | - |
| 237 | + |
238 | 238 | $page = $this->getProperty('page'); |
239 | 239 | if ( $page ) { |
240 | 240 | $row['mbf_namespace'] = $page->getNamespace(); |
241 | 241 | $row['mbf_title'] = $page->getDBkey(); |
242 | 242 | } |
243 | | - |
| 243 | + |
244 | 244 | $dbw->insert( 'moodbar_feedback', $row, __METHOD__ ); |
245 | | - |
| 245 | + |
246 | 246 | $this->setProperty( 'id', $dbw->insertId() ); |
247 | | - |
| 247 | + |
248 | 248 | return $this->getProperty('id'); |
249 | 249 | } |
250 | | - |
| 250 | + |
251 | 251 | /** |
252 | 252 | * Gets the valid types of a feedback item. |
253 | 253 | */ |
254 | 254 | public static function getValidTypes() { |
255 | 255 | return self::$validTypes; |
256 | 256 | } |
257 | | - |
| 257 | + |
258 | 258 | } |
Index: trunk/extensions/MoodBar/Formatter.php |
— | — | @@ -15,7 +15,7 @@ |
16 | 16 | switch( $field ) { |
17 | 17 | case 'page': |
18 | 18 | $title = $data->getProperty('page'); |
19 | | - |
| 19 | + |
20 | 20 | global $wgUser; |
21 | 21 | $linker = $wgUser->getSkin(); |
22 | 22 | $outData = $linker->link( $title ); |
— | — | @@ -38,10 +38,10 @@ |
39 | 39 | $outData = htmlspecialchars( $outData ); |
40 | 40 | break; |
41 | 41 | } |
42 | | - |
| 42 | + |
43 | 43 | return $outData; |
44 | 44 | } |
45 | | - |
| 45 | + |
46 | 46 | /** |
47 | 47 | * Gets an internal representation of $field from $data. |
48 | 48 | * @param $data MBFeedbackItem to retrieve the data from. |
— | — | @@ -50,7 +50,7 @@ |
51 | 51 | */ |
52 | 52 | public static function getInternalRepresentation( $data, $field ) { |
53 | 53 | $outData = null; |
54 | | - |
| 54 | + |
55 | 55 | switch( $field ) { |
56 | 56 | case 'namespace': |
57 | 57 | $page = $data->getProperty('page'); |
— | — | @@ -86,7 +86,7 @@ |
87 | 87 | default: |
88 | 88 | $outData = $data->getProperty($field); |
89 | 89 | } |
90 | | - |
| 90 | + |
91 | 91 | return $outData; |
92 | 92 | } |
93 | 93 | } |
Index: trunk/extensions/MoodBar/MoodBar.php |
— | — | @@ -119,7 +119,6 @@ |
120 | 120 | ), |
121 | 121 | ); |
122 | 122 | |
123 | | - |
124 | 123 | /** Configuration **/ |
125 | 124 | /** The registration time after which users will be shown the MoodBar **/ |
126 | 125 | $wgMoodBarCutoffTime = null; |
Index: trunk/extensions/MoodBar/SpecialMoodBar.php |
— | — | @@ -17,24 +17,24 @@ |
18 | 18 | 'mbf_user_agent' => 'useragent', |
19 | 19 | 'mbf_comment' => 'comment', |
20 | 20 | ); |
21 | | - |
| 21 | + |
22 | 22 | function __construct() { |
23 | 23 | parent::__construct( 'MoodBar', 'moodbar-view' ); |
24 | 24 | } |
25 | | - |
| 25 | + |
26 | 26 | function execute($par) { |
27 | 27 | global $wgUser, $wgOut; |
28 | | - |
| 28 | + |
29 | 29 | if ( !$this->userCanExecute( $wgUser ) ) { |
30 | 30 | $this->displayRestrictionError(); |
31 | 31 | return; |
32 | 32 | } |
33 | | - |
| 33 | + |
34 | 34 | $wgOut->setPageTitle( wfMsg( 'moodbar-admin-title' ) ); |
35 | 35 | $wgOut->addWikiMsg( 'moodbar-admin-intro' ); |
36 | | - |
| 36 | + |
37 | 37 | $pager = new MoodBarPager(); |
38 | | - |
| 38 | + |
39 | 39 | if ( $pager->getNumRows() > 0 ) { |
40 | 40 | $wgOut->addHTML( |
41 | 41 | $pager->getNavigationBar() . |
— | — | @@ -50,38 +50,38 @@ |
51 | 51 | class MoodBarPager extends TablePager { |
52 | 52 | function getFieldNames() { |
53 | 53 | static $headers = null; |
54 | | - |
| 54 | + |
55 | 55 | if ( is_null( $headers ) ) { |
56 | 56 | $headers = array(); |
57 | 57 | foreach( SpecialMoodBar::$fields as $field => $property ) { |
58 | 58 | $headers[$field] = wfMessage("moodbar-header-$property")->text(); |
59 | 59 | } |
60 | 60 | } |
61 | | - |
| 61 | + |
62 | 62 | return $headers; |
63 | 63 | } |
64 | | - |
| 64 | + |
65 | 65 | // Overridden from TablePager, it's just easier because |
66 | 66 | // we're doing things with a proper object model |
67 | 67 | function formatRow( $row ) { |
68 | 68 | $out = ''; |
69 | | - |
| 69 | + |
70 | 70 | $data = MBFeedbackItem::load( $row ); |
71 | 71 | $outData = null; |
72 | | - |
| 72 | + |
73 | 73 | foreach( SpecialMoodBar::$fields as $field ) { |
74 | 74 | $outData = MoodBarFormatter::getHTMLRepresentation( $data, $field ); |
75 | 75 | $out .= Xml::tags( 'td', null, $outData ); |
76 | 76 | } |
77 | | - |
| 77 | + |
78 | 78 | $out = Xml::tags( 'tr', $this->getRowAttrs($row), $out ) . "\n"; |
79 | 79 | return $out; |
80 | 80 | } |
81 | | - |
| 81 | + |
82 | 82 | function formatValue( $name, $value ) { |
83 | 83 | return ''; |
84 | 84 | } |
85 | | - |
| 85 | + |
86 | 86 | function getQueryInfo() { |
87 | 87 | $info = array( |
88 | 88 | 'tables' => array('moodbar_feedback', 'user'), |
— | — | @@ -93,14 +93,14 @@ |
94 | 94 | ), |
95 | 95 | ), |
96 | 96 | ); |
97 | | - |
| 97 | + |
98 | 98 | return $info; |
99 | 99 | } |
100 | | - |
| 100 | + |
101 | 101 | function getDefaultSort() { |
102 | 102 | return 'mbf_id'; |
103 | 103 | } |
104 | | - |
| 104 | + |
105 | 105 | function isFieldSortable( $name ) { |
106 | 106 | $sortable = array( |
107 | 107 | 'mbf_id', |
— | — | @@ -108,10 +108,10 @@ |
109 | 109 | 'mbf_user_id', |
110 | 110 | 'mbf_namespace', |
111 | 111 | ); |
112 | | - |
| 112 | + |
113 | 113 | return in_array( $name, $sortable ); |
114 | 114 | } |
115 | | - |
| 115 | + |
116 | 116 | function getTitle() { |
117 | 117 | return SpecialPage::getTitleFor( 'MoodBar' ); |
118 | 118 | } |
Index: trunk/extensions/MoodBar/MoodBar.hooks.php |
— | — | @@ -8,10 +8,10 @@ |
9 | 9 | if ( self::shouldShowMoodbar( $output, $skin ) ) { |
10 | 10 | $output->addModules( array( 'ext.moodBar.init', 'ext.moodBar.core' ) ); |
11 | 11 | } |
12 | | - |
| 12 | + |
13 | 13 | return true; |
14 | 14 | } |
15 | | - |
| 15 | + |
16 | 16 | /** |
17 | 17 | * Determines whether or not we should show the MoodBar. |
18 | 18 | */ |
— | — | @@ -26,11 +26,11 @@ |
27 | 27 | } |
28 | 28 | global $wgUser; |
29 | 29 | $user = $wgUser; |
30 | | - |
| 30 | + |
31 | 31 | if ( $user->isAnon() ) { |
32 | 32 | return false; |
33 | 33 | } |
34 | | - |
| 34 | + |
35 | 35 | // Only show MoodBar for users registered after a certain time |
36 | 36 | global $wgMoodBarCutoffTime; |
37 | 37 | if ( $wgMoodBarCutoffTime && |
— | — | @@ -38,14 +38,14 @@ |
39 | 39 | { |
40 | 40 | return false; |
41 | 41 | } |
42 | | - |
| 42 | + |
43 | 43 | if ( class_exists('EditPageTracking') ) { |
44 | 44 | return ((bool)EditPageTracking::getFirstEditPage($user)); |
45 | 45 | } |
46 | | - |
| 46 | + |
47 | 47 | return true; |
48 | 48 | } |
49 | | - |
| 49 | + |
50 | 50 | /** |
51 | 51 | * ResourceLoaderGetConfigVars hook |
52 | 52 | */ |
— | — | @@ -57,27 +57,27 @@ |
58 | 58 | ) + $wgMoodBarConfig; |
59 | 59 | return true; |
60 | 60 | } |
61 | | - |
| 61 | + |
62 | 62 | public static function makeGlobalVariablesScript( &$vars ) { |
63 | 63 | global $wgUser; |
64 | 64 | $vars['mbEditToken'] = $wgUser->editToken(); |
65 | 65 | return true; |
66 | 66 | } |
67 | | - |
| 67 | + |
68 | 68 | /** |
69 | 69 | * Runs MoodBar schema updates |
70 | 70 | */ |
71 | 71 | public static function onLoadExtensionSchemaUpdates( $updater = null ) { |
72 | 72 | $updater->addExtensionUpdate( array( 'addTable', 'moodbar_feedback', |
73 | 73 | dirname(__FILE__).'/sql/MoodBar.sql', true ) ); |
74 | | - |
| 74 | + |
75 | 75 | $updater->addExtensionUpdate( array( 'addField', 'moodbar_feedback', |
76 | 76 | 'mbf_user_editcount', dirname(__FILE__).'/sql/mbf_user_editcount.sql', true ) |
77 | 77 | ); |
78 | | - |
| 78 | + |
79 | 79 | return true; |
80 | 80 | } |
81 | | - |
| 81 | + |
82 | 82 | /** |
83 | 83 | * Gets the MoodBar testing bucket that a user is in. |
84 | 84 | * @param $user The user to check |
— | — | @@ -86,9 +86,9 @@ |
87 | 87 | public static function getUserBuckets( $user ) { |
88 | 88 | $id = $user->getID(); |
89 | 89 | $buckets = array(); |
90 | | - |
| 90 | + |
91 | 91 | // No show-time bucketing yet. This method is a stub. |
92 | | - |
| 92 | + |
93 | 93 | sort($buckets); |
94 | 94 | return $buckets; |
95 | 95 | } |
Index: trunk/extensions/MoodBar/exportMoodBar.php |
— | — | @@ -24,33 +24,33 @@ |
25 | 25 | 'useragent', |
26 | 26 | 'comment', |
27 | 27 | ); |
28 | | - |
| 28 | + |
29 | 29 | public function __construct() { |
30 | 30 | parent::__construct(); |
31 | 31 | $this->mDescription = "Exports MoodBar feedback"; |
32 | 32 | $this->addOption( 'since-id', 'Get feedback after this ID' ); |
33 | 33 | $this->addOption( 'since-time', 'Get feedback after this time' ); |
34 | 34 | } |
35 | | - |
| 35 | + |
36 | 36 | public function execute() { |
37 | 37 | $dbr = wfGetDB( DB_SLAVE ); |
38 | 38 | $lastRowCount = 1; |
39 | 39 | $fh = fopen('php://stdout', 'w'); |
40 | | - |
| 40 | + |
41 | 41 | $offsetCond = array( 1 ); |
42 | | - |
| 42 | + |
43 | 43 | if ( $this->getOption('since-id') ) { |
44 | 44 | $offsetCond[] = 'mbf_id > '.$dbr->addQuotes( $this->getArg('since-id') ); |
45 | 45 | } |
46 | | - |
| 46 | + |
47 | 47 | if ( $this->getOption('since-time') ) { |
48 | 48 | $ts = $dbr->timestamp( $this->getArg('since-id') ); |
49 | 49 | $offsetCond[] = 'mbf_timestamp > '.$dbr->addQuotes( $ts ); |
50 | 50 | } |
51 | | - |
| 51 | + |
52 | 52 | fputcsv( $fh, $this->fields ); |
53 | 53 | $lastId = 0; |
54 | | - |
| 54 | + |
55 | 55 | while ( $lastRowCount > 0 ) { |
56 | 56 | $res = $dbr->select( |
57 | 57 | array('moodbar_feedback','user'), |
— | — | @@ -65,27 +65,27 @@ |
66 | 66 | ) |
67 | 67 | ) |
68 | 68 | ); |
69 | | - |
| 69 | + |
70 | 70 | $lastRowCount = $dbr->numRows( $res ); |
71 | | - |
| 71 | + |
72 | 72 | foreach( $res as $row ) { |
73 | 73 | $this->outputRow( $fh, $row ); |
74 | 74 | $lastId = $row->mbf_id; |
75 | 75 | } |
76 | | - |
| 76 | + |
77 | 77 | $offsetCond = 'mbf_id > ' . $dbr->addQuotes( $lastId ); |
78 | 78 | } |
79 | 79 | } |
80 | | - |
| 80 | + |
81 | 81 | protected function outputRow( $fh, $row ) { |
82 | 82 | $item = MBFeedbackItem::load( $row ); |
83 | 83 | $user = User::newFromRow( $row ); |
84 | 84 | $outData = array(); |
85 | | - |
| 85 | + |
86 | 86 | foreach( $this->fields as $field ) { |
87 | 87 | $outData[] = MoodBarFormatter::getInternalRepresentation( $item, $field ); |
88 | 88 | } |
89 | | - |
| 89 | + |
90 | 90 | fputcsv( $fh, $outData ); |
91 | 91 | } |
92 | 92 | } |