Index: trunk/extensions/PageTriage/sql/PageTriageLog.sql |
— | — | @@ -0,0 +1,12 @@ |
| 2 | +-- Store the triage log for articles |
| 3 | +CREATE TABLE /*_*/pagetriage_log ( |
| 4 | + ptrl_id int unsigned NOT NULL PRIMARY KEY auto_increment, |
| 5 | + ptrl_page_id int unsigned NOT NULL, |
| 6 | + ptrl_user_id int unsigned NOT NULL, |
| 7 | + ptrl_triaged tinyint unsigned not null default 0, |
| 8 | + ptrl_comment varbinary(255), |
| 9 | + ptrl_timestamp varbinary(14) NOT NULL |
| 10 | +) /*$wgDBTableOptions*/; |
| 11 | + |
| 12 | +CREATE INDEX /*i*/ptrl_page_id_timestamp ON /*_*/pagetriage_log (ptrl_page_id, ptrl_timestamp); |
| 13 | +CREATE INDEX /*i*/ptrl_timestamp ON /*_*/pagetriage_log (ptrl_timestamp); |
Property changes on: trunk/extensions/PageTriage/sql/PageTriageLog.sql |
___________________________________________________________________ |
Added: svn:eol-style |
1 | 14 | + native |
Index: trunk/extensions/PageTriage/includes/PageTriageUtil.php |
— | — | @@ -0,0 +1,138 @@ |
| 2 | +<?php |
| 3 | + |
| 4 | +/** |
| 5 | + * Utility class for PageTriage |
| 6 | + */ |
| 7 | +class PageTriageUtil { |
| 8 | + |
| 9 | + /** |
| 10 | + * Get a list of stat for untriaged articles |
| 11 | + * @return array |
| 12 | + * |
| 13 | + * @Todo - Limit the number of records by a timestamp filter, maybe 30 days etc, |
| 14 | + * depends on the time the triage queue should look back for listview |
| 15 | + */ |
| 16 | + public static function getUntriageArticleStat() { |
| 17 | + global $wgMemc; |
| 18 | + |
| 19 | + $key = wfMemcKey( 'pagetriage', 'untriaged-article', 'stat' ); |
| 20 | + |
| 21 | + $data = $wgMemc->get( $key ); |
| 22 | + if ( $data !== false ) { |
| 23 | + return $data; |
| 24 | + } |
| 25 | + |
| 26 | + $dbr = wfGetDB( DB_SLAVE ); |
| 27 | + |
| 28 | + $res = $dbr->selectRow( |
| 29 | + array( 'pagetriage_page' ), |
| 30 | + array( 'COUNT(ptrp_id) AS total' ), |
| 31 | + array( 'ptrp_triaged' => 0 ) |
| 32 | + ); |
| 33 | + |
| 34 | + $percentile = array( 25, 50, 75, 90, 100 ); |
| 35 | + |
| 36 | + $data = array( 'count' => 0 ); |
| 37 | + |
| 38 | + foreach ( $percentile as $val ) { |
| 39 | + $data['age-' . $val . 'th-percentile'] = false; |
| 40 | + } |
| 41 | + |
| 42 | + if ( $res ) { |
| 43 | + $data['count'] = intval( $res->total ); |
| 44 | + |
| 45 | + // show percentile stat only if there is a certain number of untriaged articles |
| 46 | + if ( $data['count'] > 10 ) { |
| 47 | + foreach ( $percentile as $val ) { |
| 48 | + $data['age-' . $val . 'th-percentile'] = self::estimateArticleAgePercentile( $val, $data['count'] ); |
| 49 | + } |
| 50 | + } |
| 51 | + } |
| 52 | + |
| 53 | + // make it expire in an hour |
| 54 | + $wgMemc->set( $key, $data, 3600 ); |
| 55 | + return $data; |
| 56 | + } |
| 57 | + |
| 58 | + /** |
| 59 | + * Get top page triagers in the past week |
| 60 | + * @param $num int - number of records to retrieve |
| 61 | + * @return array |
| 62 | + */ |
| 63 | + public static function getTopTriager( $num = 5 ) { |
| 64 | + global $wgMemc; |
| 65 | + |
| 66 | + $dbr = wfGetDB( DB_SLAVE ); |
| 67 | + $key = wfMemcKey( 'pagetriage', 'top-triager', 'past-week' ); |
| 68 | + |
| 69 | + $topTriager = $wgMemc->get( $key ); |
| 70 | + if ( $topTriager === false ) { |
| 71 | + $timestamp = wfTimestamp( TS_UNIX ) - 7 * 24 * 60 * 60; // 1 week ago |
| 72 | + |
| 73 | + $res = $dbr->select( |
| 74 | + array( 'pagetriage_log', 'user' ), |
| 75 | + array( 'user_name', 'COUNT(ptrl_id) AS num' ), |
| 76 | + array( 'user_id = ptrl_user_id', 'ptrl_timestamp > ' . $dbr->addQuotes( $dbr->timestamp( $timestamp ) ) ), |
| 77 | + __METHOD__, |
| 78 | + array( 'GROUP BY' => 'user_id', 'ORDER BY' => 'num DESC', 'LIMIT' => $num ) |
| 79 | + ); |
| 80 | + |
| 81 | + $topTriager = iterator_to_array( $res ); |
| 82 | + |
| 83 | + // make it expire in 2 hours |
| 84 | + $wgMemc->set( $key, $topTriager, 7200 ); |
| 85 | + } |
| 86 | + |
| 87 | + return $topTriager; |
| 88 | + } |
| 89 | + |
| 90 | + /** |
| 91 | + * Calculate the age of untriaged articles by percentile |
| 92 | + * @param $percentile int |
| 93 | + * @param $count int |
| 94 | + * @return int|bool |
| 95 | + */ |
| 96 | + private static function estimateArticleAgePercentile( $percentile, $count ) { |
| 97 | + |
| 98 | + if ( !is_int( $percentile ) || $percentile < 1 || $percentile > 100) { |
| 99 | + throw new MWPageTriageUtilInvalidNumberException( 'Invalid percentage number' ); |
| 100 | + } |
| 101 | + |
| 102 | + if ( !is_int( $count ) || $count < 1 ) { |
| 103 | + throw new MWPageTriageUtilInvalidNumberException ( 'Invalid total count' ); |
| 104 | + } |
| 105 | + |
| 106 | + // starting from oldest timestamp if percent is > 50 |
| 107 | + if ( $percentile > 50 ) { |
| 108 | + $percentile = 100 - $percentile; |
| 109 | + $order = 'ASC'; |
| 110 | + } else { |
| 111 | + $order = 'DESC'; |
| 112 | + } |
| 113 | + |
| 114 | + $start = floor( ( $percentile / 100 ) * $count ) - 1; |
| 115 | + |
| 116 | + if ( $start < 0 ) { |
| 117 | + $start = 0; |
| 118 | + } |
| 119 | + |
| 120 | + $dbr = wfGetDB( DB_SLAVE ); |
| 121 | + |
| 122 | + $res = $dbr->selectRow( |
| 123 | + array( 'pagetriage_page' ), |
| 124 | + array( 'ptrp_timestamp' ), |
| 125 | + array( 'ptrp_triaged' => 0 ), |
| 126 | + __METHOD__, |
| 127 | + array( 'ORDER BY' => "ptrp_timestamp $order", 'LIMIT' => '1', 'OFFSET' => $start ) |
| 128 | + ); |
| 129 | + |
| 130 | + if ( $res ) { |
| 131 | + return $res->ptrp_timestamp; |
| 132 | + } else { |
| 133 | + return false; |
| 134 | + } |
| 135 | + } |
| 136 | + |
| 137 | +} |
| 138 | + |
| 139 | +class MWPageTriageUtilInvalidNumberException extends MWException {} |
Property changes on: trunk/extensions/PageTriage/includes/PageTriageUtil.php |
___________________________________________________________________ |
Added: svn:eol-style |
1 | 140 | + native |
Index: trunk/extensions/PageTriage/PageTriage.php |
— | — | @@ -52,6 +52,7 @@ |
53 | 53 | $wgSpecialPages['PageTriage'] = 'SpecialPageTriage'; |
54 | 54 | $wgSpecialPageGroups['PageTriage'] = 'changes'; |
55 | 55 | $wgAutoloadClasses['ArticleMetadata'] = $dir . 'includes/ArticleMetadata.php'; |
| 56 | +$wgAutoloadClasses['PageTriageUtil'] = $dir . 'includes/PageTriageUtil.php'; |
56 | 57 | $wgAutoloadClasses['PageTriageHooks'] = $dir . 'PageTriage.hooks.php'; |
57 | 58 | |
58 | 59 | $wgAutoloadClasses['ApiQueryPageTriage'] = $dir . 'api/ApiQueryPageTriage.php'; |
— | — | @@ -60,6 +61,7 @@ |
61 | 62 | // custom exceptions |
62 | 63 | $wgAutoloadClasses['MWArticleMetadataMissingPageIdException'] = $dir . 'includes/ArticleMetadata.php'; |
63 | 64 | $wgAutoloadClasses['MWArticleMetadataMetaDataOutofBoundException'] = $dir . 'includes/ArticleMetadata.php'; |
| 65 | +$wgAutoloadClasses['MWPageTriageUtilInvalidNumberException'] = $dir . 'includes/PageTriageUtil.php'; |
64 | 66 | |
65 | 67 | // api modules |
66 | 68 | $wgAPIModules['pagetriage'] = 'ApiQueryPageTriage'; |
— | — | @@ -91,6 +93,7 @@ |
92 | 94 | $updater->addExtensionTable( 'pagetriage_tags', $base . '/PageTriageTags.sql' ); |
93 | 95 | $updater->addExtensionTable( 'pagetriage_page_tags', $base . '/PageTriagePageTags.sql' ); |
94 | 96 | $updater->addExtensionTable( 'pagetriage_page', $base . '/PageTriagePage.sql' ); |
| 97 | + $updater->addExtensionTable( 'pagetriage_log', $base . '/PageTriageLog.sql' ); |
95 | 98 | |
96 | 99 | return true; |
97 | 100 | } |