r106696 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r106695‎ | r106696 | r106697 >
Date:20:59, 19 December 2011
Author:awjrichards
Status:ok
Tags:
Comment:
Modified paths:
  • /branches/wmf/1.18wmf1/extensions/ContributionReporting (modified) (history)
  • /branches/wmf/1.18wmf1/extensions/ContributionReporting/ContributionHistory_body.php (modified) (history)
  • /branches/wmf/1.18wmf1/extensions/ContributionReporting/ContributionReporting.i18n.php (modified) (history)
  • /branches/wmf/1.18wmf1/extensions/ContributionReporting/ContributionReporting.php (modified) (history)
  • /branches/wmf/1.18wmf1/extensions/ContributionReporting/ContributionStatistics_body.php (modified) (history)
  • /branches/wmf/1.18wmf1/extensions/ContributionReporting/ContributionTotal_body.php (modified) (history)
  • /branches/wmf/1.18wmf1/extensions/ContributionReporting/ContributionTrackingStatistics_body.php (modified) (history)
  • /branches/wmf/1.18wmf1/extensions/ContributionReporting/DailyTotal_body.php (modified) (history)
  • /branches/wmf/1.18wmf1/extensions/ContributionReporting/FundraiserStatistics_body.php (modified) (history)
  • /branches/wmf/1.18wmf1/extensions/ContributionReporting/PopulateFundraisingStatistics.php (added) (history)
  • /branches/wmf/1.18wmf1/extensions/ContributionReporting/YearlyTotal_body.php (deleted) (history)
  • /branches/wmf/1.18wmf1/extensions/ContributionReporting/patches (added) (history)
  • /branches/wmf/1.18wmf1/extensions/ContributionReporting/patches/public-reporting-summaries.sql (modified) (history)

Diff [purge]

Index: branches/wmf/1.18wmf1/extensions/ContributionReporting/YearlyTotal_body.php
@@ -1,81 +0,0 @@
2 -<?php
3 -/**
4 - * Special Page for Contribution statistics extension
5 - *
6 - * @file
7 - * @ingroup Extensions
8 - */
9 -
10 -class SpecialYearlyTotal extends IncludableSpecialPage {
11 -
12 - protected $sharedMaxAge = 600; // Cache for 10 minutes on the server side
13 - protected $maxAge = 600; // Cache for 10 minutes on the client side
14 -
15 - /* Functions */
16 -
17 - public function __construct() {
18 - parent::__construct( 'YearlyTotal' );
19 - }
20 -
21 - public function execute( $sub ) {
22 - global $wgRequest, $wgOut, $egFundraiserStatisticsFundraisers;
23 -
24 - $js = $wgRequest->getBool( 'js', false );
25 -
26 - $adjustment = $wgRequest->getVal( 'adjustment' );
27 - // Make sure it's a number
28 - if ( is_nan( $adjustment ) ) {
29 - $adjustment = 0;
30 - }
31 -
32 - /* Setup */
33 - $wgOut->disable();
34 - $this->sendHeaders();
35 -
36 - $total = $this->query( $adjustment );
37 -
38 - $content = "wgFundraisingYearlyTotal = $total;";
39 -
40 - if ( $js ) {
41 - echo $content;
42 - } else {
43 - echo $total;
44 - }
45 - }
46 -
47 - /* Private Functions */
48 -
49 - private function query( $adjustment ) {
50 - global $wgMemc, $egFundraiserStatisticsCacheTimeout, $egFundraiserStatisticsFundraisers;
51 -
52 - $currenctFundraiserIndex = count( $egFundraiserStatisticsFundraisers ) - 1;
53 - $year = $egFundraiserStatisticsFundraisers[$currenctFundraiserIndex]['id'];
54 -
55 - $key = wfMemcKey( 'fundraiserstatistics', $year, $adjustment );
56 - $cache = $wgMemc->get( $key );
57 - if ( $cache != false && $cache != -1 ) {
58 - return $cache;
59 - }
60 -
61 - // Get the timestamp for the start of the current fundraiser
62 - // Note: This depends on the fundraisers being listed in chronological order
63 - $start = strtotime( $egFundraiserStatisticsFundraisers[$currenctFundraiserIndex]['start'] );
64 - $start = intval( wfTimestampOrNull( TS_UNIX, $start ) );
65 -
66 - $total = efContributionReportingTotal( $start, $adjustment );
67 - if ( !$total ) $total = 0;
68 -
69 - $wgMemc->set( $key, $total, $egFundraiserStatisticsCacheTimeout );
70 - return $total;
71 - }
72 -
73 - private function sendHeaders() {
74 - global $wgJsMimeType;
75 - header( "Content-type: $wgJsMimeType; charset=utf-8" );
76 - header( "Cache-Control: public, s-maxage=$this->sharedMaxAge, max-age=$this->maxAge" );
77 - }
78 -
79 - public function isListed(){
80 - return false;
81 - }
82 -}
Index: branches/wmf/1.18wmf1/extensions/ContributionReporting/ContributionReporting.php
@@ -11,12 +11,18 @@
1212
1313 $wgContributionReportingBaseURL = "http://meta.wikimedia.org/w/index.php?title=Special:NoticeTemplate/view&template=";
1414
15 -// Override these with appropriate DB settings for the CiviCRM database...
 15+// Override these with appropriate DB settings for the CiviCRM master database...
1616 $wgContributionReportingDBserver = $wgDBserver;
1717 $wgContributionReportingDBuser = $wgDBuser;
1818 $wgContributionReportingDBpassword = $wgDBpassword;
1919 $wgContributionReportingDBname = $wgDBname;
2020
 21+// Override these with appropriate DB settings for the CiviCRM slave database...
 22+$wgContributionReportingReadDBserver = $wgDBserver;
 23+$wgContributionReportingReadDBuser = $wgDBuser;
 24+$wgContributionReportingReadDBpassword = $wgDBpassword;
 25+$wgContributionReportingReadDBname = $wgDBname;
 26+
2127 // And now the tracking database
2228 $wgContributionTrackingDBserver = $wgDBserver;
2329 $wgContributionTrackingDBuser = $wgDBuser;
@@ -26,7 +32,7 @@
2733 $wgExtensionCredits['specialpage'][] = array(
2834 'path' => __FILE__,
2935 'name' => 'Contribution Reporting',
30 - 'url' => 'http://www.mediawiki.org/wiki/Extension:ContributionReporting',
 36+ 'url' => 'https://www.mediawiki.org/wiki/Extension:ContributionReporting',
3137 'author' => array( 'David Strauss', 'Brion Vibber', 'Siebrand Mazeland', 'Trevor Parscal', 'Tomasz Finc' ),
3238 'descriptionmsg' => 'contributionreporting-desc',
3339 );
@@ -41,9 +47,8 @@
4248 $wgAutoloadClasses['SpecialContributionStatistics'] = $dir . 'ContributionStatistics_body.php';
4349 $wgAutoloadClasses['SpecialFundraiserStatistics'] = $dir . 'FundraiserStatistics_body.php';
4450 $wgAutoloadClasses['SpecialContributionTrackingStatistics'] = $dir . 'ContributionTrackingStatistics_body.php';
 51+$wgAutoloadClasses['SpecialDailyTotal'] = $dir . 'DailyTotal_body.php';
4552 /*
46 -$wgAutoloadClasses['SpecialDailyTotal'] = $dir . 'DailyTotal_body.php';
47 -$wgAutoloadClasses['SpecialYearlyTotal'] = $dir . 'YearlyTotal_body.php';
4853 $wgAutoloadClasses['DisabledNotice'] = $dir . 'DisabledNotice_body.php';
4954 */
5055
@@ -52,10 +57,7 @@
5358 $wgSpecialPages['ContributionStatistics'] = 'SpecialContributionStatistics';
5459 $wgSpecialPages['FundraiserStatistics'] = 'SpecialFundraiserStatistics';
5560 $wgSpecialPages['ContributionTrackingStatistics'] = 'SpecialContributionTrackingStatistics';
56 -/*
5761 $wgSpecialPages['DailyTotal'] = 'SpecialDailyTotal';
58 -$wgSpecialPages['YearlyTotal'] = 'SpecialYearlyTotal';
59 -*/
6062
6163 $wgSpecialPageGroups['ContributionHistory'] = 'contribution';
6264 $wgSpecialPageGroups['ContributionTotal'] = 'contribution';
@@ -154,6 +156,8 @@
155157 }
156158
157159 /**
 160+ * Define the contributiontotal magic word
 161+ * Example: {{#contributiontotal:fundraiser=2011|fudgefactor=0}}
158162 * @param $magicWords array
159163 * @param $langCode string
160164 * @return bool
@@ -165,6 +169,7 @@
166170
167171 /**
168172 * Automatically use a local or special database connection for reporting
 173+ * This connection will typically be to the CiviCRM master database
169174 * @return DatabaseMysql
170175 */
171176 function efContributionReportingConnection() {
@@ -186,6 +191,29 @@
187192 }
188193
189194 /**
 195+ * Automatically use a local or special database connection for reporting
 196+ * This connection will typically be to a CiviCRM slave database
 197+ * @return DatabaseMysql
 198+ */
 199+function efContributionReportingReadConnection() {
 200+ global $wgContributionReportingReadDBserver, $wgContributionReportingReadDBname;
 201+ global $wgContributionReportingReadDBuser, $wgContributionReportingReadDBpassword;
 202+
 203+ static $db;
 204+
 205+ if ( !$db ) {
 206+ $db = new DatabaseMysql(
 207+ $wgContributionReportingReadDBserver,
 208+ $wgContributionReportingReadDBuser,
 209+ $wgContributionReportingReadDBpassword,
 210+ $wgContributionReportingReadDBname );
 211+ $db->query( "SET names utf8" );
 212+ }
 213+
 214+ return $db;
 215+}
 216+
 217+/**
190218 * Automatically use a local or special database connection for tracking
191219 * @return DatabaseMysql
192220 */
@@ -208,39 +236,67 @@
209237 }
210238
211239 /**
212 - * Get the total amount of money raised since the start of the fundraiser
213 - * @param $start
214 - * @param $fudgeFactor
215 - * @return string
 240+ * Get the total amount of money raised for a specific fundraiser
 241+ * @param string $fundraiser The ID of the fundraiser to return the current total for
 242+ * @param int $fudgeFactor How much to adjust the total by
 243+ * @return integer
216244 */
217 -function efContributionReportingTotal( $start, $fudgeFactor ) {
218 - $db = efContributionReportingConnection();
 245+function efContributionReportingTotal( $fundraiser, $fudgeFactor = 0 ) {
 246+ global $wgMemc, $egFundraiserStatisticsFundraisers, $egFundraiserStatisticsCacheTimeout;
219247
220 - $sql = 'SELECT ROUND( SUM(converted_amount) ) AS ttl FROM public_reporting';
221 -
222 - if ( $start ) {
223 - $sql .= ' WHERE received >= ' . $db->addQuotes( wfTimestamp( TS_UNIX, $start ) );
 248+ // If a total is cached, use that
 249+ $key = wfMemcKey( 'contributionreportingtotal', $fundraiser, $fudgeFactor );
 250+ $cache = $wgMemc->get( $key );
 251+ if ( $cache != false && $cache != -1 ) {
 252+ return $cache;
224253 }
 254+
 255+ $dbr = wfGetDB( DB_SLAVE );
 256+
 257+ // Find the index number for the requested fundraiser
 258+ $myFundraiserIndex = false;
 259+ foreach ( $egFundraiserStatisticsFundraisers as $fundraiserIndex => $fundraiserArray ) {
 260+ if ( $fundraiserArray['id'] == $fundraiser ) {
 261+ $myFundraiserIndex = $fundraiserIndex;
 262+ break;
 263+ }
 264+ }
 265+ if ( !$myFundraiserIndex ) {
 266+ // If none was found, use the most recent fundraiser
 267+ $myFundraiserIndex = count( $egFundraiserStatisticsFundraisers ) - 1;
 268+ }
 269+
 270+ $myFundraiser = $egFundraiserStatisticsFundraisers[$myFundraiserIndex];
225271
226 - $res = $db->query( $sql );
227 -
228 - $row = $res->fetchRow();
229 -
230 - # Output
231 - $output = $row['ttl'] ? $row['ttl'] : '0';
 272+ // First, try to get the total from the summary table
 273+ $result = $dbr->select(
 274+ 'public_reporting_fundraisers',
 275+ 'round( prf_total ) AS total',
 276+ array( 'prf_id' => $myFundraiser['id'] ),
 277+ __METHOD__
 278+ );
 279+ $row = $dbr->fetchRow( $result );
232280
233 - // Make sure fudge factor is a number
 281+ if ( $row['total'] > 0 ) {
 282+ $total = $row['total'];
 283+ } else {
 284+ $total = 0;
 285+ }
 286+
 287+ // Make sure the fudge factor is a number
234288 if ( is_nan( $fudgeFactor ) ) {
235289 $fudgeFactor = 0;
236290 }
237291
238 - $output += $fudgeFactor;
 292+ // Add the fudge factor to the total
 293+ $total += $fudgeFactor;
239294
240 - return $output;
 295+ $wgMemc->set( $key, $total, $egFundraiserStatisticsCacheTimeout );
 296+ return $total;
241297 }
242298
243299 /**
244 - * @return string
 300+ * @return integer
245301 */
246302 function efContributionReportingTotal_Render() {
247303 $args = func_get_args();
@@ -250,18 +306,18 @@
251307 $start = false;
252308
253309 foreach( $args as $arg ) {
254 - if ( strpos($arg,'=') === false ) {
 310+ if ( strpos( $arg,'=' ) === false ) {
255311 continue;
256312 }
257313
258 - list($key,$value) = explode( '=', trim($arg), 2 );
 314+ list( $key, $value ) = explode( '=', trim( $arg ), 2 );
259315
260 - if ($key == 'fudgefactor') {
 316+ if ( $key == 'fudgefactor' ) {
261317 $fudgeFactor = $value;
262 - } elseif ($key == 'start') {
263 - $start = $value;
 318+ } elseif ( $key == 'fundraiser' ) {
 319+ $fundraiser = $value;
264320 }
265321 }
266322
267 - return efContributionReportingTotal( $start, $fudgeFactor );
 323+ return efContributionReportingTotal( $fundraiser, $fudgeFactor );
268324 }
Property changes on: branches/wmf/1.18wmf1/extensions/ContributionReporting/ContributionReporting.php
___________________________________________________________________
Modified: svn:mergeinfo
269325 Merged /trunk/extensions/ContributionReporting/ContributionReporting.php:r105657,105659,105757,105916,105965,106136,106234,106239,106246,106287,106362
Index: branches/wmf/1.18wmf1/extensions/ContributionReporting/ContributionTrackingStatistics_body.php
@@ -19,6 +19,10 @@
2020
2121 public function execute( $sub ) {
2222 global $wgOut, $wgRequest;
 23+
 24+ # Emergency short cut until this is back in working order
 25+ $wgOut->redirect( SpecialPage::getTitleFor( 'FundraiserStatistics' )->getFullURL() );
 26+ return;
2327
2428 $start = $wgRequest->getIntOrNull( 'start' );
2529 $end = $wgRequest->getIntOrNull( 'end' );
Property changes on: branches/wmf/1.18wmf1/extensions/ContributionReporting/ContributionTrackingStatistics_body.php
___________________________________________________________________
Modified: svn:mergeinfo
2630 Merged /trunk/extensions/ContributionReporting/ContributionTrackingStatistics_body.php:r105965,106362
Index: branches/wmf/1.18wmf1/extensions/ContributionReporting/FundraiserStatistics_body.php
@@ -307,7 +307,7 @@
308308 * Retrieve the donation data from the database
309309 *
310310 * @param boolean $mostRecent Is this query for the most recent fundraiser?
311 - * @param string $start The start date for a fundraiser
 311+ * @param string $start The start date for a fundraiser, e.g. 'Oct 22 2007'
312312 * @param string $end The end date for a fundraiser
313313 * @return an array of results or null
314314 */
@@ -323,31 +323,32 @@
324324 return $cache;
325325 }
326326
327 - // Use database
328 - $dbr = efContributionReportingConnection();
 327+ // Use MediaWiki slave database
 328+ $dbr = wfGetDB( DB_SLAVE );
 329+ // Set timezone to UTC (contribution data will always be in UTC)
 330+ date_default_timezone_set( 'UTC' );
 331+
329332 $conditions = array(
330 - 'received >= ' . $dbr->addQuotes( wfTimestamp( TS_UNIX, strtotime( $start ) ) ),
331 - 'received <= ' . $dbr->addQuotes( wfTimestamp( TS_UNIX, strtotime( $end ) + 24 * 60 * 60 ) ),
332 - 'converted_amount >= ' . $egFundraiserStatisticsMinimum,
333 - 'converted_amount <= ' . $egFundraiserStatisticsMaximum
 333+ 'prd_date >= ' . $dbr->addQuotes( wfTimestamp( TS_DB, strtotime( $start ) ) ),
 334+ 'prd_date <= ' . $dbr->addQuotes( wfTimestamp( TS_DB, strtotime( $end ) ) ),
334335 );
335336
336337 // Get the data for a fundraiser
337 - $select = $dbr->select( 'public_reporting',
 338+ $select = $dbr->select( 'public_reporting_days',
338339 array(
339 - "DATE_FORMAT(FROM_UNIXTIME(received),'%Y-%m-%d')",
340 - 'sum(converted_amount)',
341 - 'count(*)',
342 - 'avg(converted_amount)',
343 - 'max(converted_amount)',
 340+ 'prd_date',
 341+ 'prd_total',
 342+ 'prd_number',
 343+ 'prd_average',
 344+ 'prd_maximum',
344345 ),
345346 $conditions,
346347 __METHOD__,
347348 array(
348 - 'ORDER BY' => 'received',
349 - 'GROUP BY' => "DATE_FORMAT(FROM_UNIXTIME(received),'%Y-%m-%d')"
 349+ 'ORDER BY' => 'prd_date',
350350 )
351351 );
 352+
352353 $result = array();
353354 $ytd = 0;
354355 while ( $row = $dbr->fetchRow( $select ) ) {
Property changes on: branches/wmf/1.18wmf1/extensions/ContributionReporting/FundraiserStatistics_body.php
___________________________________________________________________
Modified: svn:mergeinfo
355356 Merged /trunk/extensions/ContributionReporting/FundraiserStatistics_body.php:r105916,105965,106246,106287,106362
Index: branches/wmf/1.18wmf1/extensions/ContributionReporting/ContributionHistory_body.php
@@ -7,7 +7,7 @@
88 function execute( $language ) {
99 global $wgRequest, $wgOut, $wgLang;
1010
11 - # Emergecny short cut until post donation comments are enabled
 11+ # Emergency short cut until post donation comments are enabled
1212 $wgOut->redirect( SpecialPage::getTitleFor( 'FundraiserStatistics' )->getFullURL() );
1313 return;
1414
@@ -30,7 +30,7 @@
3131 // Paging controls
3232 $newer = $db->selectField( 'public_reporting', 'received',
3333 array_merge(
34 - array( 'received > ' . strtotime( 'July 1st 2008' ) ),
 34+ array( 'received > ' . strtotime( 'July 1st 2011' ) ),
3535 ( $offset !== null ? array( 'received > ' . $offset ) : array() )
3636 ),
3737 __METHOD__,
@@ -42,7 +42,7 @@
4343 );
4444 $older = $db->selectField( 'public_reporting', 'received',
4545 array_merge(
46 - array( 'received > ' . strtotime( 'July 1st 2008' ) ),
 46+ array( 'received > ' . strtotime( 'July 1st 2011' ) ),
4747 ( $offset !== null ? array( 'received <= ' . $offset ) : array() )
4848 ),
4949 __METHOD__,
@@ -85,7 +85,7 @@
8686
8787 if ( $offset == null ) {
8888 $offset = $db->selectField( 'public_reporting', 'received',
89 - array( 'received > ' . strtotime( 'July 1st 2008' ) ),
 89+ array( 'received > ' . strtotime( 'July 1st 2011' ) ),
9090 __METHOD__,
9191 array(
9292 'ORDER BY' => 'received DESC',
@@ -98,7 +98,7 @@
9999
100100 $res = $db->select( 'public_reporting', '*',
101101 array_merge(
102 - array( 'received > ' . strtotime( 'July 1st 2008' ) ),
 102+ array( 'received > ' . strtotime( 'July 1st 2011' ) ),
103103 ( $offset !== null ? array( 'received <= ' . $offset ) : array() )
104104 ),
105105 __METHOD__,
Property changes on: branches/wmf/1.18wmf1/extensions/ContributionReporting/ContributionHistory_body.php
___________________________________________________________________
Modified: svn:mergeinfo
106106 Merged /trunk/extensions/ContributionReporting/ContributionHistory_body.php:r105965,106362
Index: branches/wmf/1.18wmf1/extensions/ContributionReporting/PopulateFundraisingStatistics.php
@@ -0,0 +1,308 @@
 2+<?php
 3+
 4+$IP = getenv( 'MW_INSTALL_PATH' );
 5+if ( $IP === false ) {
 6+ $IP = dirname( __FILE__ ) . '/../..';
 7+}
 8+require( "$IP/maintenance/Maintenance.php" );
 9+
 10+class PopulateFundraisingStatistics extends Maintenance {
 11+ /**
 12+ * DB slave
 13+ * @var object
 14+ */
 15+ protected $dbr;
 16+
 17+ /**
 18+ * DB master
 19+ * @var object
 20+ */
 21+ protected $dbw;
 22+
 23+ /**
 24+ * Valid operations and their execution methods for this script to perform
 25+ *
 26+ * Operations are passed in as options during run-time - only valid options,
 27+ * which are defined here, can be executed. Valid operations are mapped here
 28+ * to a corresponding method ( array( 'operation' => 'method' ))
 29+ * @var array
 30+ */
 31+ protected $operation_map = array(
 32+ 'populatedays' => 'populateDays',
 33+ 'populatefundraisers' => 'populateFundraisers',
 34+ 'updatedays' => 'updateDays',
 35+ );
 36+
 37+ /**
 38+ * Operations to execute
 39+ * @var array
 40+ */
 41+ public $operations = array();
 42+
 43+ public function __construct() {
 44+ parent::__construct();
 45+ $this->mDescription = "Populates the public reporting summary tables";
 46+
 47+ $this->addOption( 'op', 'The ContributionReporting stats gathering operation to run (e.g. "updatedays"). Can specify multiple operations, separated by comma.', true, true );
 48+ }
 49+
 50+ /**
 51+ * Bootstrap this maintenance script
 52+ *
 53+ * Performs operations necessary for this maintenance script to run which
 54+ * cannot or do not make sense to run in the constructor.
 55+ */
 56+ public function bootstrap() {
 57+ /**
 58+ * Set user-specified operations to perform
 59+ */
 60+ $operations = explode( ',', $this->getOption( 'op' ) );
 61+ // Check sanity of specified operations
 62+ if ( !$this->checkOperations( $operations ) ) {
 63+ $this->error( 'Invalid operation specified.', true );
 64+ } else {
 65+ $this->operations = $operations;
 66+ }
 67+
 68+ // Set database objects
 69+ $this->dbr = wfGetDB( DB_SLAVE );
 70+ $this->dbw = wfGetDB( DB_MASTER );
 71+ $this->dbpr = efContributionReportingReadConnection();
 72+
 73+ // Set timezone to UTC (contribution data will always be in UTC)
 74+ date_default_timezone_set( 'UTC' );
 75+ }
 76+
 77+ /**
 78+ * Check whether or not specified operations are valid.
 79+ *
 80+ * A specified operation is considered valid if it exists
 81+ * as a key in the operation map.
 82+ *
 83+ * @param array $ops An array of operations to check
 84+ * @return bool
 85+ */
 86+ public function checkOperations( array $ops ) {
 87+ foreach ( $ops as $operation ) {
 88+ if ( !isset( $this->operation_map[ $operation ] ) ) {
 89+ return false;
 90+ }
 91+ }
 92+ return true;
 93+ }
 94+
 95+ public function execute() {
 96+ // finish bootstrapping the script
 97+ $this->bootstrap();
 98+
 99+ // execute requested operations
 100+ foreach ( $this->operations as $operation ) {
 101+ $method = $this->operation_map[ $operation ];
 102+ $this->$method();
 103+ }
 104+ }
 105+
 106+ /**
 107+ * Populate the donation stats for every day
 108+ *
 109+ * Note that these summaries exclude amounts that are not between the mimumum and maximum
 110+ * donation amounts. This is because every once in a while we have to condense multiple
 111+ * donations that may span several days into a single donation for CiviCRM consumption.
 112+ */
 113+ public function populateDays() {
 114+ global $egFundraiserStatisticsMinimum, $egFundraiserStatisticsMaximum;
 115+
 116+ $begin = time();
 117+ $records = 0;
 118+ $insertArray = array();
 119+ $this->output( "Writing data to public_reporting_days...\n" );
 120+
 121+ $conditions = array(
 122+ 'converted_amount >= ' . intval( $egFundraiserStatisticsMinimum ),
 123+ 'converted_amount <= ' . intval( $egFundraiserStatisticsMaximum )
 124+ );
 125+
 126+ // Get the data for a fundraiser
 127+ $result = $this->dbpr->select( 'public_reporting',
 128+ array(
 129+ "DATE_FORMAT( FROM_UNIXTIME( received ),'%Y-%m-%d' ) AS date",
 130+ 'sum( converted_amount ) AS total',
 131+ 'count( * ) AS number',
 132+ 'avg( converted_amount ) AS average',
 133+ 'max( converted_amount ) AS maximum',
 134+ ),
 135+ $conditions,
 136+ __METHOD__,
 137+ array(
 138+ 'ORDER BY' => 'received',
 139+ 'GROUP BY' => "DATE_FORMAT( FROM_UNIXTIME( received ),'%Y-%m-%d' )"
 140+ )
 141+ );
 142+
 143+ while ( $row = $this->dbpr->fetchRow( $result ) ) {
 144+ // Add it to the insert array
 145+ $insertArray[] = array(
 146+ 'prd_date' => $row['date'],
 147+ 'prd_total' => $row['total'],
 148+ 'prd_number' => $row['number'],
 149+ 'prd_average' => $row['average'],
 150+ 'prd_maximum' => $row['maximum'],
 151+ 'prd_insert_timestamp' => time(),
 152+ );
 153+ $records++;
 154+ }
 155+
 156+ if ( $records > 0 ) {
 157+ // Empty the table of previous totals
 158+ $res = $this->dbw->delete( 'public_reporting_days', array( 1 ) );
 159+ // Insert the new totals
 160+ $res = $this->dbw->insert( 'public_reporting_days', $insertArray, __METHOD__ );
 161+ // Wait for the databases to sync
 162+ wfWaitForSlaves();
 163+ }
 164+
 165+ $lag = time() - $begin;
 166+ $this->output( "Inserted " . $records . " rows. ($lag seconds)\n" );
 167+ $this->output( "Done.\n" );
 168+ }
 169+
 170+ /**
 171+ * Populate the cumulative donation stats for all fundraisers
 172+ *
 173+ * Note that we do not build these stats from the daily summaries since the summaries exclude
 174+ * amounts that are not between the minumum and maximum donation amounts.
 175+ */
 176+ public function populateFundraisers() {
 177+ global $egFundraiserStatisticsFundraisers;
 178+
 179+ $begin = time();
 180+ $records = 0;
 181+ $insertArray = array();
 182+ $this->output( "Writing data to public_reporting_fundraisers...\n" );
 183+ foreach ( $egFundraiserStatisticsFundraisers as $fundraiser ) {
 184+
 185+ $conditions = array(
 186+ 'received >= ' . $this->dbpr->addQuotes( wfTimestamp( TS_UNIX, strtotime( $fundraiser['start'] ) ) ),
 187+ 'received <= ' . $this->dbpr->addQuotes( wfTimestamp( TS_UNIX, strtotime( $fundraiser['end'] ) + 24 * 60 * 60 ) ),
 188+ );
 189+
 190+ // Get the total for a fundraiser
 191+ $result = $this->dbpr->select(
 192+ 'public_reporting',
 193+ array(
 194+ 'sum( converted_amount ) AS total',
 195+ 'count( * ) AS number',
 196+ 'avg( converted_amount ) AS average',
 197+ 'max( converted_amount ) AS maximum',
 198+ ),
 199+ $conditions,
 200+ __METHOD__
 201+ );
 202+ $row = $this->dbpr->fetchRow( $result );
 203+
 204+ // Add it to the insert array
 205+ $insertArray[] = array(
 206+ 'prf_id' => $fundraiser['id'],
 207+ 'prf_total' => $row['total'],
 208+ 'prf_number' => $row['number'],
 209+ 'prf_average' => $row['average'],
 210+ 'prf_maximum' => $row['maximum'],
 211+ 'prf_insert_timestamp' => time(),
 212+ );
 213+
 214+ $records++;
 215+ }
 216+ if ( $records > 0 ) {
 217+ // Empty the table of previous totals
 218+ $res = $this->dbw->delete( 'public_reporting_fundraisers', array( 1 ) );
 219+ // Insert the new totals
 220+ $res = $this->dbw->insert( 'public_reporting_fundraisers', $insertArray, __METHOD__ );
 221+ // Wait for the databases to sync
 222+ wfWaitForSlaves();
 223+ }
 224+ $lag = time() - $begin;
 225+ $this->output( "Inserted " . $records . " rows. ($lag seconds)\n" );
 226+ $this->output( "Done.\n" );
 227+ }
 228+
 229+ /**
 230+ * Populate the donation stats for every day of the current fundraiser
 231+ *
 232+ * Note that if you are running more than one fundraiser at once, you'll want to use
 233+ * populateDays instead of updateDays.
 234+ * Note that these summaries exclude amounts that are not between the mimumum and maximum
 235+ * donation amounts. This is because every once in a while we have to condense multiple
 236+ * donations that may span several days into a single donation for CiviCRM consumption.
 237+ */
 238+ public function updateDays() {
 239+ global $egFundraiserStatisticsFundraisers, $egFundraiserStatisticsMinimum, $egFundraiserStatisticsMaximum;
 240+
 241+ $mostRecentFundraiser = end( $egFundraiserStatisticsFundraisers );
 242+ $start = $mostRecentFundraiser['start'];
 243+ $end = $mostRecentFundraiser['end'];
 244+ $begin = time();
 245+ $records = 0;
 246+ $insertArray = array();
 247+ $this->output( "Writing data to public_reporting_days...\n" );
 248+
 249+ $conditions = array(
 250+ 'received >= ' . $this->dbpr->addQuotes( wfTimestamp( TS_UNIX, strtotime( $start ) ) ),
 251+ 'received <= ' . $this->dbpr->addQuotes( wfTimestamp( TS_UNIX, strtotime( $end ) + 24 * 60 * 60 ) ),
 252+ 'converted_amount >= ' . $egFundraiserStatisticsMinimum,
 253+ 'converted_amount <= ' . $egFundraiserStatisticsMaximum
 254+ );
 255+
 256+ // Get the data for a fundraiser
 257+ $result = $this->dbpr->select( 'public_reporting',
 258+ array(
 259+ "DATE_FORMAT( FROM_UNIXTIME( received ),'%Y-%m-%d' ) AS date",
 260+ 'sum( converted_amount ) AS total',
 261+ 'count( * ) AS number',
 262+ 'avg( converted_amount ) AS average',
 263+ 'max( converted_amount ) AS maximum',
 264+ ),
 265+ $conditions,
 266+ __METHOD__,
 267+ array(
 268+ 'ORDER BY' => 'received',
 269+ 'GROUP BY' => "DATE_FORMAT( FROM_UNIXTIME( received ),'%Y-%m-%d' )"
 270+ )
 271+ );
 272+
 273+ while ( $row = $this->dbpr->fetchRow( $result ) ) {
 274+ // Add it to the insert array
 275+ $insertArray[] = array(
 276+ 'prd_date' => $row['date'],
 277+ 'prd_total' => $row['total'],
 278+ 'prd_number' => $row['number'],
 279+ 'prd_average' => $row['average'],
 280+ 'prd_maximum' => $row['maximum'],
 281+ 'prd_insert_timestamp' => time(),
 282+ );
 283+ $records++;
 284+ }
 285+
 286+ if ( $records > 0 ) {
 287+ // Empty the table of previous totals for this fundraiser
 288+ $res = $this->dbw->delete(
 289+ 'public_reporting_days',
 290+ array(
 291+ 'prd_date >= ' . $this->dbpr->addQuotes( wfTimestamp( TS_DB, strtotime( $start ) ) ),
 292+ 'prd_date <= ' . $this->dbpr->addQuotes( wfTimestamp( TS_DB, strtotime( $end ) ) ),
 293+ )
 294+ );
 295+ // Insert the new totals
 296+ $res = $this->dbw->insert( 'public_reporting_days', $insertArray, __METHOD__ );
 297+ // Wait for the databases to sync
 298+ wfWaitForSlaves();
 299+ }
 300+
 301+ $lag = time() - $begin;
 302+ $this->output( "Updated " . $records . " rows. ($lag seconds)\n" );
 303+ $this->output( "Done.\n" );
 304+ }
 305+
 306+}
 307+
 308+$maintClass = "PopulateFundraisingStatistics";
 309+require_once( DO_MAINTENANCE );
Property changes on: branches/wmf/1.18wmf1/extensions/ContributionReporting/PopulateFundraisingStatistics.php
___________________________________________________________________
Added: svn:eol-style
1310 + native
Index: branches/wmf/1.18wmf1/extensions/ContributionReporting/ContributionTotal_body.php
@@ -1,25 +1,35 @@
22 <?php
33
4 -class ContributionTotal extends SpecialPage {
 4+class ContributionTotal extends UnlistedSpecialPage {
 5+
 6+ protected $sharedMaxAge = 300; // Cache for 5 minutes on the server side
 7+ protected $maxAge = 300; // Cache for 5 minutes on the client side
 8+
59 function __construct() {
610 parent::__construct( 'ContributionTotal' );
711 }
812
913 function execute( $par ) {
10 - global $wgRequest, $wgOut;
 14+ global $wgRequest, $wgOut, $egFundraiserStatisticsFundraisers;
1115
1216 wfLoadExtensionMessages( 'ContributionReporting' );
1317
1418 $this->setHeaders();
1519
16 - # Get request data from, e.g.
17 - $start = intval( wfTimestampOrNull( TS_UNIX, $wgRequest->getVal( 'start' ) ) );
 20+ // Get request data
 21+ $fundraiserId = $wgRequest->getText( 'fundraiser' );
1822 $action = $wgRequest->getText( 'action' );
19 - $fudgeFactor = $wgRequest->getInt( 'fudgefactor' );
 23+ $fudgeFactor = $wgRequest->getInt( 'adjustment' );
 24+
 25+ // If no fundraiser was specified, use the most recent
 26+ if ( !$fundraiserId ) {
 27+ $mostRecentFundraiser = end( $egFundraiserStatisticsFundraisers );
 28+ $fundraiserId = $mostRecentFundraiser['id'];
 29+ }
2030
21 - $output = efContributionReportingTotal( $start, $fudgeFactor );
 31+ $output = efContributionReportingTotal( $fundraiserId, $fudgeFactor );
2232
23 - header( 'Cache-Control: max-age=300,s-maxage=300' );
 33+ header( "Cache-Control: max-age=$this->maxAge,s-maxage=$this->sharedMaxAge" );
2434 if ( $action == 'raw' ) {
2535 $wgOut->disable();
2636 echo $output;
Property changes on: branches/wmf/1.18wmf1/extensions/ContributionReporting/ContributionTotal_body.php
___________________________________________________________________
Modified: svn:mergeinfo
2737 Merged /trunk/extensions/ContributionReporting/ContributionTotal_body.php:r105659,105757,105916,105965
Index: branches/wmf/1.18wmf1/extensions/ContributionReporting/patches/public-reporting-summaries.sql
@@ -0,0 +1,21 @@
 2+-- Create summary tables for fundraising statistics
 3+
 4+CREATE TABLE IF NOT EXISTS /*$wgDBprefix*/public_reporting_fundraisers (
 5+ `prf_id` varchar(32) NOT NULL,
 6+ `prf_total` decimal(14,4) unsigned NOT NULL DEFAULT '0.0000',
 7+ `prf_number` int(11) NOT NULL DEFAULT '0',
 8+ `prf_average` decimal(8,4) NOT NULL DEFAULT '0.0000',
 9+ `prf_maximum` decimal(11,4) NOT NULL DEFAULT '0.0000',
 10+ `prf_insert_timestamp` int(10) NOT NULL,
 11+ PRIMARY KEY (prf_id)
 12+) /*$wgDBTableOptions*/;
 13+
 14+CREATE TABLE IF NOT EXISTS /*$wgDBprefix*/public_reporting_days (
 15+ `prd_date` date NOT NULL,
 16+ `prd_total` decimal(14,4) unsigned NOT NULL DEFAULT '0.0000',
 17+ `prd_number` int(11) NOT NULL DEFAULT '0',
 18+ `prd_average` decimal(8,4) unsigned NOT NULL DEFAULT '0.0000',
 19+ `prd_maximum` decimal(11,4) unsigned NOT NULL DEFAULT '0.0000',
 20+ `prd_insert_timestamp` int(10) NOT NULL,
 21+ PRIMARY KEY (prd_date)
 22+) /*$wgDBTableOptions*/;
Property changes on: branches/wmf/1.18wmf1/extensions/ContributionReporting/patches/public-reporting-summaries.sql
___________________________________________________________________
Added: svn:eol-style
123 + native
Index: branches/wmf/1.18wmf1/extensions/ContributionReporting/DailyTotal_body.php
@@ -6,13 +6,11 @@
77 * @ingroup Extensions
88 */
99
10 -class SpecialDailyTotal extends IncludableSpecialPage {
 10+class SpecialDailyTotal extends UnlistedSpecialPage {
1111
12 - protected $sharedMaxAge = 600; // Cache for 10 minutes on the server side
13 - protected $maxAge = 600; // Cache for 10 minutes on the client side
 12+ protected $sharedMaxAge = 300; // Cache for 5 minutes on the server side
 13+ protected $maxAge = 300; // Cache for 5 minutes on the client side
1414
15 - /* Functions */
16 -
1715 public function __construct() {
1816 parent::__construct( 'DailyTotal' );
1917 }
@@ -20,13 +18,12 @@
2119 public function execute( $sub ) {
2220 global $wgRequest, $wgOut;
2321
24 - $js = $wgRequest->getBool( 'js', false );
25 -
 22+ $this->setHeaders();
 23+
 24+ // Get request data
 25+ $action = $wgRequest->getText( 'action' );
 26+ $fudgeFactor = $wgRequest->getInt( 'adjustment' );
2627 $timezone = $wgRequest->getText( 'timezone', '0' );
27 -
28 - /* Setup */
29 - $wgOut->disable();
30 - $this->sendHeaders();
3128
3229 $zoneList = array (
3330 '-12' => array( 'name' => 'Kwajalein', 'offset' => '-12:00' ),
@@ -79,64 +76,68 @@
8077 }
8178
8279 $setTimeZone = date_default_timezone_set( $timeZoneName );
83 - $start = date( 'Y-m-d' ); // Get the current date in the requested timezone
84 - $total = $this->query( $timeZoneOffset, $start );
85 -
86 - $content = "wgFundraisingDailyTotal = $total;";
87 -
88 - if ( $js ) {
89 - echo $content;
 80+ $today = date( 'Y-m-d' ); // Get the current date in the requested timezone
 81+ $output = $this->getTodaysTotal( $timeZoneOffset, $today, $fudgeFactor );
 82+
 83+ header( "Cache-Control: max-age=$this->maxAge,s-maxage=$this->sharedMaxAge" );
 84+ if ( $action == 'raw' ) {
 85+ $wgOut->disable();
 86+ echo $output;
9087 } else {
91 - echo $total;
 88+ $wgOut->setRobotpolicy( 'noindex,nofollow' );
 89+ $wgOut->addHTML( $output );
9290 }
9391 }
9492
9593 /* Private Functions */
9694
97 - private function query( $timeZoneOffset, $start ) {
 95+ /**
 96+ * Get the total amount of money raised for today
 97+ * @param string $timeZoneOffset The timezone to request the total for
 98+ * @param string $today The current date in the requested time zone, e.g. '2011-12-16'
 99+ * @param int $fudgeFactor How much to adjust the total by
 100+ * @return integer
 101+ */
 102+ private function getTodaysTotal( $timeZoneOffset, $today, $fudgeFactor = 0 ) {
98103 global $wgMemc, $egFundraiserStatisticsMinimum, $egFundraiserStatisticsMaximum, $egFundraiserStatisticsCacheTimeout;
99104
100 - $key = wfMemcKey( 'fundraiserstatistics', $timeZoneOffset, $start );
 105+ // Delete this block once there is timezone support in the populating script
 106+ $setTimeZone = date_default_timezone_set( 'UTC' );
 107+ $today = date( 'Y-m-d' ); // Get the current date in UTC
 108+ $timeZoneOffset = '+00:00';
 109+
 110+ $key = wfMemcKey( 'fundraiserdailytotal', $timeZoneOffset, $today, $fudgeFactor );
101111 $cache = $wgMemc->get( $key );
102112 if ( $cache != false && $cache != -1 ) {
103113 return $cache;
104114 }
105115
106 - // We're only interested in donations from the past 2 days at most
107 - $recentTime = time() - 60 * 60 * 48;
 116+ // Use MediaWiki slave database
 117+ $dbr = wfGetDB( DB_SLAVE );
108118
109 - // Use database
110 - $dbr = efContributionReportingConnection();
111 - #$dbr = wfGetDB( DB_MASTER );
112 - $conditions = array(
113 - 'received > ' . $recentTime,
114 - 'converted_amount >= ' . $egFundraiserStatisticsMinimum,
115 - 'converted_amount <= ' . $egFundraiserStatisticsMaximum,
116 - "DATE_FORMAT(CONVERT_TZ(FROM_UNIXTIME(received),'+00:00','$timeZoneOffset'),'%Y-%m-%d') = '$start'"
117 - );
118 -
119 - $select = $dbr->select( 'public_reporting',
120 - array(
121 - 'sum(converted_amount)'
122 - ),
123 - $conditions,
 119+ $result = $dbr->select(
 120+ 'public_reporting_days',
 121+ 'round( prd_total ) AS total',
 122+ array( 'prd_date' => $today ),
124123 __METHOD__
125124 );
126 - $row = $dbr->fetchRow( $select );
127 - $total = $row['sum(converted_amount)'];
128 - if ( !$total ) $total = 0;
 125+ $row = $dbr->fetchRow( $result );
129126
 127+ if ( $row['total'] > 0 ) {
 128+ $total = $row['total'];
 129+ } else {
 130+ $total = 0;
 131+ }
 132+
 133+ // Make sure the fudge factor is a number
 134+ if ( is_nan( $fudgeFactor ) ) {
 135+ $fudgeFactor = 0;
 136+ }
 137+
 138+ // Add the fudge factor to the total
 139+ $total += $fudgeFactor;
 140+
130141 $wgMemc->set( $key, $total, $egFundraiserStatisticsCacheTimeout );
131142 return $total;
132143 }
133 -
134 - private function sendHeaders() {
135 - global $wgJsMimeType;
136 - header( "Content-type: $wgJsMimeType; charset=utf-8" );
137 - header( "Cache-Control: public, s-maxage=$this->sharedMaxAge, max-age=$this->maxAge" );
138 - }
139 -
140 - public function isListed(){
141 - return false;
142 - }
143144 }
Index: branches/wmf/1.18wmf1/extensions/ContributionReporting/ContributionReporting.i18n.php
@@ -15,6 +15,7 @@
1616 // ContributionReporting and ContributionTotal
1717 'contributionreporting-desc' => 'Live reporting on the Wikimedia fundraiser',
1818 'contributiontotal' => 'Contribution total',
 19+ 'dailytotal' => 'Daily total',
1920
2021 'contribstats-header' => '',
2122 'contribstats-footer' => '',
Property changes on: branches/wmf/1.18wmf1/extensions/ContributionReporting/ContributionReporting.i18n.php
___________________________________________________________________
Modified: svn:mergeinfo
2223 Merged /trunk/extensions/ContributionReporting/ContributionReporting.i18n.php:r105965
Index: branches/wmf/1.18wmf1/extensions/ContributionReporting/ContributionStatistics_body.php
@@ -24,6 +24,11 @@
2525
2626 public function execute( $sub ) {
2727 global $wgOut,$egContributionStatisticsViewDays;
 28+
 29+ # Emergency short cut until this can be changed to use cron-generated data
 30+ # These queries are too expensive to run on demand.
 31+ $wgOut->redirect( SpecialPage::getTitleFor( 'FundraiserStatistics' )->getFullURL() );
 32+ return;
2833
2934 $this->evalDateRange();
3035
Property changes on: branches/wmf/1.18wmf1/extensions/ContributionReporting/ContributionStatistics_body.php
___________________________________________________________________
Modified: svn:mergeinfo
3136 Merged /trunk/extensions/ContributionReporting/ContributionStatistics_body.php:r105965,106362
Property changes on: branches/wmf/1.18wmf1/extensions/ContributionReporting
___________________________________________________________________
Modified: svn:mergeinfo
3237 Merged /trunk/extensions/ContributionReporting:r105641,105657,105659,105757,105916,105965,106136,106234,106239,106246,106287,106362

Past revisions this follows-up on

RevisionCommit summaryAuthorDate
r105145rewriting FundraisingStatistics to use 1 query instead of 6, and heavily cach...kaldari02:12, 5 December 2011
r105454make sure fudge factor is number (again) to be safekaldari19:40, 7 December 2011
r105641an initial implementation of a stats summary system. not yet integrated into ...kaldari02:24, 9 December 2011
r105657a really gosh darn useful commentkaldari06:50, 9 December 2011
r105659make parserfunction based on fundraiser ID instead of start time, start using...kaldari08:04, 9 December 2011
r105757svn:eol-style nativeialex09:19, 10 December 2011
r105916updating FundraisingStatistics to use summary tablekaldari19:09, 12 December 2011
r105965making sure nothing touches the public reporting table except the cron job, r...kaldari01:15, 13 December 2011
r106136Update a butt-ton of extension about URLs to point to https://www.mediawiki.org/brion23:49, 13 December 2011
r106234follow-up to r105641 - better db syncing, using primary keys, etckaldari19:30, 14 December 2011
r106239follow-up to r105659, only connect to db when necessary, use better condition...kaldari20:08, 14 December 2011
r106246follow-up to r105965 - better condition statementkaldari21:40, 14 December 2011
r106287follow-up to r106246 - fixing syntax errorskaldari00:24, 15 December 2011
r106362reorganizing how were connecting to the databases, fixing spelling of emergencykaldari20:04, 15 December 2011

Status & tagging log