Index: trunk/extensions/SelectionSifter/schema/log.sql |
— | — | @@ -0,0 +1,34 @@ |
| 2 | +-- Replace /*_*/ with the proper prefix |
| 3 | +-- Replace /*$wgDBTableOptions*/ with the correct options |
| 4 | + |
| 5 | +CREATE TABLE IF NOT EXISTS /*_*/assessment_changelog ( |
| 6 | + l_project varchar(63) not null, |
| 7 | + -- project name |
| 8 | + |
| 9 | + l_namespace int unsigned not null, |
| 10 | + -- article namespace |
| 11 | + |
| 12 | + l_article varchar(255) not null, |
| 13 | + -- article name |
| 14 | + |
| 15 | + l_action varchar(20) character set ascii not null, |
| 16 | + -- type of log entry (e.g. 'quality') |
| 17 | + |
| 18 | + l_timestamp binary(14) not null, |
| 19 | + -- timestamp when log entry was added |
| 20 | + |
| 21 | + l_old varchar(63), |
| 22 | + -- old value (e.g. B-Class) |
| 23 | + |
| 24 | + l_new varchar(63), |
| 25 | + -- new value (e.g. GA-Class) |
| 26 | + |
| 27 | + l_revision_timestamp binary(20) not null, |
| 28 | + -- timestamp when page was edited |
| 29 | + -- a wiki-format timestamp |
| 30 | + |
| 31 | + primary key (l_project, l_namespace, l_article, l_action, l_timestamp), |
| 32 | + key (l_article, l_namespace) |
| 33 | +) /*$wgDBTableOptions*/; |
| 34 | + |
| 35 | +CREATE INDEX /*i*/l_project ON /*_*/assessment_changelog (l_project); |
Property changes on: trunk/extensions/SelectionSifter/schema/log.sql |
___________________________________________________________________ |
Added: svn:eol-style |
1 | 36 | + native |
Index: trunk/extensions/SelectionSifter/schema/project_stats.sql |
— | — | @@ -0,0 +1,49 @@ |
| 2 | +-- Replace /*_*/ with the proper prefix |
| 3 | +-- Replace /*$wgDBTableOptions*/ with the correct options |
| 4 | + |
| 5 | +CREATE TABLE IF NOT EXISTS /*_*/project_stats ( |
| 6 | + |
| 7 | + ps_project varchar(63) not null, |
| 8 | + -- project name |
| 9 | + |
| 10 | + ps_timestamp binary(14) not null, |
| 11 | + -- last time project data was updated |
| 12 | + |
| 13 | + ps_quality varchar(63) not null, |
| 14 | + -- quality assessment. lowercase. |
| 15 | + -- possible values: fa, a, ga, b, b1, b2, b3, b4, b5, b6, c, start, stub, fl, l, unclassified |
| 16 | + |
| 17 | + ps_count int unsigned default 0, |
| 18 | + -- how many pages are assessed in project |
| 19 | + |
| 20 | + ps_top_icount int unsigned default 0, |
| 21 | + -- how many pages are assessed in project to be top importance |
| 22 | + |
| 23 | + ps_high_icount int unsigned default 0, |
| 24 | + -- how many pages are assessed in project to be high importance |
| 25 | + |
| 26 | + ps_mid_icount int unsigned default 0, |
| 27 | + -- how many pages are assessed in project to be mid importance |
| 28 | + |
| 29 | + ps_low_icount int unsigned default 0, |
| 30 | + -- how many pages are assessed in project to be low importance |
| 31 | + |
| 32 | + ps_bottom_icount int unsigned default 0, |
| 33 | + -- how many pages are assessed in project to be bottom importance |
| 34 | + |
| 35 | + ps_no_icount int unsigned default 0, |
| 36 | + -- how many pages are assessed in project to be of no importance |
| 37 | + |
| 38 | + ps_unclassified_icount int unsigned default 0, |
| 39 | + -- how many pages are assessed in project without a classified importance |
| 40 | + |
| 41 | + ps_qcount int unsigned default 0, |
| 42 | + -- how many pages have quality assessments in the project |
| 43 | + |
| 44 | + ps_icount int unsigned default 0, |
| 45 | + -- how many pages have importance assessments in the project |
| 46 | + |
| 47 | + primary key (ps_project, ps_quality) |
| 48 | +) /*$wgDBTableOptions*/; |
| 49 | + |
| 50 | +CREATE INDEX /*i*/ps_project ON /*_*/project_stats (ps_project); |
Property changes on: trunk/extensions/SelectionSifter/schema/project_stats.sql |
___________________________________________________________________ |
Added: svn:eol-style |
1 | 51 | + native |
Index: trunk/extensions/SelectionSifter/schema/ratings.sql |
— | — | @@ -0,0 +1,33 @@ |
| 2 | +-- Replace /*_*/ with the proper prefix |
| 3 | +-- Replace /*$wgDBTableOptions*/ with the correct options |
| 4 | + |
| 5 | +CREATE TABLE IF NOT EXISTS /*_*/ratings ( |
| 6 | + r_project varchar(63) not null, |
| 7 | + -- project name |
| 8 | + |
| 9 | + r_namespace int unsigned not null, |
| 10 | + -- article namespace |
| 11 | + |
| 12 | + r_article varchar(255) not null, |
| 13 | + -- article title |
| 14 | + |
| 15 | + r_quality varchar(63), |
| 16 | + -- quality rating |
| 17 | + |
| 18 | + r_quality_timestamp binary(20), |
| 19 | + -- time when quality rating was assigned |
| 20 | + -- NOTE: a revid can be obtained from timestamp via API |
| 21 | + -- a wiki-format timestamp |
| 22 | + |
| 23 | + r_importance varchar(63), |
| 24 | + -- importance rating |
| 25 | + |
| 26 | + r_importance_timestamp binary(20), |
| 27 | + -- time when importance rating was assigned |
| 28 | + -- a wiki-style timestamp |
| 29 | + |
| 30 | + primary key (r_project, r_namespace, r_article) |
| 31 | +) /*$wgDBTableOptions*/; |
| 32 | + |
| 33 | +CREATE INDEX /*i*/r_article ON /*_*/ratings (r_namespace, r_article); |
| 34 | +CREATE INDEX /*i*/r_project ON /*_*/ratings (r_project); |
Property changes on: trunk/extensions/SelectionSifter/schema/ratings.sql |
___________________________________________________________________ |
Added: svn:eol-style |
1 | 35 | + native |
Index: trunk/extensions/SelectionSifter/schema/selections.sql |
— | — | @@ -0,0 +1,23 @@ |
| 2 | +-- Replace /*_*/ with the proper prefix |
| 3 | +-- Replace /*$wgDBTableOptions*/ with the correct options |
| 4 | + |
| 5 | +CREATE TABLE IF NOT EXISTS /*_*/selections ( |
| 6 | + s_selection_name varchar(63) not null, |
| 7 | + -- project name |
| 8 | + |
| 9 | + s_namespace int unsigned not null, |
| 10 | + -- article namespace |
| 11 | + |
| 12 | + s_article varchar(255) not null, |
| 13 | + -- article name |
| 14 | + |
| 15 | + s_timestamp binary(14) not null, |
| 16 | + -- timestamp when entry was added |
| 17 | + |
| 18 | + s_revision int unsigned, |
| 19 | + -- manually set revision |
| 20 | + |
| 21 | + primary key (s_selection_name, s_namespace, s_article) |
| 22 | +) /*$wgDBTableOptions*/; |
| 23 | + |
| 24 | +CREATE INDEX /*i*/s_selection_name ON /*_*/selections (s_selection_name); |
Property changes on: trunk/extensions/SelectionSifter/schema/selections.sql |
___________________________________________________________________ |
Added: svn:eol-style |
1 | 25 | + native |
Index: trunk/extensions/SelectionSifter/TableDisplay.php |
— | — | @@ -0,0 +1,61 @@ |
| 2 | +<?php |
| 3 | +if ( !defined( 'MEDIAWIKI' ) ) { |
| 4 | + exit( 1 ); |
| 5 | +} |
| 6 | + |
| 7 | +/** |
| 8 | + * @todo Document overall purpose of this class. |
| 9 | + */ |
| 10 | +class TableDisplay { |
| 11 | + |
| 12 | + /** |
| 13 | + * Register our parser functions |
| 14 | + */ |
| 15 | + public static function ParserFunctionInit( &$parser ) { |
| 16 | + $parser->setFunctionHook( 'AssessmentStats', 'TableDisplay::AssessmentStatsRender' ); |
| 17 | + return true; |
| 18 | + } |
| 19 | + |
| 20 | + /** |
| 21 | + * Register new magic words. |
| 22 | + */ |
| 23 | + public static function LanguageGetMagic( &$magicWords, $langCode ) { |
| 24 | + $magicWords['AssessmentStats'] = array( 0, 'AssessmentStats' ); |
| 25 | + return true; |
| 26 | + } |
| 27 | + |
| 28 | + /** |
| 29 | + * @todo Document! |
| 30 | + * @param string $projectName |
| 31 | + * @param unknown $projectStats |
| 32 | + * @return string A wikitable containing statistics for a project name |
| 33 | + */ |
| 34 | + private static function formatTable( $projectName, $projectStats ) { |
| 35 | + // Column Headers |
| 36 | + $col_headers = array_keys($projectStats['top']); |
| 37 | + $output = "{| class='wikitable' \n|+ $projectName article ratings\n"; |
| 38 | + $output .= "|-\n ! scope='col' | \n"; |
| 39 | + foreach( $col_headers as $col_header ) { |
| 40 | + $output .= "! scope='col' | $col_header \n"; |
| 41 | + } |
| 42 | + foreach( $projectStats as $importance => $qualityRatings ) { |
| 43 | + $output .= "|- \n ! scope='row' | $importance\n"; |
| 44 | + foreach( $qualityRatings as $quality => $qualityCount ) { |
| 45 | + $output .= "| $qualityCount \n"; |
| 46 | + } |
| 47 | + } |
| 48 | + $output .= "|}"; |
| 49 | + return $output; |
| 50 | + } |
| 51 | + |
| 52 | + /** |
| 53 | + * Callback for AssessmentsStats parser function |
| 54 | + * @param Parser $parser Parser object passed by MW hook system (unused) |
| 55 | + * @param unknown A project object?? |
| 56 | + */ |
| 57 | + public static function AssessmentStatsRender( $parser, $project ) { |
| 58 | + $projectStats = Statistics::getProjectStats( $project ); |
| 59 | + $output = TableDisplay::formatTable( $project, $projectStats ); |
| 60 | + return $output; |
| 61 | + } |
| 62 | +} |
Property changes on: trunk/extensions/SelectionSifter/TableDisplay.php |
___________________________________________________________________ |
Added: svn:eol-style |
1 | 63 | + native |
Index: trunk/extensions/SelectionSifter/models/Statistics.php |
— | — | @@ -0,0 +1,122 @@ |
| 2 | +<?php |
| 3 | + |
| 4 | +/** |
| 5 | + * Has static methods to grab assessment statistics |
| 6 | + **/ |
| 7 | + |
| 8 | +class Statistics { |
| 9 | + public static function getImportanceColumn( $importance ) { |
| 10 | + $importanceColumnMapping = array( |
| 11 | + 'top' => 'ps_top_icount', |
| 12 | + 'high' => 'ps_high_icount', |
| 13 | + 'mid' => 'ps_mid_icount', |
| 14 | + 'low' => 'ps_mid_icount', |
| 15 | + 'no' => 'ps_no_icount', |
| 16 | + '' => 'ps_unclassified_icount' |
| 17 | + ); |
| 18 | + |
| 19 | + return $importanceColumnMapping[ strtolower( $importance ) ]; |
| 20 | + } |
| 21 | + |
| 22 | + public static function updateAggregateStats( $rating, $is_new_rating, $update_global = true ) { |
| 23 | + if(! $is_new_rating && empty($rating->old_importance) && empty($rating->old_quality) ) { |
| 24 | + return; |
| 25 | + } |
| 26 | + $dbw = wfGetDB( DB_MASTER ); |
| 27 | + $importance_column = Statistics::getImportanceColumn( $rating->importance ); |
| 28 | + $dbw->insert( |
| 29 | + 'project_stats', |
| 30 | + array( |
| 31 | + 'ps_project' => $rating->project, |
| 32 | + 'ps_quality' => $rating->quality, |
| 33 | + $importance_column => '0' |
| 34 | + ), |
| 35 | + __METHOD__, |
| 36 | + array( 'IGNORE' ) |
| 37 | + ); |
| 38 | + $dbw->update( |
| 39 | + 'project_stats', |
| 40 | + array( "$importance_column = $importance_column + 1" ), |
| 41 | + array( |
| 42 | + "ps_project" => $rating->project, |
| 43 | + "ps_quality" => $rating->quality |
| 44 | + ), |
| 45 | + __METHOD__ |
| 46 | + ); |
| 47 | + |
| 48 | + if(! $is_new_rating ) { |
| 49 | + // Is not a new rating, and atleast one of quality or importance has changed |
| 50 | + if(! empty( $rating->old_quality ) ) { |
| 51 | + $q_value = $rating->old_quality; |
| 52 | + } else { |
| 53 | + $q_value = $rating->quality; |
| 54 | + } |
| 55 | + if(! empty( $rating->old_importance) ) { |
| 56 | + $i_column = Statistics::getImportanceColumn( $rating->old_importance ); |
| 57 | + } else { |
| 58 | + $i_column = Statistics::getImportanceColumn( $rating->importance ); |
| 59 | + } |
| 60 | + $dbw->update( |
| 61 | + 'project_stats', |
| 62 | + array( "$i_column = $i_column - 1" ), |
| 63 | + array( |
| 64 | + "ps_project" => $rating->project, |
| 65 | + "ps_quality" => $q_value |
| 66 | + ), |
| 67 | + __METHOD__ |
| 68 | + ); |
| 69 | + } |
| 70 | + |
| 71 | + if( $update_global ) { |
| 72 | + $global_rating = new Rating( |
| 73 | + "Global Project", |
| 74 | + $rating->namespace, |
| 75 | + $rating->title, |
| 76 | + $rating->quality, |
| 77 | + $rating->quality_timestamp, |
| 78 | + $rating->importance, |
| 79 | + $rating->importance_timestamp |
| 80 | + ); |
| 81 | + $global_rating->old_importance = $rating->old_importance; |
| 82 | + $global_rating->old_quality = $rating->old_quality; |
| 83 | + Statistics::updateAggregateStats( $global_rating, $is_new_rating, false ); |
| 84 | + } |
| 85 | + } |
| 86 | + |
| 87 | + public static function getProjectStats( $project ) { |
| 88 | + $dbr = wfGetDB( DB_SLAVE ); |
| 89 | + $query = $dbr->select( |
| 90 | + "project_stats", |
| 91 | + "*", |
| 92 | + array( |
| 93 | + "ps_project" => $project |
| 94 | + ), |
| 95 | + __METHOD__ |
| 96 | + ); |
| 97 | + |
| 98 | + $project_statistics = array( |
| 99 | + "top" => array(), |
| 100 | + "high" => array(), |
| 101 | + "mid" => array(), |
| 102 | + "low" => array(), |
| 103 | + "no" => array(), |
| 104 | + "" => array() |
| 105 | + ); |
| 106 | + |
| 107 | + |
| 108 | + foreach( $query as $row_object ) { |
| 109 | + $data_row = (array)$row_object; |
| 110 | + $quality = $data_row['ps_quality']; |
| 111 | + foreach( $project_statistics as $importance => &$importance_row ) { |
| 112 | + $importance_row[$quality] = $data_row[Statistics::getImportanceColumn( $importance )]; |
| 113 | + } |
| 114 | + } |
| 115 | + |
| 116 | + // Make '' into 'unclassified' |
| 117 | + $project_statistics['unclassified'] = $project_statistics['']; |
| 118 | + unset( $project_statistics[''] ); |
| 119 | + |
| 120 | + return $project_statistics; |
| 121 | + } |
| 122 | + |
| 123 | +} |
Property changes on: trunk/extensions/SelectionSifter/models/Statistics.php |
___________________________________________________________________ |
Added: svn:eol-style |
1 | 124 | + native |
Index: trunk/extensions/SelectionSifter/models/Log.php |
— | — | @@ -0,0 +1,38 @@ |
| 2 | +<?php |
| 3 | + |
| 4 | +/** |
| 5 | + * Represents an convenience methods for logging |
| 6 | + **/ |
| 7 | +class AssessmentChangeLog { |
| 8 | + public static function makeEntry( $project, $namespace, $article, $timestamp, $action, $old, $new ) { |
| 9 | + $dbw = wfGetDB( DB_MASTER ); |
| 10 | + $dbw->insert( |
| 11 | + 'assessment_changelog', |
| 12 | + array( |
| 13 | + 'l_project' => $project, |
| 14 | + 'l_namespace' => $namespace, |
| 15 | + 'l_article' => $article, |
| 16 | + 'l_action' => $action, |
| 17 | + 'l_timestamp' => $timestamp, |
| 18 | + 'l_old' => $old, |
| 19 | + 'l_new' => $new, |
| 20 | + 'l_revision_timestamp' => 0 |
| 21 | + ), |
| 22 | + __METHOD__ |
| 23 | + ); |
| 24 | + } |
| 25 | + |
| 26 | + public static function getLogs() { |
| 27 | + $dbr = wfGetDB( DB_SLAVE ); |
| 28 | + $logs = $dbr->select( |
| 29 | + 'assessment_changelog', |
| 30 | + '*' |
| 31 | + ); |
| 32 | + $entries = array(); |
| 33 | + foreach( $logs as $entry ) { |
| 34 | + $entry = (array)$entry; |
| 35 | + array_push( $entries, $entry ); |
| 36 | + } |
| 37 | + return $entries; |
| 38 | + } |
| 39 | +} |
Property changes on: trunk/extensions/SelectionSifter/models/Log.php |
___________________________________________________________________ |
Added: svn:eol-style |
1 | 40 | + native |
Index: trunk/extensions/SelectionSifter/models/Rating.php |
— | — | @@ -0,0 +1,207 @@ |
| 2 | +<?php |
| 3 | + |
| 4 | +/** |
| 5 | + * Represents an article and associated rating |
| 6 | + **/ |
| 7 | +class Rating { |
| 8 | + public $project; |
| 9 | + public $namespace; |
| 10 | + public $title; |
| 11 | + public $quality; |
| 12 | + public $quality_timestamp; |
| 13 | + public $importance; |
| 14 | + public $importance_timestamp; |
| 15 | + |
| 16 | + public $old_importance; |
| 17 | + public $old_quality; |
| 18 | + private $inDB = false; |
| 19 | + |
| 20 | + public function __construct( $project, $namespace, $title, $quality, $quality_timestamp, $importance, $importance_timestamp ) { |
| 21 | + $this->project = $project; |
| 22 | + $this->namespace = $namespace; |
| 23 | + $this->title = $title; |
| 24 | + $this->quality = $quality; |
| 25 | + $this->quality_timestamp = $quality_timestamp; |
| 26 | + $this->importance = $importance; |
| 27 | + $this->importance_timestamp = $importance_timestamp; |
| 28 | + } |
| 29 | + |
| 30 | + public function update( $importance, $quality, $timestamp ) { |
| 31 | + $logAction = ""; // q for quality change, i for importance change, qi for both |
| 32 | + if( $quality != $this->quality ) { |
| 33 | + $this->old_quality = $this->quality; |
| 34 | + $this->quality = $quality; |
| 35 | + $this->quality_timestamp = $timestamp; |
| 36 | + $logAction .= "q"; |
| 37 | + } |
| 38 | + if( $importance != $this->importance ) { |
| 39 | + $this->old_importance = $this->importance; |
| 40 | + $this->importance = $importance; |
| 41 | + $this->importance_timestamp = $timestamp; |
| 42 | + $logAction .= "i"; |
| 43 | + } |
| 44 | + if( $logAction != "") { |
| 45 | + $timestamp = wfTimestamp( TS_MW ); |
| 46 | + if( strpos( $logAction, 'q' ) !== false ) { |
| 47 | + AssessmentChangeLog::makeEntry( |
| 48 | + $this->project, |
| 49 | + $this->namespace, |
| 50 | + $this->title, |
| 51 | + $timestamp, |
| 52 | + "quality", |
| 53 | + $this->old_quality, |
| 54 | + $this->quality |
| 55 | + ); |
| 56 | + } |
| 57 | + if( strpos( $logAction, 'i' ) !== false ) { |
| 58 | + AssessmentChangeLog::makeEntry( |
| 59 | + $this->project, |
| 60 | + $this->namespace, |
| 61 | + $this->title, |
| 62 | + $timestamp, |
| 63 | + "importance", |
| 64 | + $this->old_importance, |
| 65 | + $this->importance |
| 66 | + ); |
| 67 | + } |
| 68 | + |
| 69 | + $this->saveAll(); |
| 70 | + } |
| 71 | + } |
| 72 | + |
| 73 | + public function saveAll() { |
| 74 | + $data_array = array( |
| 75 | + 'r_project' => $this->project, |
| 76 | + 'r_namespace' => $this->namespace, |
| 77 | + 'r_article' => $this->title, |
| 78 | + 'r_quality' => $this->quality, |
| 79 | + 'r_quality_timestamp' => $this->quality_timestamp, |
| 80 | + 'r_importance' => $this->importance, |
| 81 | + 'r_importance_timestamp' => $this->importance_timestamp |
| 82 | + ); |
| 83 | + $dbw = wfGetDB( DB_MASTER ); |
| 84 | + if( $this->inDB ) { |
| 85 | + $dbw->update( |
| 86 | + "ratings", |
| 87 | + $data_array, |
| 88 | + array( |
| 89 | + 'r_namespace' => $this->namespace, |
| 90 | + 'r_article' => $this->title, |
| 91 | + 'r_project' => $this->project |
| 92 | + ), |
| 93 | + __METHOD__ |
| 94 | + ); |
| 95 | + |
| 96 | + Statistics::updateAggregateStats( $this, false ); |
| 97 | + } else { |
| 98 | + $dbw->insert( |
| 99 | + "ratings", |
| 100 | + $data_array, |
| 101 | + __METHOD__ |
| 102 | + ); |
| 103 | + |
| 104 | + Statistics::updateAggregateStats( $this, true ); |
| 105 | + $this->inDB = true; |
| 106 | + } |
| 107 | + } |
| 108 | + |
| 109 | + public static function forTitle( $title ) { |
| 110 | + $dbr = wfGetDB( DB_SLAVE ); |
| 111 | + $query = $dbr->select( |
| 112 | + "ratings", |
| 113 | + array( |
| 114 | + "r_project", "r_namespace", "r_article", "r_quality", |
| 115 | + "r_quality_timestamp", "r_importance", "r_importance_timestamp" |
| 116 | + ), |
| 117 | + array( |
| 118 | + "r_namespace" => $title->getNamespace(), |
| 119 | + "r_article" => $title->getText(), |
| 120 | + ), |
| 121 | + __METHOD__ |
| 122 | + ); |
| 123 | + |
| 124 | + $ratings = array(); |
| 125 | + |
| 126 | + foreach( $query as $row ) { |
| 127 | + $rating = new Rating( |
| 128 | + $row->r_project, $row->r_namespace, |
| 129 | + $row->r_article, $row->r_quality, |
| 130 | + $row->r_quality_timestamp, $row->r_importance, |
| 131 | + $row->r_importance_timestamp); |
| 132 | + $rating->inDB = true; |
| 133 | + $ratings[$rating->project] = $rating; |
| 134 | + } |
| 135 | + return $ratings; |
| 136 | + } |
| 137 | + |
| 138 | + public static function moveArticle( $oldTitle, $newTitle ) { |
| 139 | + // Can be optimized to use two queries - so we touch DB_MASTER only if necessary |
| 140 | + // But is that a good thing? |
| 141 | + $dbw = wfGetDB( DB_MASTER ); |
| 142 | + $dbw->update( |
| 143 | + 'ratings', |
| 144 | + array( |
| 145 | + 'r_namespace' => $newTitle->getNamespace(), |
| 146 | + 'r_article' => $newTitle->getText() |
| 147 | + ), |
| 148 | + array( |
| 149 | + 'r_namespace' => $oldTitle->getNamespace(), |
| 150 | + 'r_article' => $oldTitle->getText() |
| 151 | + ), |
| 152 | + __METHOD__ |
| 153 | + ); |
| 154 | + // Article moves not logged - yet |
| 155 | + } |
| 156 | + |
| 157 | + private static function checkArticle( $article, $category_filters ) { |
| 158 | + // Check category |
| 159 | + if( count( $category_filters ) == 0 || ( count($category_filters) == 1 && empty( $category_filters[0] ) ) ) { |
| 160 | + return true; |
| 161 | + } |
| 162 | + |
| 163 | + foreach( $category_filters as $category ) { |
| 164 | + if( in_array( $category, $article['categories'] ) ) { |
| 165 | + return true; |
| 166 | + } |
| 167 | + } |
| 168 | + return false; |
| 169 | + } |
| 170 | + |
| 171 | + public static function filterArticles( $filters ) { |
| 172 | + $database_filters_columns = array( 'r_project', 'r_importance', 'r_quality' ); |
| 173 | + |
| 174 | + $dbr = wfGetDB( DB_SLAVE ); |
| 175 | + $database_filters = array(); |
| 176 | + |
| 177 | + foreach($filters as $column => $value) { |
| 178 | + if( ! ( !isset($value) or $value == null or $value == "" ) && in_array( $column, $database_filters_columns ) ) { |
| 179 | + $database_filters[$column] = $value; |
| 180 | + } |
| 181 | + } |
| 182 | + $category_filters = explode( ',', trim( $filters['categories'] ) ); |
| 183 | + $query = $dbr->select( |
| 184 | + 'ratings', |
| 185 | + '*', |
| 186 | + $database_filters, |
| 187 | + __METHOD__ |
| 188 | + ); |
| 189 | + |
| 190 | + $articles = array(); |
| 191 | + foreach( $query as $article_row ) { |
| 192 | + $article = (array)$article_row; |
| 193 | + $title = Title::makeTitle( $article['r_namespace'], $article['r_article'] ); |
| 194 | + $article['title'] = $title; |
| 195 | + $categories = array_keys( $title->getParentCategories() ); |
| 196 | + $article['categories'] = array(); |
| 197 | + foreach( $categories as $category ) { |
| 198 | + $split = explode(':', $category); |
| 199 | + array_push( $article['categories'], trim( $split[1] ) ); |
| 200 | + } |
| 201 | + |
| 202 | + if( Rating::checkArticle( $article, $category_filters ) ) { |
| 203 | + array_push( $articles, $article ); |
| 204 | + } |
| 205 | + } |
| 206 | + return $articles; |
| 207 | + } |
| 208 | +} |
Property changes on: trunk/extensions/SelectionSifter/models/Rating.php |
___________________________________________________________________ |
Added: svn:eol-style |
1 | 209 | + native |
Index: trunk/extensions/SelectionSifter/models/Selection.php |
— | — | @@ -0,0 +1,74 @@ |
| 2 | +<?php |
| 3 | + |
| 4 | +/** |
| 5 | + * Represents an convenience methods for logging |
| 6 | + **/ |
| 7 | +class Selection { |
| 8 | + public static function addEntries( $name, $articles ) { |
| 9 | + $dbw = wfGetDB( DB_MASTER ); |
| 10 | + $timestamp = wfTimestamp( TS_MW ); |
| 11 | + foreach( $articles as $article ) { |
| 12 | + $success = $dbw->insert( |
| 13 | + 'selections', |
| 14 | + array( |
| 15 | + 's_selection_name' => $name, |
| 16 | + 's_namespace' => $article['r_namespace'], |
| 17 | + 's_article' => $article['r_article'], |
| 18 | + 's_timestamp' => $timestamp |
| 19 | + ), |
| 20 | + __METHOD__, |
| 21 | + array( 'IGNORE' ) |
| 22 | + ); |
| 23 | + } |
| 24 | + } |
| 25 | + |
| 26 | + public static function setRevision( $name, $namespace, $article, $revision ) { |
| 27 | + $dbw = wfGetDB( DB_MASTER ); |
| 28 | + $success = $dbw->update( |
| 29 | + 'selections', |
| 30 | + array( |
| 31 | + 's_revision' => $revision |
| 32 | + ), |
| 33 | + array( |
| 34 | + 's_selection_name' => $name, |
| 35 | + 's_namespace' => $namespace, |
| 36 | + 's_article' => $article |
| 37 | + ), |
| 38 | + __METHOD__ |
| 39 | + ); |
| 40 | + return $success; |
| 41 | + } |
| 42 | + |
| 43 | + public static function deleteArticle( $name, $namespace, $article ) { |
| 44 | + $dbw = wfGetDB( DB_MASTER ); |
| 45 | + $success = $dbw->delete( |
| 46 | + 'selections', |
| 47 | + array( |
| 48 | + 's_selection_name' => $name, |
| 49 | + 's_namespace' => $namespace, |
| 50 | + 's_article' => $article |
| 51 | + ), |
| 52 | + __METHOD__ |
| 53 | + ); |
| 54 | + return $success; |
| 55 | + } |
| 56 | + public static function getSelection( $name ) { |
| 57 | + $dbr = wfGetDB( DB_SLAVE ); |
| 58 | + |
| 59 | + $query = $dbr->select( |
| 60 | + 'selections', |
| 61 | + '*', |
| 62 | + array('s_selection_name' => $name), |
| 63 | + __METHOD__ |
| 64 | + ); |
| 65 | + |
| 66 | + $articles = array(); |
| 67 | + foreach( $query as $article_row ) { |
| 68 | + $article = (array)$article_row; |
| 69 | + $title = Title::makeTitle( $article['s_namespace'], $article['s_article'] ); |
| 70 | + $article['title'] = $title; |
| 71 | + array_push( $articles, $article ); |
| 72 | + } |
| 73 | + return $articles; |
| 74 | + } |
| 75 | +} |
Property changes on: trunk/extensions/SelectionSifter/models/Selection.php |
___________________________________________________________________ |
Added: svn:eol-style |
1 | 76 | + native |
Index: trunk/extensions/SelectionSifter/SpecialFilterRatings.php |
— | — | @@ -0,0 +1,68 @@ |
| 2 | +<?php |
| 3 | +/** |
| 4 | + */ |
| 5 | + |
| 6 | +if ( !defined( 'MEDIAWIKI' ) ) { |
| 7 | + echo( "not a valid entry point.\n" ); |
| 8 | + die( 1 ); |
| 9 | +} |
| 10 | + |
| 11 | +class SpecialFilterRatings extends SpecialPage { |
| 12 | + |
| 13 | + public function __construct() { |
| 14 | + parent::__construct( 'FilterRatings' ); |
| 15 | + } |
| 16 | + |
| 17 | + // prototypey code |
| 18 | + public function execute( $par ) { |
| 19 | + global $wgOut, $wgRequest; |
| 20 | + |
| 21 | + $project = $wgRequest->getVal('project'); |
| 22 | + $importance = $wgRequest->getVal('importance'); |
| 23 | + $quality = $wgRequest->getVal('quality'); |
| 24 | + $categories = $wgRequest->getVal('categories'); |
| 25 | + |
| 26 | + $filters = array( |
| 27 | + 'r_project' => $project, |
| 28 | + 'r_importance' => $importance, |
| 29 | + 'r_quality' => $quality, |
| 30 | + 'categories' => $categories |
| 31 | + ); |
| 32 | + |
| 33 | + $categories = explode(',', $wgRequest->getVal('categories')); |
| 34 | + foreach($categories as &$category) { |
| 35 | + $category = trim($category); |
| 36 | + } |
| 37 | + $entries = Rating::filterArticles($filters); |
| 38 | + |
| 39 | + if( $wgRequest->wasPosted() ) { |
| 40 | + $wgOut->disable(); |
| 41 | + |
| 42 | + $action = $wgRequest->getVal('action'); |
| 43 | + $selection_name = $wgRequest->getVal('selection'); |
| 44 | + |
| 45 | + if( $action == 'addtoselection' ) { |
| 46 | + $success = Selection::addEntries($selection_name, $entries); |
| 47 | + $sel_page = new SpecialSelection(); |
| 48 | + |
| 49 | + $url = $sel_page->getTitle()->getLinkUrl( array( 'name' => $selection_name ) ); |
| 50 | + $return = array( |
| 51 | + 'status' => $success, |
| 52 | + 'selection_url' => $url |
| 53 | + ); |
| 54 | + } |
| 55 | + echo json_encode($return); |
| 56 | + return; |
| 57 | + } |
| 58 | + |
| 59 | + $this->setHeaders(); |
| 60 | + |
| 61 | + $wgOut->setPageTitle("Filter Articles by Ratings"); |
| 62 | + |
| 63 | + $template = new FilterRatingsTemplate(); |
| 64 | + $template->set( 'filters', $filters ); |
| 65 | + $template->set( 'articles', $entries ); |
| 66 | + |
| 67 | + $wgOut->addTemplate( $template ); |
| 68 | + } |
| 69 | +} |
Property changes on: trunk/extensions/SelectionSifter/SpecialFilterRatings.php |
___________________________________________________________________ |
Added: svn:eol-style |
1 | 70 | + native |
Index: trunk/extensions/SelectionSifter/SelectionSifter.php |
— | — | @@ -0,0 +1,48 @@ |
| 2 | +<?php |
| 3 | +/** |
| 4 | + * Proof of Concept for Yuvi Panda's 2011 GSoC |
| 5 | + * |
| 6 | + * @file |
| 7 | + * @ingroup Extensions |
| 8 | + * @author Yuvi Panda, http://yuvi.in |
| 9 | + * @copyright © 2011 Yuvaraj Pandian (yuvipanda@yuvi.in) |
| 10 | + * @licence Modified BSD License |
| 11 | + */ |
| 12 | + |
| 13 | +if( !defined( 'MEDIAWIKI' ) ) { |
| 14 | + echo( "This file is an extension to the MediaWiki software and cannot be used standalone.\n" ); |
| 15 | + die( 1 ); |
| 16 | +} |
| 17 | + |
| 18 | +// Extension credits that will show up on Special:Version |
| 19 | + |
| 20 | +// Set up the new special page |
| 21 | +$dir = dirname( __FILE__ ) . '/'; |
| 22 | + |
| 23 | +$wgAutoloadClasses['SelectionSifterHooks'] = $dir . 'SelectionSifter.hooks.php'; |
| 24 | +$wgAutoloadClasses['Statistics'] = $dir . 'models/Statistics.php'; |
| 25 | +$wgAutoloadClasses['Rating'] = $dir . 'models/Rating.php'; |
| 26 | +$wgAutoloadClasses['AssessmentChangeLog'] = $dir . 'models/Log.php'; |
| 27 | +$wgAutoloadClasses['Selection'] = $dir . 'models/Selection.php'; |
| 28 | +$wgAutoloadClasses['TableDisplay'] = $dir . 'TableDisplay.php'; |
| 29 | +$wgAutoloadClasses['AssessmentsExtractor'] = $dir . 'AssessmentsExtractor.php'; |
| 30 | +$wgAutoloadClasses['SpecialAssessmentLog'] = $dir . 'SpecialAssessmentLog.php'; |
| 31 | +$wgAutoloadClasses['SpecialFilterRatings'] = $dir . 'SpecialFilterRatings.php'; |
| 32 | +$wgAutoloadClasses['SpecialSelection'] = $dir . 'SpecialSelection.php'; |
| 33 | + |
| 34 | +$wgAutoloadClasses['FilterRatingsTemplate'] = $dir . 'templates/FilterRatingsTemplate.php'; |
| 35 | +$wgAutoloadClasses['SelectionTemplate'] = $dir . 'templates/SelectionTemplate.php'; |
| 36 | + |
| 37 | +$wgHooks['ArticleSaveComplete'][] = 'SelectionSifterHooks::ArticleSaveComplete'; |
| 38 | +$wgHooks['LoadExtensionSchemaUpdates'][] = 'SelectionSifterHooks::SetupSchema'; |
| 39 | + |
| 40 | +$wgHooks['ParserFirstCallInit'][] = 'TableDisplay::ParserFunctionInit'; |
| 41 | +$wgHooks['LanguageGetMagic'][] = 'TableDisplay::LanguageGetMagic'; |
| 42 | + |
| 43 | +$wgHooks['TitleMoveComplete'][] = 'SelectionSifterHooks::TitleMoveComplete'; |
| 44 | + |
| 45 | +$wgSpecialPages['AssessmentLog'] = 'SpecialAssessmentLog'; |
| 46 | +$wgSpecialPages['FilterRatings'] = 'SpecialFilterRatings'; |
| 47 | +$wgSpecialPages['Selection'] = 'SpecialSelection'; |
| 48 | + |
| 49 | +// Configuration |
Property changes on: trunk/extensions/SelectionSifter/SelectionSifter.php |
___________________________________________________________________ |
Added: svn:eol-style |
1 | 50 | + native |
Index: trunk/extensions/SelectionSifter/AssessmentsExtractor.php |
— | — | @@ -0,0 +1,40 @@ |
| 2 | +<?php |
| 3 | + |
| 4 | +/** |
| 5 | + * Helps extract assessments from a parsed $DOM file |
| 6 | + **/ |
| 7 | +class AssessmentsExtractor |
| 8 | +{ |
| 9 | + /** @todo document */ |
| 10 | + private $mText; |
| 11 | + |
| 12 | + /** |
| 13 | + * @todo Document |
| 14 | + * @param string $preparedText TODO: what is it for? |
| 15 | + */ |
| 16 | + function __construct( $preparedText ) { |
| 17 | + $this->mText = $preparedText; |
| 18 | + } |
| 19 | + |
| 20 | + /** |
| 21 | + * Once AssessmentsExtractor is build, call this method to generate |
| 22 | + * an array of assessment. |
| 23 | + * @todo Describe the returned array |
| 24 | + * @todo What happens if the preparedText does not match the expected format? |
| 25 | + * @return array Assessments |
| 26 | + */ |
| 27 | + public function extractAssessments() { |
| 28 | + $regex = '/<span data-project-name="(?P<project>.*)" data-importance="(?P<importance>.*)" data-quality="(?P<quality>.*)"\s*>/'; |
| 29 | + $matches = array(); |
| 30 | + preg_match_all($regex, $this->mText, $matches, PREG_SET_ORDER); |
| 31 | + |
| 32 | + $assessments = array(); |
| 33 | + foreach($matches as $match) { |
| 34 | + $assessments[$match['project']] = array( |
| 35 | + 'importance' => $match['importance'], |
| 36 | + 'quality' => $match['quality'] |
| 37 | + ); |
| 38 | + } |
| 39 | + return $assessments; |
| 40 | + } |
| 41 | +} |
Property changes on: trunk/extensions/SelectionSifter/AssessmentsExtractor.php |
___________________________________________________________________ |
Added: svn:eol-style |
1 | 42 | + native |
Index: trunk/extensions/SelectionSifter/SelectionSifter.hooks.php |
— | — | @@ -0,0 +1,65 @@ |
| 2 | +<?php |
| 3 | +/** |
| 4 | + * |
| 5 | + * @file |
| 6 | + * @ingroup Extensions |
| 7 | + * @author Yuvi Panda, http://yuvi.in |
| 8 | + * @copyright © 2011 Yuvaraj Pandian (yuvipanda@yuvi.in) |
| 9 | + * @licence Modified BSD License |
| 10 | + */ |
| 11 | + |
| 12 | +if ( !defined( 'MEDIAWIKI' ) ) { |
| 13 | + exit( 1 ); |
| 14 | +} |
| 15 | + |
| 16 | +class SelectionSifterHooks { |
| 17 | + |
| 18 | + private static function updateDatabase( $title, $assessments, $timestamp ) { |
| 19 | + $main_title = Title::makeTitle( NS_MAIN, $title->getText() ); |
| 20 | + $ratings = Rating::forTitle( $main_title ); |
| 21 | + foreach ( $assessments as $project => $assessment ) { |
| 22 | + $curRating = $ratings[$project]; |
| 23 | + if( $curRating ) { |
| 24 | + $curRating->update( $assessment['importance'], $assessment['quality'], 0 ); |
| 25 | + } else { |
| 26 | + $rating = new Rating( |
| 27 | + $project, |
| 28 | + $main_title->getNamespace(), |
| 29 | + $main_title->getText(), |
| 30 | + $assessment['quality'], |
| 31 | + 0, |
| 32 | + $assessment['importance'], |
| 33 | + 0 |
| 34 | + ); |
| 35 | + $rating->saveAll(); |
| 36 | + } |
| 37 | + } |
| 38 | + } |
| 39 | + |
| 40 | + public static function TitleMoveComplete( &$title, &$newtitle, &$user, $oldid, $newid ) { |
| 41 | + Rating::moveArticle( $title, $newtitle ); |
| 42 | + return true; |
| 43 | + } |
| 44 | + |
| 45 | + public static function ArticleSaveComplete(&$article, &$user, $text, $summary, $minoredit, $watchthis, $sectionanchor, &$flags, $revision, &$status, $baseRevId) { |
| 46 | + global $wgParser; |
| 47 | + $title = $article->getTitle(); |
| 48 | + if( $title->getNamespace() == NS_TALK && $revision ) { |
| 49 | + // All conditions to minimize the situations we've to run the job to update the data |
| 50 | + $preparedText = $article->prepareTextForEdit( $text )->output->getText(); |
| 51 | + $extractor = new AssessmentsExtractor( $preparedText ); |
| 52 | + $assessments = $extractor->extractAssessments(); |
| 53 | + SelectionSifterHooks::updateDatabase( $title, $assessments, $revision ); |
| 54 | + } |
| 55 | + return true; |
| 56 | + } |
| 57 | + |
| 58 | + public static function SetupSchema( DatabaseUpdater $du ) { |
| 59 | + $base = dirname( __FILE__ ) . '/schema'; |
| 60 | + $du->addExtensionTable( "ratings", "$base/ratings.sql"); |
| 61 | + $du->addExtensionTable( "project_stats", "$base/project_stats.sql" ); |
| 62 | + $du->addExtensionTable( "assessment_changelog", "$base/log.sql" ); |
| 63 | + $du->addExtensionTable( "selections", "$base/selections.sql" ); |
| 64 | + return true; |
| 65 | + } |
| 66 | +} |
Property changes on: trunk/extensions/SelectionSifter/SelectionSifter.hooks.php |
___________________________________________________________________ |
Added: svn:eol-style |
1 | 67 | + native |
Index: trunk/extensions/SelectionSifter/SpecialSelection.php |
— | — | @@ -0,0 +1,92 @@ |
| 2 | +<?php |
| 3 | +/** |
| 4 | + */ |
| 5 | + |
| 6 | +if ( !defined( 'MEDIAWIKI' ) ) { |
| 7 | + echo( "not a valid entry point.\n" ); |
| 8 | + die( 1 ); |
| 9 | +} |
| 10 | + |
| 11 | +class SpecialSelection extends SpecialPage { |
| 12 | + |
| 13 | + public function __construct() { |
| 14 | + parent::__construct( 'Selection' ); |
| 15 | + } |
| 16 | + |
| 17 | + private function makeCSV( $articles, $name ) { |
| 18 | + $outstream = fopen( "php://output", "w" ); |
| 19 | + $headers = array( |
| 20 | + 'article', |
| 21 | + 'revision', |
| 22 | + 'added' |
| 23 | + ); |
| 24 | + fputcsv( $outstream, $headers ); |
| 25 | + foreach( $articles as $article ) { |
| 26 | + $row = array( |
| 27 | + $article['title']->getFullText(), |
| 28 | + $article['s_revision'], |
| 29 | + wfTimeStamp( TS_ISO_8601, $article['s_timestamp'] ) |
| 30 | + ); |
| 31 | + fputcsv( $outstream, $row ); |
| 32 | + } |
| 33 | + fclose( $outstream ); |
| 34 | + } |
| 35 | + |
| 36 | + public function execute( $par ) { |
| 37 | + global $wgOut, $wgRequest; |
| 38 | + |
| 39 | + $name = $wgRequest->getVal( 'name' ); |
| 40 | + $format = $wgRequest->getVal( 'format' ); |
| 41 | + |
| 42 | + if( $wgRequest->wasPosted() ) { |
| 43 | + $wgOut->disable(); |
| 44 | + $namespace = $wgRequest->getVal( 'namespace' ); |
| 45 | + $article = $wgRequest->getVal( 'article' ); |
| 46 | + |
| 47 | + $action = $wgRequest->getVal( 'action' ); |
| 48 | + if( $action == 'setrevision' ) { |
| 49 | + $revision = $wgRequest->getVal( 'revision' ); |
| 50 | + $success = Selection::setRevision( $name, $namespace, $article, $revision ); |
| 51 | + $title = Title::makeTitle( $namespace, $article ); |
| 52 | + $url = $title->getLinkUrl( array( 'oldid' => $revision ) ); |
| 53 | + $return = array( |
| 54 | + 'status' => $success, |
| 55 | + 'revision' => $revision, |
| 56 | + 'revision_url' => $url |
| 57 | + ); |
| 58 | + } elseif ( $action == 'deletearticle') { |
| 59 | + $success = Selection::deleteArticle( $name, $namespace, $article ); |
| 60 | + $return = array( |
| 61 | + 'status' => $success |
| 62 | + ); |
| 63 | + } |
| 64 | + echo json_encode($return); |
| 65 | + return; |
| 66 | + } |
| 67 | + $entries = Selection::getSelection( $name ); |
| 68 | + $this->setHeaders(); |
| 69 | + |
| 70 | + $wgOut->setPageTitle("Selection"); |
| 71 | + |
| 72 | + if( $format == 'csv' ) { |
| 73 | + $wgRequest->response()->header( 'Content-type: text/csv' ); |
| 74 | + // Is there a security issue in letting the name be arbitrary? |
| 75 | + $wgRequest->response()->header( |
| 76 | + "Content-Disposition: attachment; filename=$name.csv" |
| 77 | + ); |
| 78 | + $wgOut->disable(); |
| 79 | + $this->makeCSV( $entries, $name ); |
| 80 | + } |
| 81 | + |
| 82 | + $csv_link = $this->getFullTitle()->getFullUrl( array( |
| 83 | + 'format' => 'csv', |
| 84 | + 'name' => $name |
| 85 | + ) ); |
| 86 | + $template = new SelectionTemplate(); |
| 87 | + $template->set( 'articles', $entries ); |
| 88 | + $template->set( 'name', $name ); |
| 89 | + $template->set( 'csv_link', $csv_link ); |
| 90 | + |
| 91 | + $wgOut->addTemplate( $template ); |
| 92 | + } |
| 93 | +} |
Property changes on: trunk/extensions/SelectionSifter/SpecialSelection.php |
___________________________________________________________________ |
Added: svn:eol-style |
1 | 94 | + native |
Index: trunk/extensions/SelectionSifter/README |
— | — | @@ -0,0 +1,8 @@ |
| 2 | +Extension to provide Asssessment parsing and collection/filtering based on assessments for creating collections of articles. Used primarily for the Wikipedia Offline projeect. |
| 3 | + |
| 4 | +This is YuviPanda's GSoC 2011 Project. The extension works only on MySQL, with a proper engine that supports Transactions. |
| 5 | + |
| 6 | +This is intended to replace the WP1.0 bot [1] in use on the english wikipedia. The major aim is to make it easier to select and export article selections for various offline collections (Wikipedia 1.0 being such a collection). |
| 7 | + |
| 8 | + |
| 9 | +[1] http://en.wikipedia.org/wiki/User:WP_1.0_bot |
Property changes on: trunk/extensions/SelectionSifter/README |
___________________________________________________________________ |
Added: svn:eol-style |
1 | 10 | + native |
Index: trunk/extensions/SelectionSifter/.vimrc |
— | — | @@ -0,0 +1,2 @@ |
| 2 | +set noexpandtab |
| 3 | +set tabstop=4 |
Property changes on: trunk/extensions/SelectionSifter/.vimrc |
___________________________________________________________________ |
Added: svn:eol-style |
1 | 4 | + native |
Index: trunk/extensions/SelectionSifter/SpecialAssessmentLog.php |
— | — | @@ -0,0 +1,29 @@ |
| 2 | +<?php |
| 3 | +/** |
| 4 | + * @todo Document this file |
| 5 | + */ |
| 6 | + |
| 7 | +if ( !defined( 'MEDIAWIKI' ) ) { |
| 8 | + echo( "not a valid entry point.\n" ); |
| 9 | + die( 1 ); |
| 10 | +} |
| 11 | + |
| 12 | +/** |
| 13 | + * A special page showing various logs related to the assessment extension |
| 14 | + */ |
| 15 | +class SpecialAssessmentLog extends SpecialPage { |
| 16 | + |
| 17 | + public function __construct() { |
| 18 | + parent::__construct( 'AssessmentLog' ); |
| 19 | + } |
| 20 | + |
| 21 | + public function execute( $par ) { |
| 22 | + global $wgOut, $wgRequest; |
| 23 | + |
| 24 | + $entries = AssessmentChangeLog::getLogs(); |
| 25 | + |
| 26 | + $element = Html::element( 'div', array(), print_r( $entries, true) ); |
| 27 | + |
| 28 | + $wgOut->addHTML( $element ); |
| 29 | + } |
| 30 | +} |
Property changes on: trunk/extensions/SelectionSifter/SpecialAssessmentLog.php |
___________________________________________________________________ |
Added: svn:eol-style |
1 | 31 | + native |
Index: trunk/extensions/SelectionSifter/templates/FilterRatingsTemplate.php |
— | — | @@ -0,0 +1,70 @@ |
| 2 | +<?php |
| 3 | +if( !defined( 'MEDIAWIKI' ) ) { |
| 4 | + die( -1 ); |
| 5 | +} |
| 6 | + |
| 7 | +class FilterRatingsTemplate extends QuickTemplate { |
| 8 | + public function execute() { |
| 9 | + $articles = $this->data['articles']; |
| 10 | + $filters = $this->data['filters']; |
| 11 | +?> |
| 12 | + |
| 13 | +<form method="GET" id="filterForm"> |
| 14 | +<p> |
| 15 | +Project Name: <input type="text" name="project" value="<?php echo htmlentities( $filters['r_project'] ); ?>" /> |
| 16 | +Importance: <input type="text" name="importance" value="<?php echo htmlentities( $filters['r_importance'] ); ?>" /> |
| 17 | +Quality: <input type="text" name="quality" value="<?php echo htmlentities( $filters['r_quality'] ); ?>" /> |
| 18 | +<br /> |
| 19 | +Categories (comma separated): <input type="text" name="categories" value="<?php echo htmlentities( $filters['categories'] ); ?>" /> |
| 20 | +<input type="submit" id="submit-query" /> |
| 21 | +</p> |
| 22 | +</form> |
| 23 | +<div> |
| 24 | +Add to Selection: |
| 25 | +<input type="text" name="selection" id="selection" /> |
| 26 | +<input type="button" id="add-to-selection" value="Add" /> |
| 27 | +</div> |
| 28 | +<div id="notice"> |
| 29 | +</div> |
| 30 | +<div id=""> |
| 31 | +<?php if( count($articles) > 0 ) { ?> |
| 32 | +<h3>Results</h3> |
| 33 | + <table> |
| 34 | + <tr> |
| 35 | + <th>Project</th> |
| 36 | + <th>Article</th> |
| 37 | + <th>Importance</th> |
| 38 | + <th>Quality</th> |
| 39 | + </tr> |
| 40 | + <?php foreach( $articles as $article ) { ?> |
| 41 | + <tr> |
| 42 | + <td><?php echo htmlentities( $article['r_project'] ); ?></td> |
| 43 | + <td><a href="<?php echo htmlentities( $article['title']->getLinkURL() ); ?>"><?php echo htmlentities( $article['r_article'] ); ?></a></td> |
| 44 | + <td><?php echo htmlentities( $article['r_importance'] ); ?></td> |
| 45 | + <td><?php echo htmlentities( $article['r_quality'] ); ?></td> |
| 46 | + </tr> |
| 47 | + <?php } ?> |
| 48 | + </table> |
| 49 | +<?php } else { ?> |
| 50 | +<p>No results found</p> |
| 51 | +<?php } ?> |
| 52 | +</div> |
| 53 | + |
| 54 | + <script type="text/javascript"> |
| 55 | + // Should I use RL for tiny snippets like this too? |
| 56 | + $("#add-to-selection").click(function() { |
| 57 | + var selection = $("#selection").val(); |
| 58 | + $.post("", { |
| 59 | + action: "addtoselection", |
| 60 | + selection: selection |
| 61 | + }, function(raw_data) { |
| 62 | + var data = $.parseJSON(raw_data); |
| 63 | + $("#notice").hide().html("Added to selection <a href='" + data.selection_url + "'>" + selection + "</a>").fadeIn(); |
| 64 | + }); |
| 65 | + return false; |
| 66 | + }); |
| 67 | + </script> |
| 68 | + |
| 69 | +<?php |
| 70 | + } // execute() |
| 71 | +} // class |
Property changes on: trunk/extensions/SelectionSifter/templates/FilterRatingsTemplate.php |
___________________________________________________________________ |
Added: svn:eol-style |
1 | 72 | + native |
Index: trunk/extensions/SelectionSifter/templates/SelectionTemplate.php |
— | — | @@ -0,0 +1,109 @@ |
| 2 | +<?php |
| 3 | +if( !defined( 'MEDIAWIKI' ) ) { |
| 4 | + die( -1 ); |
| 5 | +} |
| 6 | + |
| 7 | +class SelectionTemplate extends QuickTemplate { |
| 8 | + public function execute() { |
| 9 | + $articles = $this->data['articles']; |
| 10 | + $name = $this->data['name']; |
| 11 | + $csv_link = $this->data['csv_link']; |
| 12 | +?> |
| 13 | + |
| 14 | +<div id=""> |
| 15 | +<?php if( count($articles) > 0 ) { ?> |
| 16 | +<h3>Articles in Selection <?php echo htmlentities( $name ); ?></h3> <small><a href="<?php echo htmlentities( $csv_link ); ?>">Export CSV</a></small> |
| 17 | + <table> |
| 18 | + <tr> |
| 19 | + <th style="width:150px">Article</th> |
| 20 | + <th style="width:150px">Added on</th> |
| 21 | + <th style="width:75px">Revision</th> |
| 22 | + <th style="width:300px">Actions</th> |
| 23 | + </tr> |
| 24 | + <?php foreach( $articles as $article ) { ?> |
| 25 | + <tr class="article-row" data-namespace="<?php echo htmlentities( $article['s_namespace'] ); ?>" data-article="<?php echo htmlentities( $article['s_article'] ); ?>"> |
| 26 | + <td><a href="<?php echo $article['title']->getLinkURL(); ?>"><?php echo htmlentities( $article['s_article'] ); ?></a></td> |
| 27 | + <td><?php echo wfTimeStamp( TS_ISO_8601, $article['s_timestamp'] ); ?></td> |
| 28 | + <td><?php if($article['s_revision'] != null) { ?> |
| 29 | + <a href="<?php echo htmlentities( $article['title']->getLinkUrl( array( 'oldid' => $article['s_revision'] ) ) ); ?>" class="revision-link"><?php echo htmlentities( $article['s_revision'] ); ?></a> |
| 30 | + <?php } ?> |
| 31 | + </td> |
| 32 | + <td> |
| 33 | + <div class="item-actions"> |
| 34 | + <div class="revision-input" style="display:none"> |
| 35 | + <input type="text" class="revision-id" placeholder="Enter revision id" value="<?php echo htmlentities( $article['s_revision'] ); ?>" /> |
| 36 | + (<a href="#" class="revision-save">Save</a> | <a href="#" class="revision-cancel">Cancel</a>) |
| 37 | + </div> |
| 38 | + <a href="#" class="change-revision">Set Revision</a> | |
| 39 | + <a href="#" class="delete-article">Delete</a> |
| 40 | + </div> |
| 41 | + </td> |
| 42 | + </tr> |
| 43 | + <?php } ?> |
| 44 | + </table> |
| 45 | +<?php } else { ?> |
| 46 | +<p>No such selection found</p> |
| 47 | +<?php } ?> |
| 48 | +</div> |
| 49 | + |
| 50 | + <script type="text/javascript"> |
| 51 | + // Should this be a RL module? |
| 52 | + $(document).ready(function() { |
| 53 | + $(".change-revision").click(function() { |
| 54 | + var parent = $(this).parents(".article-row"); |
| 55 | + var input_box = $(".revision-input", parent); |
| 56 | + input_box.fadeToggle(); |
| 57 | + return false; |
| 58 | + }); |
| 59 | + $(".revision-save").click(function() { |
| 60 | + var parent = $(this).parents(".article-row"); |
| 61 | + var ns = parent.attr("data-namespace"), |
| 62 | + article = parent.attr("data-article"); |
| 63 | + var input = $("input.revision-id", parent); |
| 64 | + var input_box = $(".revision-input", parent); |
| 65 | + var revlink = $(".revision-link", parent); |
| 66 | + |
| 67 | + var revid = input.val(); |
| 68 | + |
| 69 | + $.post('', { |
| 70 | + action: 'setrevision', |
| 71 | + namespace: ns, |
| 72 | + article: article, |
| 73 | + revision: revid |
| 74 | + }, function(raw_data) { |
| 75 | + var data = $.parseJSON(raw_data) |
| 76 | + console.log(data); |
| 77 | + input_box.fadeOut(); |
| 78 | + revlink.hide(); |
| 79 | + revlink.attr("href", data.revision_url).html(data.revision).fadeIn(); |
| 80 | + }); |
| 81 | + |
| 82 | + return false; |
| 83 | + }); |
| 84 | + $(".delete-article").click(function() { |
| 85 | + var parent = $(this).parents(".article-row"); |
| 86 | + var ns = parent.attr("data-namespace"), |
| 87 | + article = parent.attr("data-article"); |
| 88 | + |
| 89 | + $.post('', { |
| 90 | + action: 'deletearticle', |
| 91 | + namespace: ns, |
| 92 | + article: article |
| 93 | + }, function() { |
| 94 | + parent.fadeOut(); |
| 95 | + }); |
| 96 | + |
| 97 | + return false; |
| 98 | + }); |
| 99 | + |
| 100 | + $(".revision-cancel").click(function() { |
| 101 | + var parent = $(this).parents("div.item-actions"); |
| 102 | + var input_box = parent.children(".revision-input"); |
| 103 | + input_box.fadeOut(); |
| 104 | + }); |
| 105 | + }); |
| 106 | + </script> |
| 107 | + |
| 108 | +<?php |
| 109 | + } // execute() |
| 110 | +} // class |
Property changes on: trunk/extensions/SelectionSifter/templates/SelectionTemplate.php |
___________________________________________________________________ |
Added: svn:eol-style |
1 | 111 | + native |