Changeset 1566 for trunk/bp-activity/bp-activity-classes.php
- Timestamp:
- 06/23/2009 12:57:13 AM (15 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/bp-activity/bp-activity-classes.php
r1366 r1566 10 10 var $component_action; 11 11 var $date_recorded; 12 var $is_private = false; 13 var $no_sitewide_cache = false; 14 15 var $table_name; 16 var $table_name_cached; 17 var $for_secondary_user = false; 18 19 function bp_activity_activity( $id = null, $populate = true ) { 12 var $hide_sitewide = false; 13 14 function bp_activity_activity( $args = false, $populate = false ) { 20 15 global $bp; 21 16 22 if ( $id ) { 23 $this->id = $id; 17 if ( $args ) { 18 extract( $args ); 19 20 $this->user_id = $user_id; 21 $this->component_name = $component_name; 22 $this->component_action = $component_action; 23 $this->item_id = $item_id; 24 $this->secondary_item_id = $secondary_item_id; 24 25 25 26 if ( $populate ) … … 31 32 global $wpdb, $bp; 32 33 33 $activity = $wpdb->get_row( $wpdb->prepare( "SELECT * FROM {$this->table_name} WHERE id = %d", $this->id ) ); 34 34 $activity = $wpdb->get_row( $wpdb->prepare( "SELECT * FROM {$bp->activity->table_name} WHERE id = %d", $this->id ) ); 35 36 $this->id = $activity->id; 35 37 $this->item_id = $activity->item_id; 36 38 $this->secondary_item_id = $activity->secondary_item_id; 37 39 $this->user_id = $activity->user_id; 40 $this->content = $activity->content; 41 $this->primary_link = $activity->primary_link; 38 42 $this->component_name = $activity->component_name; 39 43 $this->component_action = $activity->component_action; 40 44 $this->date_recorded = $activity->date_recorded; 41 $this->is_private = $activity->is_private; 42 $this->no_sitewide_cache = $activity->no_sitewide_cache; 45 $this->hide_sitewide = $activity->hide_sitewide; 43 46 } 44 47 … … 48 51 do_action( 'bp_activity_before_save', $this ); 49 52 50 if ( !$this->item_id || !$this->user_id || $this->is_private || !$this->component_name ) 51 return false; 52 53 // Set the table names 54 $this->table_name = $bp->activity->table_name_user_activity; 55 $this->table_name_cached = $bp->activity->table_name_user_activity_cached; 56 57 if ( !$this->exists() ) { 58 // Insert the new activity into the activity table. 59 $activity = $wpdb->query( $wpdb->prepare( "INSERT INTO {$this->table_name} ( item_id, secondary_item_id, user_id, component_name, component_action, date_recorded, is_private, no_sitewide_cache ) VALUES ( %d, %d, %d, %s, %s, FROM_UNIXTIME(%d), %d, %d )", $this->item_id, $this->secondary_item_id, $this->user_id, $this->component_name, $this->component_action, $this->date_recorded, $this->is_private, $this->no_sitewide_cache ) ); 60 61 // Fetch the formatted activity content so we can add it to the cache. 53 if ( !$this->user_id || !$this->component_name || !$this->component_action ) 54 return false; 55 56 /*** 57 * Before v1.1 of BuddyPress, activity content was calculated at a later point. This is no longer the 58 * case, to to be backwards compatible we need to fetch content here to continue. 59 */ 60 if ( empty( $this->content ) || !$this->content ) { 62 61 if ( function_exists( $bp->{$this->component_name}->format_activity_function ) ) { 63 if ( !$ activity_content = call_user_func( $bp->{$this->component_name}->format_activity_function, $this->item_id, $this->user_id, $this->component_action, $this->secondary_item_id, $this->for_secondary_user ) )62 if ( !$fetched_content = call_user_func( $bp->{$this->component_name}->format_activity_function, $this->item_id, $this->user_id, $this->component_action, $this->secondary_item_id, $this->for_secondary_user ) ) 64 63 return false; 65 } 66 67 // Add the cached version of the activity to the cached activity table. 68 $activity_cached = $wpdb->query( $wpdb->prepare( "INSERT INTO {$this->table_name_cached} ( user_id, item_id, secondary_item_id, content, primary_link, component_name, component_action, date_cached, date_recorded, is_private ) VALUES ( %d, %d, %d, %s, %s, %s, %s, FROM_UNIXTIME(%d), FROM_UNIXTIME(%d), %d )", $this->user_id, $this->item_id, $this->secondary_item_id, $activity_content['content'], $activity_content['primary_link'], $this->component_name, $this->component_action, time(), $this->date_recorded, $this->is_private ) ); 69 70 // Add the cached version of the activity to the sitewide activity table. 71 if ( !$this->no_sitewide_cache ) 72 $sitewide_cached = $wpdb->query( $wpdb->prepare( "INSERT INTO {$bp->activity->table_name_sitewide} ( user_id, item_id, secondary_item_id, content, primary_link, component_name, component_action, date_cached, date_recorded ) VALUES ( %d, %d, %d, %s, %s, %s, %s, FROM_UNIXTIME(%d), FROM_UNIXTIME(%d) )", $this->user_id, $this->item_id, $this->secondary_item_id, $activity_content['content'], $activity_content['primary_link'], $this->component_name, $this->component_action, time(), $this->date_recorded ) ); 73 74 if ( $activity && $activity_cached ) { 64 65 $this->content = $fetched_content['content']; 66 $this->primary_link = $fetched_content['primary_link']; 67 } 68 } 69 70 if ( !$this->primary_link ) 71 $this->primary_link = $bp->loggedin_user->domain; 72 73 if ( $existing_activity_id = $this->exists() ) 74 BP_Activity_Activity::delete_by_activity_id( $existing_activity_id ); 75 76 /* If we have an existing ID, update the activity item, otherwise insert it. */ 77 if ( $this->id ) { 78 if ( $wpdb->query( $wpdb->prepare( "UPDATE {$bp->activity->table_name} SET user_id = %d, component_name = %s, component_action = %s, content = %s, primary_link = %s, date_recorded = FROM_UNIXTIME(%d), item_id = %d, secondary_item_id = %d, hide_sitewide = %d WHERE id = %d", $this->user_id, $this->component_name, $this->component_action, $this->content, $this->primary_link, $this->date_recorded, $this->item_id, $this->secondary_item_id, $this->hide_sitewide, $this->id ) ) ) { 75 79 do_action( 'bp_activity_after_save', $this ); 76 80 return true; 77 81 } 78 79 return false; 80 } 82 } else { 83 if ( $wpdb->query( $wpdb->prepare( "INSERT INTO {$bp->activity->table_name} ( user_id, component_name, component_action, content, primary_link, date_recorded, item_id, secondary_item_id, hide_sitewide ) VALUES ( %d, %s, %s, %s, %s, FROM_UNIXTIME(%d), %d, %d, %d )", $this->user_id, $this->component_name, $this->component_action, $this->content, $this->primary_link, $this->date_recorded, $this->item_id, $this->secondary_item_id, $this->hide_sitewide ) ) ) { 84 do_action( 'bp_activity_after_save', $this ); 85 return true; 86 } 87 } 88 89 return false; 81 90 } 82 91 83 92 function exists() { 84 93 global $wpdb, $bp; 85 return $wpdb->get_var( $wpdb->prepare( "SELECT id FROM {$this->table_name} WHERE item_id = %d AND secondary_item_id = %d AND user_id = %d AND component_name = %s AND component_action = %s", $this->item_id, $this->secondary_item_id, $this->user_id, $this->component_name, $this->component_action ) ); 94 95 /* If we have an item id, try and match on that, if not do a content match */ 96 if ( $this->item_id ) { 97 if ( $this->secondary_item_id ) 98 $secondary_sql = $wpdb->prepare( " AND secondary_item_id = %d", $secondary_item_id ); 99 100 return $wpdb->get_var( $wpdb->prepare( "SELECT id FROM {$bp->activity->table_name} WHERE user_id = %d AND item_id = %d{$secondary_sql} AND component_name = %s AND component_action = %s", $this->user_id, $this->item_id, $this->component_name, $this->component_action ) ); 101 } else { 102 return $wpdb->get_var( $wpdb->prepare( "SELECT id FROM {$bp->activity->table_name} WHERE user_id = %d AND content = %s AND component_name = %s AND component_action = %s", $this->user_id, $this->content, $this->component_name, $this->component_action ) ); 103 } 86 104 } 87 105 … … 93 111 if ( !$user_id ) 94 112 return false; 95 96 if ( !$bp->activity ) 97 bp_activity_setup_globals(); 98 113 99 114 if ( $secondary_item_id ) 100 115 $secondary_sql = $wpdb->prepare( "AND secondary_item_id = %d", $secondary_item_id ); 101 116 102 if ( $component_action ) {117 if ( $component_action ) 103 118 $component_action_sql = $wpdb->prepare( "AND component_action = %s AND user_id = %d", $component_action, $user_id ); 104 $cached_component_action_sql = $wpdb->prepare( "AND component_action = %s", $component_action ); 105 } 106 107 $wpdb->query( $wpdb->prepare( "DELETE FROM {$bp->activity->table_name_user_activity} WHERE item_id = %d {$secondary_sql} AND component_name = %s {$component_action_sql}", $item_id, $component_name ) ); 108 109 // Delete this entry from the user activity cache table and the sitewide cache table 110 $wpdb->query( $wpdb->prepare( "DELETE FROM {$bp->activity->table_name_user_activity_cached} WHERE user_id = %d AND item_id = %d {$secondary_sql} AND component_name = %s {$cached_component_action_sql}", $user_id, $item_id, $component_name ) ); 111 $wpdb->query( $wpdb->prepare( "DELETE FROM {$bp->activity->table_name_sitewide} WHERE item_id = %d {$secondary_sql} AND component_name = %s {$component_action_sql}", $item_id, $component_name ) ); 112 113 return true; 119 120 return $wpdb->query( $wpdb->prepare( "DELETE FROM {$bp->activity->table_name} WHERE user_id = %d AND item_id = %d {$secondary_sql} AND component_name = %s {$cached_component_action_sql}", $user_id, $item_id, $component_name ) ); 121 } 122 123 function delete_by_item_id( $user_id, $component_name, $component_action, $item_id, $secondary_item_id = false ) { 124 return BP_Activity_Activity::delete( $item_id, $component_name, $component_action, $user_id, $secondary_item_id ); 125 } 126 127 function delete_by_activity_id( $activity_id ) { 128 global $bp, $wpdb; 129 130 return $wpdb->query( $wpdb->prepare( "DELETE FROM {$bp->activity->table_name} WHERE id = %d", $activity_id ) ); 131 } 132 133 function delete_by_content( $user_id, $content, $component_name, $component_action ) { 134 global $bp, $wpdb; 135 136 return $wpdb->query( $wpdb->prepare( "DELETE FROM {$bp->activity->table_name} WHERE user_id = %d AND content = %s AND component_name = %s AND component_action = %s", $user_id, $content, $component_name, $component_action ) ); 137 } 138 139 function delete_for_user_by_component( $user_id, $component_name ) { 140 global $bp, $wpdb; 141 142 return $wpdb->query( $wpdb->prepare( "DELETE FROM {$bp->activity->table_name} WHERE user_id = %d AND component_name = %s", $user_id, $component_name ) ); 143 } 144 145 function delete_for_user( $user_id ) { 146 global $wpdb, $bp; 147 148 return $wpdb->query( $wpdb->prepare( "DELETE FROM {$bp->activity->table_name} WHERE user_id = %d", $user_id ) ); 114 149 } 115 150 … … 129 164 130 165 if ( $limit && $page && $max ) 131 $activities = $wpdb->get_results( $wpdb->prepare( "SELECT * FROM {$bp->activity->table_name _user_activity_cached} WHERE user_id = %d AND date_recorded >= FROM_UNIXTIME(%d) $privacy_sql ORDER BY date_recorded DESC $pag_sql", $user_id, $since ) );166 $activities = $wpdb->get_results( $wpdb->prepare( "SELECT * FROM {$bp->activity->table_name} WHERE user_id = %d AND date_recorded >= FROM_UNIXTIME(%d) $privacy_sql ORDER BY date_recorded DESC $pag_sql", $user_id, $since ) ); 132 167 else 133 $activities = $wpdb->get_results( $wpdb->prepare( "SELECT * FROM {$bp->activity->table_name _user_activity_cached} WHERE user_id = %d AND date_recorded >= FROM_UNIXTIME(%d) $privacy_sql ORDER BY date_recorded DESC $pag_sql $max_sql", $user_id, $since ) );134 135 $total_activities = $wpdb->get_var( $wpdb->prepare( "SELECT count(id) FROM {$bp->activity->table_name _user_activity_cached} WHERE user_id = %d AND date_recorded >= FROM_UNIXTIME(%d) $privacy_sql ORDER BY date_recorded DESC $max_sql", $user_id, $since ) );168 $activities = $wpdb->get_results( $wpdb->prepare( "SELECT * FROM {$bp->activity->table_name} WHERE user_id = %d AND date_recorded >= FROM_UNIXTIME(%d) $privacy_sql ORDER BY date_recorded DESC $pag_sql $max_sql", $user_id, $since ) ); 169 170 $total_activities = $wpdb->get_var( $wpdb->prepare( "SELECT count(id) FROM {$bp->activity->table_name} WHERE user_id = %d AND date_recorded >= FROM_UNIXTIME(%d) $privacy_sql ORDER BY date_recorded DESC $max_sql", $user_id, $since ) ); 136 171 137 172 for ( $i = 0; $i < count( $activities ); $i++ ) { … … 173 208 174 209 if ( $limit && $page && $max ) 175 $activities = $wpdb->get_results( $wpdb->prepare( "SELECT DISTINCT user_id, content, primary_link, date_recorded, component_name, component_action FROM {$bp->activity->table_name _sitewide} WHERE user_id IN ({$friend_ids}) AND date_recorded >= FROM_UNIXTIME(%d) ORDER BY date_recorded DESC $pag_sql", $since ) );210 $activities = $wpdb->get_results( $wpdb->prepare( "SELECT DISTINCT user_id, content, primary_link, date_recorded, component_name, component_action FROM {$bp->activity->table_name} WHERE user_id IN ({$friend_ids}) AND date_recorded >= FROM_UNIXTIME(%d) ORDER BY date_recorded DESC $pag_sql", $since ) ); 176 211 else 177 $activities = $wpdb->get_results( $wpdb->prepare( "SELECT DISTINCT user_id, content, primary_link, date_recorded, component_name, component_action FROM {$bp->activity->table_name _sitewide} WHERE user_id IN ({$friend_ids}) AND date_recorded >= FROM_UNIXTIME(%d) ORDER BY date_recorded DESC $pag_sql $max_sql", $since ) );178 179 $total_activities = $wpdb->get_var( $wpdb->prepare( "SELECT DISTINCT count(user_id) FROM {$bp->activity->table_name _sitewide} WHERE user_id IN ({$friend_ids}) AND date_recorded >= FROM_UNIXTIME(%d) ORDER BY date_recorded DESC $max_sql", $since ) );212 $activities = $wpdb->get_results( $wpdb->prepare( "SELECT DISTINCT user_id, content, primary_link, date_recorded, component_name, component_action FROM {$bp->activity->table_name} WHERE user_id IN ({$friend_ids}) AND date_recorded >= FROM_UNIXTIME(%d) ORDER BY date_recorded DESC $pag_sql $max_sql", $since ) ); 213 214 $total_activities = $wpdb->get_var( $wpdb->prepare( "SELECT DISTINCT count(user_id) FROM {$bp->activity->table_name} WHERE user_id IN ({$friend_ids}) AND date_recorded >= FROM_UNIXTIME(%d) ORDER BY date_recorded DESC $max_sql", $since ) ); 180 215 181 216 return array( 'activities' => $activities, 'total' => (int)$total_activities ); … … 190 225 if ( $max ) 191 226 $max_sql = $wpdb->prepare( "LIMIT %d", $max ); 192 193 /* Remove entries that are older than 6 months */194 $wpdb->query( $wpdb->prepare( "DELETE FROM " . $bp->activity->table_name_sitewide . " WHERE DATE_ADD(date_recorded, INTERVAL 6 MONTH) <= NOW()" ) );195 227 196 228 if ( $limit && $page && $max ) 197 $activities = $wpdb->get_results( $wpdb->prepare( "SELECT * FROM {$bp->activity->table_name _sitewide}ORDER BY date_recorded DESC $pag_sql" ) );229 $activities = $wpdb->get_results( $wpdb->prepare( "SELECT * FROM {$bp->activity->table_name} WHERE hide_sitewide = 0 ORDER BY date_recorded DESC $pag_sql" ) ); 198 230 else 199 $activities = $wpdb->get_results( $wpdb->prepare( "SELECT * FROM {$bp->activity->table_name _sitewide}ORDER BY date_recorded DESC $pag_sql $max_sql" ) );200 201 $total_activities = $wpdb->get_var( $wpdb->prepare( "SELECT count(id) FROM {$bp->activity->table_name _sitewide}ORDER BY date_recorded DESC $max_sql" ) );231 $activities = $wpdb->get_results( $wpdb->prepare( "SELECT * FROM {$bp->activity->table_name} WHERE hide_sitewide = 0 ORDER BY date_recorded DESC $pag_sql $max_sql" ) ); 232 233 $total_activities = $wpdb->get_var( $wpdb->prepare( "SELECT count(id) FROM {$bp->activity->table_name} WHERE hide_sitewide = 0 ORDER BY date_recorded DESC $max_sql" ) ); 202 234 203 235 for ( $i = 0; $i < count( $activities ); $i++ ) { … … 228 260 } 229 261 230 function cache_friends_activities( $activity_array ) {231 global $wpdb, $bp;232 233 /* Empty the cache */234 $wpdb->query( "TRUNCATE TABLE {$bp->activity->table_name_loggedin_user_friends_cached}" );235 236 for ( $i = 0; $i < count($activity_array); $i++ ) {237 // Cache that sucka...238 $cached = $wpdb->query( $wpdb->prepare( "INSERT INTO {$bp->activity->table_name_loggedin_user_friends_cached} ( user_id, content, primary_link, component_name, component_action, date_cached, date_recorded ) VALUES ( %d, %s, %s, %s, %s, FROM_UNIXTIME(%d), %s )", $activity_array[$i]['user_id'], $activity_array[$i]['content'], $activity_array[$i]['primary_link'], $activity_array[$i]['component_name'], $activity_array[$i]['component_action'], time(), $activity_array[$i]['date_recorded'] ) );239 }240 241 update_usermeta( $bp->loggedin_user->id, 'bp_activity_friends_last_cached', time() );242 }243 244 function cache_activities( $activity_array, $user_id ) {245 global $wpdb, $bp;246 247 /* Delete cached items older than 30 days for the user */248 $wpdb->query( $wpdb->prepare( "DELETE FROM {$bp->activity->table_name_user_activity_cached} WHERE user_id = %d AND DATE_ADD(date_recorded, INTERVAL 30 DAY) <= NOW()", $user_id ) );249 $wpdb->query( $wpdb->prepare( "DELETE FROM {$bp->activity->table_name_sitewide} WHERE user_id = %d AND DATE_ADD(date_recorded, INTERVAL 30 DAY) <= NOW()", $user_id ) );250 251 for ( $i = 0; $i < count($activity_array); $i++ ) {252 if ( empty( $activity_array[$i]['content'] ) ) continue;253 254 // Cache that sucka...255 $wpdb->query( $wpdb->prepare( "INSERT INTO {$bp->activity->table_name_user_activity_cached} ( user_id, content, item_id, secondary_item_id, primary_link, component_name, component_action, date_cached, date_recorded, is_private ) VALUES ( %d, %s, %d, %d, %s, %s, %s, FROM_UNIXTIME(%d), %s, %d )", $user_id, $activity_array[$i]['content'], $activity_array[$i]['item_id'], $activity_array[$i]['secondary_item_id'], $activity_array[$i]['primary_link'], $activity_array[$i]['component_name'], $activity_array[$i]['component_action'], time(), $activity_array[$i]['date_recorded'], $activity_array[$i]['is_private'] ) );256 257 // Add to the sitewide activity stream258 if ( !$activity_array[$i]['is_private'] && !$activity_array[$i]['no_sitewide_cache'] )259 $wpdb->query( $wpdb->prepare( "INSERT INTO {$bp->activity->table_name_sitewide} ( user_id, content, item_id, secondary_item_id, primary_link, component_name, component_action, date_cached, date_recorded ) VALUES ( %d, %s, %d, %d, %s, %s, %s, FROM_UNIXTIME(%d), %s )", $user_id, $activity_array[$i]['content'], $activity_array[$i]['item_id'], $activity_array[$i]['secondary_item_id'], $activity_array[$i]['primary_link'], $activity_array[$i]['component_name'], $activity_array[$i]['component_action'], time(), $activity_array[$i]['date_recorded'] ) );260 }261 262 update_usermeta( $bp->displayed_user->id, 'bp_activity_last_cached', time() );263 }264 265 function delete_activity_for_user( $user_id ) {266 global $wpdb, $bp;267 268 /* Empty user's activities from the sitewide stream */269 $wpdb->query( $wpdb->prepare( "DELETE FROM {$bp->activity->table_name_sitewide} WHERE user_id = %d", $user_id ) );270 271 /* Empty the user's activity items and cached activity items */272 $wpdb->query( $wpdb->prepare( "DELETE FROM {$bp->activity->table_name_user_activity} WHERE user_id = %d", $user_id ) );273 $wpdb->query( $wpdb->prepare( "DELETE FROM {$bp->activity->table_name_user_activity_cached} WHERE user_id = %d", $user_id ) );274 275 return true;276 }277 278 262 function get_last_updated() { 279 263 global $bp, $wpdb; 280 264 281 return $wpdb->get_var( $wpdb->prepare( "SELECT date_recorded FROM " . $bp->activity->table_name_sitewide . " ORDER BY date_recorded ASC LIMIT 1" ) ); 282 } 283 284 function kill_tables_for_user( $user_id ) { 285 global $bp, $wpdb; 286 287 if ( !$wpdb->get_var( "SHOW TABLES LIKE 'wp_user_{$user_id}_activity'" ) ) 288 return false; 289 290 $wpdb->query( $wpdb->prepare( "DROP TABLE wp_user_{$user_id}_activity" ) ); 291 $wpdb->query( $wpdb->prepare( "DROP TABLE wp_user_{$user_id}_activity_cached" ) ); 292 $wpdb->query( $wpdb->prepare( "DROP TABLE wp_user_{$user_id}_friends_activity_cached" ) ); 293 294 return true; 295 } 296 297 function convert_tables_for_user( $user_id ) { 298 global $bp, $wpdb; 299 300 if ( !$wpdb->get_var( "SHOW TABLES LIKE 'wp_user_{$user_id}_activity'" ) ) 301 return false; 302 303 $activity_items = $wpdb->get_results( $wpdb->prepare( "SELECT * FROM wp_user_{$user_id}_activity" ) ); 304 $activity_cached_items = $wpdb->get_results( $wpdb->prepare( "SELECT * FROM wp_user_{$user_id}_activity_cached" ) ); 305 306 if ( $activity_items ) { 307 foreach ( $activity_items as $activity_item ) { 308 $wpdb->query( $wpdb->prepare( 309 "INSERT INTO {$bp->activity->table_name_user_activity} 310 ( item_id, secondary_item_id, user_id, component_name, component_action, date_recorded, is_private, no_sitewide_cache ) 311 VALUES 312 ( %d, %d, %d, %s, %s, %s, %d, %d )", 313 $activity_item->item_id, $activity_item->secondary_item_id, $user_id, $activity_item->component_name, $activity_item->component_action, $activity_item->date_recorded, $activity_item->is_private, $activity_item->no_sitewide_cache 314 ) ); 315 } 316 } 317 318 if ( $activity_cached_items ) { 319 foreach ( $activity_cached_items as $activity_cached_item ) { 320 $wpdb->query( $wpdb->prepare( 321 "INSERT INTO {$bp->activity->table_name_user_activity_cached} 322 ( content, primary_link, item_id, secondary_item_id, user_id, component_name, component_action, date_recorded, date_cached, is_private ) 323 VALUES 324 ( %s, %s, %d, %d, %d, %s, %s, %s, %s, %d )", 325 $activity_cached_item->content, $activity_cached_item->primary_link, $activity_cached_item->item_id, $activity_cached_item->secondary_item_id, $user_id, $activity_cached_item->component_name, $activity_cached_item->component_action, $activity_cached_item->date_recorded, $activity_cached_item->date_cached, $activity_cached_item->is_private 326 ) ); 327 } 328 } 265 return $wpdb->get_var( $wpdb->prepare( "SELECT date_recorded FROM {$bp->activity->table_name} ORDER BY date_recorded ASC LIMIT 1" ) ); 329 266 } 330 267 }
Note: See TracChangeset
for help on using the changeset viewer.