Skip to content

Commit 0ebf5ce

Browse files
committed
Add support for Pull Request linking
Expanding on the existing changeset linking functionality, it is now possible to generate links to pull requests (for VCS that support it, currently implemented only for Bitbucket and Github), using the following syntax p:<repo>:<PR id> Based on an original idea by PhracturedBlue. Fixes #116
1 parent 04b8a0a commit 0ebf5ce

File tree

6 files changed

+89
-52
lines changed

6 files changed

+89
-52
lines changed

Source/MantisSourcePlugin.class.php

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,16 @@ public function hooks() {
2525
*/
2626
public $configuration = false;
2727

28+
/**
29+
* Define the VCS's ability to handle links to Pull Requests.
30+
* If false, Pull Request links are not supported; otherwise this should be
31+
* a sprintf template used to build an URL linking to a Pull Request, by
32+
* appending it at the end of url_repo().
33+
* e.g. '/pull/%s', %s being the PR's number
34+
* @var false|string linkPullRequest
35+
*/
36+
public $linkPullRequest = false;
37+
2838
/**
2939
* Get a long, proper string representing the plugin's source control type.
3040
* Should be localized if possible.

Source/Source.API.php

Lines changed: 0 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -394,56 +394,6 @@ function Source_Process_Changesets( $p_changesets, $p_repo=null ) {
394394
event_signal( 'EVENT_SOURCE_FIXED', array( $t_fixed_bugs ) );
395395
}
396396

397-
/**
398-
* preg_replace_callback function for working with VCS links.
399-
*/
400-
function Source_Changeset_Link_Callback( $p_matches ) {
401-
$t_url_type = strtolower($p_matches[1]);
402-
$t_repo_name = $p_matches[2];
403-
$t_revision = $p_matches[3];
404-
405-
$t_repo_table = plugin_table( 'repository', 'Source' );
406-
$t_changeset_table = plugin_table( 'changeset', 'Source' );
407-
$t_file_table = plugin_table( 'file', 'Source' );
408-
409-
$t_query = "SELECT c.* FROM $t_changeset_table AS c
410-
JOIN $t_repo_table AS r ON r.id=c.repo_id
411-
WHERE c.revision LIKE " . db_param() . '
412-
AND r.name LIKE ' . db_param();
413-
$t_result = db_query( $t_query, array( $t_revision . '%', $t_repo_name . '%' ), 1 );
414-
415-
if ( db_num_rows( $t_result ) > 0 ) {
416-
$t_row = db_fetch_array( $t_result );
417-
418-
$t_changeset = new SourceChangeset( $t_row['repo_id'], $t_row['revision'], $t_row['branch'], $t_row['timestamp'], $t_row['author'], $t_row['message'], $t_row['user_id'] );
419-
$t_changeset->id = $t_row['id'];
420-
421-
$t_repo = SourceRepo::load( $t_changeset->repo_id );
422-
$t_vcs = SourceVCS::repo( $t_repo );
423-
424-
switch( $t_url_type ) {
425-
case 'v':
426-
case 'd':
427-
$t_url = $t_vcs->url_changeset( $t_repo, $t_changeset );
428-
break;
429-
case 'c':
430-
case 's':
431-
default:
432-
$t_url = plugin_page( 'view' ) . '&id=' . $t_changeset->id;
433-
}
434-
435-
$t_name = string_display_line( $t_repo->name . ' ' . $t_vcs->show_changeset( $t_repo, $t_changeset ) );
436-
437-
if ( !is_blank( $t_url ) ) {
438-
return '<a href="' . $t_url . '">' . $t_name . '</a>';
439-
}
440-
441-
return $t_name;
442-
}
443-
444-
return $p_matches[0];
445-
}
446-
447397
/**
448398
* Object for handling registration and retrieval of VCS type extension plugins.
449399
*/

Source/Source.php

Lines changed: 73 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ class SourcePlugin extends MantisPlugin {
2222
* <rev> = changeset revision ID (e.g. SVN rev number, GIT SHA, etc.)
2323
* The match is not case-sensitive.
2424
*/
25-
const CHANGESET_LINKING_REGEX = '/(?:([cdsv]?):([^:\s][^:\n\t]*):([^:\s]+):)/i';
25+
const CHANGESET_LINKING_REGEX = '/(?:([cdsvp]?):([^:\s][^:\n\t]*):([^:\s]+):)/i';
2626

2727
function register() {
2828
$this->name = plugin_lang_get( 'title' );
@@ -160,7 +160,7 @@ function menu_main() {
160160
function display_formatted( $p_event, $p_text, $p_multiline ) {
161161
$p_text = preg_replace_callback(
162162
self::CHANGESET_LINKING_REGEX,
163-
'Source_Changeset_Link_Callback',
163+
array( $this, 'Changeset_Link_Callback' ),
164164
$p_text
165165
);
166166
return $p_text;
@@ -246,5 +246,76 @@ function schema() {
246246
);
247247
}
248248

249+
/**
250+
* preg_replace callback to generate VCS links to changesets and pull requests.
251+
* @param string $p_matches
252+
* @return string
253+
*/
254+
protected function Changeset_Link_Callback( $p_matches ) {
255+
$t_url_type = strtolower($p_matches[1]);
256+
$t_repo_name = $p_matches[2];
257+
$t_revision = $p_matches[3];
258+
259+
// Pull request links
260+
if( $t_url_type == 'p' ) {
261+
$t_repo = SourceRepo::load_by_name( $t_repo_name );
262+
if( $t_repo !== null ) {
263+
$t_vcs = SourceVCS::repo( $t_repo );
264+
if( $t_vcs->linkPullRequest ) {
265+
$t_url = $t_vcs->url_repo( $t_repo )
266+
. sprintf( $t_vcs->linkPullRequest, $t_revision );
267+
$t_name = string_display_line(
268+
$t_repo->name . ' ' .
269+
plugin_lang_get ( 'pullrequest' ) . ' ' .
270+
$t_revision
271+
);
272+
return '<a href="' . $t_url . '">' . $t_name . '</a>';
273+
}
274+
}
275+
return $p_matches[0];
276+
}
277+
278+
// Changeset links
279+
$t_repo_table = plugin_table( 'repository', 'Source' );
280+
$t_changeset_table = plugin_table( 'changeset', 'Source' );
281+
282+
$t_query = "SELECT c.* FROM $t_changeset_table AS c
283+
JOIN $t_repo_table AS r ON r.id=c.repo_id
284+
WHERE c.revision LIKE " . db_param() . '
285+
AND r.name LIKE ' . db_param();
286+
$t_result = db_query( $t_query, array( $t_revision . '%', $t_repo_name . '%' ), 1 );
287+
288+
if( db_num_rows( $t_result ) > 0 ) {
289+
$t_row = db_fetch_array( $t_result );
290+
291+
$t_changeset = new SourceChangeset(
292+
$t_row['repo_id'], $t_row['revision'], $t_row['branch'],
293+
$t_row['timestamp'], $t_row['author'], $t_row['message'],
294+
$t_row['user_id']
295+
);
296+
$t_changeset->id = $t_row['id'];
297+
298+
$t_repo = SourceRepo::load( $t_changeset->repo_id );
299+
$t_vcs = SourceVCS::repo( $t_repo );
300+
301+
switch( $t_url_type ) {
302+
case 'v':
303+
case 'd':
304+
$t_url = $t_vcs->url_changeset( $t_repo, $t_changeset );
305+
break;
306+
case 'c':
307+
case 's':
308+
default:
309+
$t_url = plugin_page( 'view' ) . '&id=' . $t_changeset->id;
310+
}
311+
312+
$t_name = string_display_line( $t_repo->name . ' ' . $t_vcs->show_changeset( $t_repo, $t_changeset ) );
313+
314+
return '<a href="' . $t_url . '">' . $t_name . '</a>';
315+
}
316+
317+
return $p_matches[0];
318+
}
319+
249320
}
250321

Source/lang/strings_english.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ $s_plugin_Source_changesets = 'Changesets';
1414
$s_plugin_Source_file = 'File';
1515
$s_plugin_Source_files = 'Files';
1616
$s_plugin_Source_diff = 'Diff';
17+
$s_plugin_Source_pullrequest = 'Pull Request';
1718

1819
$s_plugin_Source_name = 'Name';
1920
$s_plugin_Source_type = 'Type';

SourceBitBucket/SourceBitBucket.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ class SourceBitBucketPlugin extends MantisSourcePlugin {
1414
protected $api_url_10 = 'https://bitbucket.org/api/1.0/';
1515
protected $api_url_20 = 'https://bitbucket.org/api/2.0/';
1616

17+
public $linkPullRequest = '/pull-request/%s';
18+
1719
public function register() {
1820
$this->name = plugin_lang_get( 'title' );
1921
$this->description = plugin_lang_get( 'description' );
@@ -430,4 +432,5 @@ public function url_get( $p_repo, $p_url ) {
430432
$t_url = escapeshellarg( $p_url ); //use -u user:pass
431433
return shell_exec( 'curl -u ' . $t_user_pass . ' ' . $t_url );
432434
}
435+
433436
}

SourceGithub/SourceGithub.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ class SourceGithubPlugin extends MantisSourcePlugin {
1313

1414
const ERROR_INVALID_PRIMARY_BRANCH = 'invalid_branch';
1515

16+
public $linkPullRequest = '/pull/%s';
17+
1618
public function register() {
1719
$this->name = plugin_lang_get( 'title' );
1820
$this->description = plugin_lang_get( 'description' );

0 commit comments

Comments
 (0)