Index: branches/wmf/1.17wmf1/extensions/CodeReview/archives/codereview-repopath.sql |
— | — | @@ -0,0 +1 @@ |
| 2 | +CREATE INDEX /*i*/repo_path ON /*_*/code_paths (cp_repo_id, cp_path); |
\ No newline at end of file |
Index: branches/wmf/1.17wmf1/extensions/CodeReview/modules/ext.codereview.overview.css |
— | — | @@ -0,0 +1,46 @@ |
| 2 | +#overviewmap {
|
| 3 | + border: 1px solid #2F6FAB;
|
| 4 | + padding: 2px;
|
| 5 | + min-width: 300px;
|
| 6 | +}
|
| 7 | +#overviewpop {
|
| 8 | + padding: 3px;
|
| 9 | + border: 1px solid black;
|
| 10 | + position: absolute;
|
| 11 | + height: 6.5em;
|
| 12 | + width: 16em;
|
| 13 | + display: none;
|
| 14 | + background-color: #ffffdd;
|
| 15 | + font-size: 80%;
|
| 16 | + line-height: 100%;
|
| 17 | + overflow: hidden;
|
| 18 | + white-space: pre;
|
| 19 | +}
|
| 20 | +#overviewmap > a {
|
| 21 | + display: block;
|
| 22 | + border: 1px solid #888;
|
| 23 | + float: left;
|
| 24 | + width: 26px; /* 26px for body + 2px for border + 2px for margin = 30px total */
|
| 25 | + height: 26px;
|
| 26 | + margin: 1px;
|
| 27 | + overflow: hidden;
|
| 28 | +}
|
| 29 | +#overviewmap > a:target {
|
| 30 | + border-style: dashed;
|
| 31 | +}
|
| 32 | +#overviewmap .summary {
|
| 33 | + clear: both;
|
| 34 | +}
|
| 35 | +
|
| 36 | +table.TablePager tr:target {
|
| 37 | + font-weight: bold;
|
| 38 | +}
|
| 39 | +
|
| 40 | +.overview-backlink {
|
| 41 | + clear:both;
|
| 42 | + display: none;
|
| 43 | +}
|
| 44 | +
|
| 45 | +tr:target .overview-backlink {
|
| 46 | + display: inline;
|
| 47 | +} |
\ No newline at end of file |
Index: branches/wmf/1.17wmf1/extensions/CodeReview/modules/ext.codereview.overview.js |
— | — | @@ -0,0 +1,131 @@ |
| 2 | +/* Scap roadmap viewer, version [0.0.7]
|
| 3 | + * Originally from: http://www.mediawiki.org/wiki/User:Splarka/scapmap.js
|
| 4 | + *
|
| 5 | + *
|
| 6 | + * Loads on, for example: http://www.mediawiki.org/wiki/Special:Code/MediaWiki
|
| 7 | + * Click [overview] to generate map.
|
| 8 | + * Text in the "path" input box is stripped from the path line in the summary.
|
| 9 | + * Clicking a colored box takes you to that relevant line, and a backlink is created in the id column on focus.
|
| 10 | + * Hovering over a colored box pops up a little info packet box.
|
| 11 | + */
|
| 12 | +jQuery( function( $ ) {
|
| 13 | + // check if we're on a page with a useful list of revisions
|
| 14 | + if( $( '#path' ).size() && $('table.TablePager').size() ) {
|
| 15 | + var portlet = $( '#p-namespaces' ).size() ? 'p-namespaces' : 'p-cactions';
|
| 16 | + mw.util.addPortletLink(
|
| 17 | + portlet,
|
| 18 | + '#',
|
| 19 | + mw.msg( 'codereview-overview-title' ),
|
| 20 | + 'ca-scapmap',
|
| 21 | + mw.msg( 'codereview-overview-desc' )
|
| 22 | + );
|
| 23 | + }
|
| 24 | +
|
| 25 | + $('#ca-scapmap').click( function () {
|
| 26 | + var $tr = $('table.TablePager tr');
|
| 27 | + if( $tr.size() < 2 ){
|
| 28 | + return;
|
| 29 | + } else if( $('#overviewmap').size() ) {
|
| 30 | + // We've already created it; maybe they just want to toggle it on and off
|
| 31 | + $('#overviewmap').slideToggle();
|
| 32 | + return;
|
| 33 | + }
|
| 34 | +
|
| 35 | + var overviewPopupData = {};
|
| 36 | +
|
| 37 | + $( '#contentSub' ).after( $( '<div id="overviewmap">' ) );
|
| 38 | + $( '#overviewmap' ).slideUp( 0 );
|
| 39 | +
|
| 40 | + var vpath = $( '#path' ).val();
|
| 41 | + var totals = {};
|
| 42 | + $tr.each( function( i ){
|
| 43 | + var status = false;
|
| 44 | +
|
| 45 | + var trc = $(this).attr( 'class' );
|
| 46 | + if( !trc || !trc.length ) {
|
| 47 | + return;
|
| 48 | + } else {
|
| 49 | + trc = trc.split( ' ' );
|
| 50 | + }
|
| 51 | + for( var j = 0; j < trc.length; j++ ) {
|
| 52 | + if( trc[j].substring( 0, 21 ) == 'mw-codereview-status-' ) {
|
| 53 | + status = trc[j].substring( 21 );
|
| 54 | + }
|
| 55 | + }
|
| 56 | + var $td = $( 'td', $(this) );
|
| 57 | +
|
| 58 | + var statusname = $td.filter( '.TablePager_col_cr_status' ).text();
|
| 59 | +
|
| 60 | + if( !statusname || !status ) {
|
| 61 | + return;
|
| 62 | + }
|
| 63 | +
|
| 64 | + var rev = $td.filter( '.TablePager_col_cr_id, .TablePager_col_cp_rev_id' ).text();
|
| 65 | + overviewPopupData[i] = {
|
| 66 | + 'status' : status,
|
| 67 | + 'statusname' : statusname,
|
| 68 | + 'notes' : $td.filter( '.TablePager_col_comments' ).text(),
|
| 69 | + 'author' : $td.filter( '.TablePager_col_cr_author' ).text(),
|
| 70 | + 'rev' : rev
|
| 71 | + };
|
| 72 | +
|
| 73 | + var path = $td.filter( '.TablePager_col_cr_path' ).text();
|
| 74 | + if( path && path.indexOf( vpath ) == 0 && path != vpath && vpath != '' ) {
|
| 75 | + path = '\u2026' + path.substring( vpath.length );
|
| 76 | + }
|
| 77 | + overviewPopupData[i]['path'] = path;
|
| 78 | +
|
| 79 | + if( !totals[statusname] ) {
|
| 80 | + totals[statusname] = 0;
|
| 81 | + }
|
| 82 | + totals[statusname]++;
|
| 83 | +
|
| 84 | + $(this).attr( 'id', 'TablePager-row-' + rev );
|
| 85 | +
|
| 86 | + $td.filter( '.TablePager_col_selectforchange' )
|
| 87 | + .append( $( '<a href="#box-' + i + '" class="overview-backlink">^</a>' ) );
|
| 88 | +
|
| 89 | + var $box = $( '<a href="#TablePager-row-' + rev + '" class="mw-codereview-status-' + status + '" id="box-' + i + '"> </a>' );
|
| 90 | + $( '#overviewmap' ).append( $box );
|
| 91 | + });
|
| 92 | +
|
| 93 | + var sumtext = [];
|
| 94 | + for( var i in totals ) {
|
| 95 | + if( typeof i != 'string' || typeof totals[i] != 'number' ) {
|
| 96 | + continue;
|
| 97 | + }
|
| 98 | + sumtext.push( i + ': ' + totals[i] );
|
| 99 | + }
|
| 100 | + sumtext.sort();
|
| 101 | + var $summary = $( '<div class="summary">' )
|
| 102 | + .text( 'Total revisions: ' + ( $tr.size() - 1 ) + '. [' + sumtext.join(', ') + ']' );
|
| 103 | +
|
| 104 | + $( '#overviewmap' )
|
| 105 | + .append( $summary )
|
| 106 | + .css( 'max-width', Math.floor( Math.sqrt( $tr.size() ) ) * 30 )
|
| 107 | + .slideDown();
|
| 108 | +
|
| 109 | + // Add the hover popup
|
| 110 | + $( '#overviewmap > a' )
|
| 111 | + .mouseenter( function () {
|
| 112 | +
|
| 113 | + var $el = $( this );
|
| 114 | + if ( $el.data('overviewPopup') ) {
|
| 115 | + return; // already processed
|
| 116 | + }
|
| 117 | + $el.tipsy( { fade: true, gravity: 'sw', html:true } );
|
| 118 | + var id = parseInt( $(this).attr( 'id' ).replace( /box\-/i, '' ) );
|
| 119 | +
|
| 120 | + var $popup = $( '<div id="overviewpop">' +
|
| 121 | + '<div>Rev: r<span id="overviewpop-rev">' + overviewPopupData[id]['rev'] +
|
| 122 | + '</span> (<span id="overviewpop-status">' + overviewPopupData[id]['status'] + '</span>)</div>' +
|
| 123 | + '<div>Number of notes: <span id="overviewpop-notes">' + overviewPopupData[id]['notes'] + '</span></div>' +
|
| 124 | + '<div>Path: <span id="overviewpop-path">' + overviewPopupData[id]['path'] + '</span></div>' +
|
| 125 | + '<div>Author: <span id="overviewpop-author">' + overviewPopupData[id]['author'] + '</span></div>' +
|
| 126 | + '</div>')
|
| 127 | + $el.attr( 'title', $popup.html() );
|
| 128 | + $el.data( 'codeTooltip', true );
|
| 129 | + $el.tipsy( 'show' );
|
| 130 | + });
|
| 131 | + });
|
| 132 | +} );
|
Index: branches/wmf/1.17wmf1/extensions/CodeReview/api/ApiQueryCodeTags.php |
— | — | @@ -0,0 +1,88 @@ |
| 2 | +<?php
|
| 3 | +
|
| 4 | +/**
|
| 5 | + * Created on 20 April 2011
|
| 6 | + *
|
| 7 | + * This program is free software; you can redistribute it and/or modify
|
| 8 | + * it under the terms of the GNU General Public License as published by
|
| 9 | + * the Free Software Foundation; either version 2 of the License, or
|
| 10 | + * (at your option) any later version.
|
| 11 | + *
|
| 12 | + * This program is distributed in the hope that it will be useful,
|
| 13 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
| 14 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
| 15 | + * GNU General Public License for more details.
|
| 16 | + *
|
| 17 | + * You should have received a copy of the GNU General Public License along
|
| 18 | + * with this program; if not, write to the Free Software Foundation, Inc.,
|
| 19 | + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
| 20 | + * http://www.gnu.org/copyleft/gpl.html
|
| 21 | + */
|
| 22 | +
|
| 23 | +class ApiQueryCodeTags extends ApiQueryBase {
|
| 24 | + public function __construct( $query, $moduleName ) {
|
| 25 | + parent::__construct( $query, $moduleName, 'ct' );
|
| 26 | + }
|
| 27 | +
|
| 28 | + public function execute() {
|
| 29 | + global $wgUser;
|
| 30 | + // Before doing anything at all, let's check permissions
|
| 31 | + if ( !$wgUser->isAllowed( 'codereview-use' ) ) {
|
| 32 | + $this->dieUsage( 'You don\'t have permission to view code tags', 'permissiondenied' );
|
| 33 | + }
|
| 34 | + $params = $this->extractRequestParams();
|
| 35 | +
|
| 36 | + $repo = CodeRepository::newFromName( $params['repo'] );
|
| 37 | + if ( !$repo instanceof CodeRepository ) {
|
| 38 | + $this->dieUsage( "Invalid repo ``{$params['repo']}''", 'invalidrepo' );
|
| 39 | + }
|
| 40 | +
|
| 41 | + $data = array();
|
| 42 | + foreach ( $repo->getTagList( true ) as $tag => $count ) {
|
| 43 | + $data[] = array(
|
| 44 | + 'name' => $tag,
|
| 45 | + 'revcount' => $count,
|
| 46 | + );
|
| 47 | + }
|
| 48 | +
|
| 49 | + $result = $this->getResult();
|
| 50 | + $result->setIndexedTagName( $data, 'tag' );
|
| 51 | + $result->addValue( 'query', $this->getModuleName(), $data );
|
| 52 | + }
|
| 53 | +
|
| 54 | + public function getAllowedParams() {
|
| 55 | + return array(
|
| 56 | + 'repo' => array(
|
| 57 | + ApiBase::PARAM_TYPE => 'string',
|
| 58 | + ApiBase::PARAM_REQUIRED => true,
|
| 59 | + ),
|
| 60 | + );
|
| 61 | + }
|
| 62 | +
|
| 63 | + public function getParamDescription() {
|
| 64 | + return array(
|
| 65 | + 'repo' => 'Name of the repository',
|
| 66 | + );
|
| 67 | + }
|
| 68 | +
|
| 69 | + public function getDescription() {
|
| 70 | + return 'Get a list of tags applied to revisions in a given repository';
|
| 71 | + }
|
| 72 | +
|
| 73 | + public function getPossibleErrors() {
|
| 74 | + return array_merge( parent::getPossibleErrors(), array(
|
| 75 | + array( 'code' => 'permissiondenied', 'info' => 'You don\'t have permission to view code tags' ),
|
| 76 | + array( 'code' => 'invalidrepo', 'info' => "Invalid repo ``repo''" ),
|
| 77 | + ) );
|
| 78 | + }
|
| 79 | +
|
| 80 | + public function getExamples() {
|
| 81 | + return array(
|
| 82 | + 'api.php?action=query&list=codetags&ctrepo=MediaWiki',
|
| 83 | + );
|
| 84 | + }
|
| 85 | +
|
| 86 | + public function getVersion() {
|
| 87 | + return __CLASS__ . ': $Id: ApiQueryCodeTags.php 86711 2011-04-22 14:30:46Z reedy $';
|
| 88 | + }
|
| 89 | +}
|
Index: branches/wmf/1.17wmf1/extensions/CodeReview/api/ApiQueryCodePaths.php |
— | — | @@ -0,0 +1,106 @@ |
| 2 | +<?php
|
| 3 | +
|
| 4 | +/**
|
| 5 | + * Created on 6th June 2011
|
| 6 | + *
|
| 7 | + * This program is free software; you can redistribute it and/or modify
|
| 8 | + * it under the terms of the GNU General Public License as published by
|
| 9 | + * the Free Software Foundation; either version 2 of the License, or
|
| 10 | + * (at your option) any later version.
|
| 11 | + *
|
| 12 | + * This program is distributed in the hope that it will be useful,
|
| 13 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
| 14 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
| 15 | + * GNU General Public License for more details.
|
| 16 | + *
|
| 17 | + * You should have received a copy of the GNU General Public License along
|
| 18 | + * with this program; if not, write to the Free Software Foundation, Inc.,
|
| 19 | + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
| 20 | + * http://www.gnu.org/copyleft/gpl.html
|
| 21 | + */
|
| 22 | +
|
| 23 | +class ApiQueryCodePaths extends ApiQueryBase {
|
| 24 | + public function __construct( $query, $moduleName ) {
|
| 25 | + parent::__construct( $query, $moduleName, 'cp' );
|
| 26 | + }
|
| 27 | +
|
| 28 | + public function execute() {
|
| 29 | + global $wgUser;
|
| 30 | + // Before doing anything at all, let's check permissions
|
| 31 | + if ( !$wgUser->isAllowed( 'codereview-use' ) ) {
|
| 32 | + $this->dieUsage( 'You don\'t have permission to view code paths', 'permissiondenied' );
|
| 33 | + }
|
| 34 | + $params = $this->extractRequestParams();
|
| 35 | +
|
| 36 | + $repo = CodeRepository::newFromName( $params['repo'] );
|
| 37 | + if ( !$repo instanceof CodeRepository ) {
|
| 38 | + $this->dieUsage( "Invalid repo ``{$params['repo']}''", 'invalidrepo' );
|
| 39 | + }
|
| 40 | +
|
| 41 | + $this->addTables( 'code_paths' );
|
| 42 | + $this->addFields( 'DISTINCT cp_path' );
|
| 43 | + $this->addWhere( array( 'cp_repo_id' => $repo->getId() ) );
|
| 44 | + $db = $this->getDB();
|
| 45 | +
|
| 46 | + $this->addWhere( 'cp_path ' . $db->buildLike( $params['path'], $db->anyString() ) );
|
| 47 | + $this->addOption( 'USE INDEX', 'repo_path' );
|
| 48 | +
|
| 49 | + $this->addOption( 'LIMIT', 10 );
|
| 50 | +
|
| 51 | + $res = $this->select( __METHOD__ );
|
| 52 | +
|
| 53 | + $result = $this->getResult();
|
| 54 | +
|
| 55 | + $data = array();
|
| 56 | +
|
| 57 | + foreach ( $res as $row ) {
|
| 58 | + $item = array();
|
| 59 | + ApiResult::setContent( $item, $row->cp_path );
|
| 60 | + $data[] = $item;
|
| 61 | + }
|
| 62 | +
|
| 63 | + $result->setIndexedTagName( $data, 'paths' );
|
| 64 | + $result->addValue( 'query', $this->getModuleName(), $data );
|
| 65 | + }
|
| 66 | +
|
| 67 | + public function getAllowedParams() {
|
| 68 | + return array(
|
| 69 | + 'repo' => array(
|
| 70 | + ApiBase::PARAM_TYPE => 'string',
|
| 71 | + ApiBase::PARAM_REQUIRED => true,
|
| 72 | + ),
|
| 73 | + 'path' => array(
|
| 74 | + ApiBase::PARAM_TYPE => 'string',
|
| 75 | + ApiBase::PARAM_REQUIRED => true,
|
| 76 | + ),
|
| 77 | + );
|
| 78 | + }
|
| 79 | +
|
| 80 | + public function getParamDescription() {
|
| 81 | + return array(
|
| 82 | + 'repo' => 'Name of the repository',
|
| 83 | + 'path' => 'Path prefix to filter on',
|
| 84 | + );
|
| 85 | + }
|
| 86 | +
|
| 87 | + public function getDescription() {
|
| 88 | + return 'Get a list of 10 paths in a given repository, based on the input path prefix';
|
| 89 | + }
|
| 90 | +
|
| 91 | + public function getPossibleErrors() {
|
| 92 | + return array_merge( parent::getPossibleErrors(), array(
|
| 93 | + array( 'code' => 'permissiondenied', 'info' => 'You don\'t have permission to view code paths' ),
|
| 94 | + array( 'code' => 'invalidrepo', 'info' => "Invalid repo ``repo''" ),
|
| 95 | + ) );
|
| 96 | + }
|
| 97 | +
|
| 98 | + public function getExamples() {
|
| 99 | + return array(
|
| 100 | + 'api.php?action=query&list=codepaths&cprepo=MediaWiki&cppath=/trunk/phase3',
|
| 101 | + );
|
| 102 | + }
|
| 103 | +
|
| 104 | + public function getVersion() {
|
| 105 | + return __CLASS__ . ': $Id: ApiQueryCodePaths.php 89645 2011-06-07 13:43:31Z reedy $';
|
| 106 | + }
|
| 107 | +}
|