Extended API example
This section includes an extended API example, involving multiple API calls to answer a more complicated kind of question than any single API endpoint can provide: which reviews does a specific userid need to attend to?
The code
<?php
/**
* vim:set ai si et ts=4 sw=4 syntax=php:
*
* reviews.php
*
* Queries the Swarm API and reports which reviews a specified user
* needs to attend to.
*
* Required attention is determined by the following criteria:
* - the user is a participant in a review
* - and the user has not voted on the review
* - and the user has not commented on the review
* - or the user's comment on the review is a
* task that has been addressed and needs verification
*/
if (ini_set('track_errors', 1) === false) {
echo "Warning: unable to track errors.\n";
}
# process command-line arguments
$options = getopt(
'hs:r:v',
array('help', 'swarm:', 'reviewer', 'verbose')
);
$swarm = '';
if (isset($options['s'])) {
$swarm = $options['s'];
}
if (isset($options['swarm'])) {
$swarm = $options['swarm'];
}
if (!$swarm) {
usage('Swarm API URL not provided.');
}
$reviewer = '';
if (isset($options['r'])) {
$reviewer = $options['r'];
}
if (isset($options['reviewer'])) {
$reviewer = $options['reviewer'];
}
if (!$reviewer) {
usage('Swarm reviewer not provided.');
}
$verbose = false;
if (isset($options['v']) || isset($options['verbose'])) {
$verbose = true;
}
if (isset($options['h']) || isset($options['help'])) {
usage();
}
function usage($message = null)
{
if ($message) {
echo "$message\n\n";
}
$script = basename(__FILE__);
echo <<<EOU
$script: -s <Swarm URL> -u <API userid> -p <API user's password> \
-r <reviewer userid to report on> -h
-s|--swarm Swarm's URL (e.g. https://user@password:myswarm.url/)
-r|--reviewer The reviewer to report on.
-h|--help This help text.
-v|--verbose Verbose output.
This script queries the Swarm API and reports on reviews that the
specified user needs to attend to.
Note: If your Helix Versioning Engine (p4d) has security level 3 set, you
cannot use a password to authenticate; you must acquire a host-unlocked
ticket from p4d, and use the ticket in place of a password when
communicating with the Swarm API connected to p4d.
EOU;
exit;
}
function msg($message)
{
global $verbose;
if ($verbose) {
echo $message;
}
}
function call_api($url, $params)
{
global $php_errormsg;
$query = http_build_query($params);
$request = $url . '?' . $query;
$response = @file_get_contents($request);
if ($php_errormsg) {
echo "Unable to call api: $php_errormsg\n";
exit;
}
$json = @json_decode($response, true);
if ($php_errormsg) {
echo "Unable to decode api response: $php_errormsg\n";
exit;
}
return $json;
}
# remove trailing / from URL, if it exists
$swarm = rtrim(trim($swarm), '/');
# fetch the list of reviews
$reviews = call_api(
"$swarm/api/v4/reviews",
array(
'hasReviewers' => 1, # only reviews with participants
'participants' => array($reviewer), # only review for this reviewer
'max' => 9, # get plenty of reviews, if available
'fields' => array('id', 'description', 'commits'), # get these fields
)
);
$report = array();
foreach ($reviews['reviews'] as $review) {
if (is_null($review)) {
continue;
}
$flag = false;
msg('Review: ' . $review['id'] . ' ');
# if the review is already committed, it likely does not need attention
if (array_key_exists('commits', $review)
&& count($review['commits'])
) {
msg("is committed, skipping...\n");
continue;
}
# if the review has a vote from the reviewer, they are already aware
if (array_key_exists('participants', $review)
&& array_key_exists('vote', $review['participants'][$reviewer])
) {
msg("has vote from reviewer, skipping...\n");
continue;
}
# if there are no open comments on the review, the reviewer's
# attention is required
if (array_key_exists('comments', $review)
&& $review['comments'][0] == 0
) {
msg("has no open comments, skipping...\n");
continue;
}
# fetch the comments for this review
$comments = call_api(
"$swarm/api/v4/comments",
array(
'topic' => 'reviews/' . $review['id'], # comments for this review
'max' => 9, # get plenty of comments, if available
)
);
foreach ($comments['comments'] as $comment) {
msg("\n Comment: " . $comment['id'] . ' ');
// skip over comments from other reviewers
if (array_key_exists('user', $comment) && $reviewer != $comment['user']) {
msg("is by another user, carry on...\n");
continue;
}
# skip archived comments
if (array_key_exists('flags', $comment)
&& count($comment['flags']) > 0
&& $comment['flags'][0] == 'closed'
) {
msg("is archived, carry on...\n");
continue;
}
# skip marked tasks
if (array_key_exists('taskState', $comment)
&& ($comment['taskState'] == 'comment'
|| $comment['taskState'] == 'verified'
|| $comment['taskState'] == 'open'
)
) {
msg("reviewer's comment needs attention, carry on...\n");
continue;
}
// anything else means that the reviewer's comment needs attention
// by the reviewer
$flag = true;
msg("needs attention!\n");
break;
}
// evaluation is complete. Does this review need attention?
if ($flag) {
$report[] = $review;
}
}
if (count($report)) {
echo "User '$reviewer' needs to attend to these reviews:\n";
foreach ($report as $review) {
$description = trim($review['description']);
if (strlen($description) > 60) {
$description = substr($description, 0, 60) . ' ...';
}
echo $review['id'] . ": $description\n";
}
} else {
echo "User '$reviewer' has no reviews to attend to.\n";
}
Executing the example
The example is written in PHP. To use it, download the code,
or copy and paste it into a file called reviews.php
. Then, execute it like this:
$ php reviews.php -s https://myswarm.host:port/ -r bob
Replace http://myswarm.host/
with the URL to your Swarm installation.
Replace bob
with the userid you’d like to report on.
To authenticate, insert username:password@
before the hostname. If your Helix
Versioning Engine’s security counter is set to 3
or higher, you need to
acquire a ticket and use the ticket in place of the password (see
Authentication for details). If your Swarm is installed on a
custom port, or is installed in a
sub-folder, include those elements in the URL as well.
For example:
$ php reviews.php -s https://me:F0FC33068BA244B1BBD8196CC9166F34@my.host:8080/swarm/ -r bob
If you do not specify the URL correctly, you might see an error like:
Unable to call api: file_get_contents(http://...@my.host:8080/swarm/api/v6/reviews?hasReviewers=1&participants%5B0%5D=bob&max=9&fields%5B0%5D=id&fields%5B1%5D=description&fields%5B2%5D=commits): failed to open stream: HTTP request failed! HTTP/1.1 404 Not Found
If there are no errors, and the specified userid does have reviews to attend to, the output might look like:
1234: Added grapple-grommit support to woozlewobble class. @bob sh ...
1234
is the id of a review that bob
should attend to, followed by the first
60 characters of the review’s description.