Skip to content

Instantly share code, notes, and snippets.

@lbenedix
Last active December 15, 2015 00:19
Show Gist options
  • Save lbenedix/5171782 to your computer and use it in GitHub Desktop.
Save lbenedix/5171782 to your computer and use it in GitHub Desktop.
<?php
class UiFeedbackAPI extends ApiBase {
public function execute() {
$can_read = $this->getUser()->isAllowed( 'read_uifeedback' );
$can_write = $this->getUser()->isAllowed( 'write_uifeedback' );
// Get the parameters
$params = $this->extractRequestParams();
if ( !$can_read ) {
$this->dieUsage( 'you have to be logged in to use that api' );
} else {
$method = $params[ 'mode' ];
if ( $method == 'feedback' ) { /* handling of feedback requests */
$type = $params[ 'ui-feedback-type' ];
if ( $type !== '1' && $type !== '0' ) {
$this->dieUsage( 'ui-feedback-type has to be either 0 or 1! ', 'error-code', 400 );
}
/* I decided to use getFuzzyBool, because using $params['ui-feedback-anonymous'] leads to mysterious behaviour,
a request with "ui-feedback-anonymous:false" was "ui-feedback-anonymous: true" when I printed params to the response */
$anonymous = $this->getRequest()->getFuzzyBool( 'ui-feedback-anonymous' );
if ( $anonymous ) {
$username = '';
} else {
/* username or IP */
$username = $this->getUser()->getName();
}
$notify = 0;
if ( !$anonymous ) {
$notify = $this->getRequest()->getFuzzyBool( 'ui-feedback-notify', null );
}
$task = $params[ 'ui-feedback-task' ];
$other = $params[ 'ui-feedback-task-other' ];
if ( $other !== null ) {
$task .= ' - ' . $other;
}
$done = $params[ 'ui-feedback-done' ];
if ( $done === '1' ) {
$done = 1;
} else if ( $done === '0' ) {
$done = 0;
} else {
$done = null;
}
$url = $params[ 'ui-feedback-url' ];
$a = array(
'type' => $type,
'url' => $url,
'task' => $task,
'done' => $done,
'importance' => $params[ 'ui-feedback-importance' ],
'happened' => $params[ 'ui-feedback-happened' ],
'text1' => $params[ 'ui-feedback-text1' ],
'username' => $username,
'useragent' => $params[ 'ui-feedback-useragent' ],
'notify' => $notify,
//'image_size' => $file_size,
// 'screenshot' => $file_content,
'status' => '0',
'comment' => ''
);
$dbw = wfGetDB( DB_MASTER );
/* insert Feedback into Database */
$dbw->begin();
$dbw->insert( 'uifeedback', $a, __METHOD__, array() );
$id = $dbw->insertId();
$dbw->update( 'uifeedback_stats', array( 'sent = sent + 1' ), array( 'type' => $type ), __METHOD__ );
$dbw->commit();
/* SCREENSHOT */
$token = $this->getContext()->getUser()->editToken();
$file_content = 'foo';
$file_size = 0;
if ( $type == 1 ) { // screenshot
$uploadName = 'file';
if ( array_key_exists( $uploadName, $_FILES ) ) { // Upload via files
$file_content = file_get_contents( $this->getRequest()->getFileTempname( $uploadName ) );
} elseif ( array_key_exists( $uploadName, $_POST ) ) { // Upload via dataURI
$file_content = substr( $_POST[ $uploadName ], strpos( $_POST[ $uploadName ], "," ) + 1 );
$file_content = base64_decode( $file_content );
}
// $file_size = sizeofvar( $file_content );
}
$filename = 'UIFeedback-screenshot-' . $id . '.png';
$request = new UploadFauxRequest (
$this->getRequest(),
array(
'action' => 'upload',
'filename' => $filename,
'file' => $file_content,
'token' => $token,
),
false // was posted?
);
$request->addUpload( 'file', $file_content );
$api = new ApiMain(
$request,
true // enable write?
);
$api->execute();
$upload_response = & $api->getResultData();
/* END SCREENSHOT */
$this->getResult()->addValue( null, $this->getModuleName(), array( 'status' => 'ok', 'id' => $id, '$done' => $done, 'token' => $token, 'getValues' => $request->getValues() ) );
return true;
/* end feedback */
} else if ( $method == 'count' ) { /* handling of count requests (for statistics) */
$type = $params[ 'type' ]; /* 0 dynamic request (popup), 1 questionnaire-button, 2 screenshot-button */
$show = $this->getRequest()->getFuzzyBool( 'show', false ); /* 1 = true */
$click = $this->getRequest()->getFuzzyBool( 'click', false ); /* 1 = true*/
$sent = $this->getRequest()->getFuzzyBool( 'sent', false ); /* 1 = true*/
/* illegal request */
if ( ( !$can_read ) || ( $type < 0 || $type > 2 ) || ( !$show && !$click && !$sent ) ) {
$this->dieUsage( "Bad request!" );
}
/* if click, show and sent are 1 I have no idea what to do */
if ( $click == $show && $show == $sent ) {
$this->dieUsage( "Bad request! Either show, click or sent can be true!" );
}
if ( $show ) {
$value = array( 'shown = shown + 1' );
} else if ( $click ) {
$value = array( 'clicked = clicked + 1' );
} else if ( $sent ) {
$value = array( 'sent = sent + 1' );
} else {
$this->dieUsage( 'Bad Request' );
}
/* update table */
$dbw = wfGetDB( DB_MASTER );
$dbw->update( 'uifeedback_stats',
$value,
array( 'type' => $type ),
__METHOD__
);
return;
/* end count */
/* review */
} else if ( $method == 'review' ) {
$id = $params[ 'id' ];
$new_status = $params[ 'status' ];
$comment = $params[ 'comment' ];
$reviewer = $this->getUser()->getName();
if ( $id != -1 && $new_status != -1 ) {
$dbw = wfGetDB( DB_MASTER );
$dbw->begin();
$values = array( 'status' => $new_status, 'comment' => $comment );
$conds = array( 'id' => $id );
$dbw = wfGetDB( DB_MASTER );
$dbw->update( 'uifeedback', $values, $conds, __METHOD__, array() );
$values = array( 'feedback_id' => $id,
'reviewer' => $reviewer,
'status' => $new_status,
'comment' => $comment
);
$dbw->insert( 'uifeedback_reviews', $values, __METHOD__, array() );
$dbw->commit();
$this->getResult()->addValue( null, $this->getModuleName(), array( 'status' => 'ok', 'params' => $params ) );
}
} else {
$this->dieUsage( 'Bad Request' );
}
}
}
// Description
public function getDescription() {
return 'This Api handles requests from the UIFeedback Extension';
}
// parameter.
public function getAllowedParams() {
return array(
'mode' => array(),
'ui-feedback-anonymous' => array( ApiBase::PARAM_TYPE => 'boolean',
ApiBase::PARAM_DFLT => false ),
'ui-feedback-username' => array(),
'ui-feedback-notify' => array(),
'ui-feedback-task' => array(),
'ui-feedback-task-other' => array( ApiBase::PARAM_TYPE => 'string',
ApiBase::PARAM_DFLT => null ),
'ui-feedback-done' => array( ApiBase::PARAM_TYPE => 'string', /* i took string here because boolean defaults to false when not set */
ApiBase::PARAM_DFLT => 'undefined' ),
'ui-feedback-type' => array( ApiBase::PARAM_TYPE => array( '0', '1' ) ),
'ui-feedback-url' => array(),
'ui-feedback-importance' => array( ApiBase::PARAM_TYPE => array( '0', '1', '2', '3', '4', '5' ),
ApiBase::PARAM_DFLT => '0' ),
'ui-feedback-url' => array(),
'ui-feedback-happened' => array( ApiBase::PARAM_TYPE => array( '0', '1', '2', '3', '4' ),
ApiBase::PARAM_DFLT => '0' ),
'ui-feedback-text1' => array( ApiBase::PARAM_TYPE => 'string' ),
'ui-feedback-useragent' => array( ApiBase::PARAM_TYPE => 'string' ),
'file' => array(),
'id' => array( ApiBase::PARAM_TYPE => 'integer' ),
'type' => array( ApiBase::PARAM_TYPE => 'integer' ),
'status' => array( ApiBase::PARAM_TYPE => array( '1', '2', '3' ) ),
'comment' => array( ApiBase::PARAM_TYPE => 'string' ),
'click' => array( ApiBase::PARAM_TYPE => 'integer',
ApiBase::PARAM_DFLT => 0 ),
'show' => array( ApiBase::PARAM_TYPE => 'integer',
ApiBase::PARAM_DFLT => 0 ),
'sent' => array( ApiBase::PARAM_TYPE => 'integer',
ApiBase::PARAM_DFLT => 0 ),
);
}
// Describe the parameter
public function getParamDescription() {
return array_merge( parent::getParamDescription(), array(
'mode' => 'method to use in the api (feedback, review, count)',
'ui-feedback-anonymous' => 'true, if the user want to post the feedback privately',
'ui-feedback-username' => 'the username of the user ',
'ui-feedback-notify' => '1, if the user wants be be notified about updated on this issue',
'ui-feedback-task' => 'the task (position in the list of tasks)',
'ui-feedback-task-other' => 'free text, if other is selected in task',
'ui-feedback-done' => '0: no, 1: yes, undefined',
'ui-feedback-type' => '0: Screenshot, 1: Questionnaire',
'ui-feedback-url' => 'the url from where the feedback came',
'ui-feedback-importance' => 'an integer for the importance, 0-5',
'ui-feedback-happened' => '0 unknown, 1 not expected, 2 confused, 3 missing feature, 4 other',
'ui-feedback-text1' => 'the comment (free text)',
'ui-feedback-useragent' => 'the useragent',
'file' => 'binary data (the rendered png)',
'type' => '',
'id' => 'for review-mode: feedback-id',
'status' => 'for review-mode: review-status',
'comment' => 'for review-mode: review-comment',
'click' => '',
'show' => '',
'sent' => '',
) );
}
// Get examples
// TODO
public function getExamples() {
return array(
'api.php?action=apisampleoutput&face=O_o&format=xml' => 'Get a sideways look (and the usual predictions)'
);
}
}
/* this classes are written by brion */
class FauxWebRequestUpload extends WebRequestUpload {
public function __construct( $request, $filedata ) {
if ( $filedata === false ) {
$this->doesExist = false;
$this->fileInfo = null;
} else {
$tmp = tempnam( sys_get_temp_dir(), 'fakeupload' );
file_put_contents( $tmp, $filedata );
$this->doesExist = true;
$this->fileInfo = array(
'name' => $tmp,
'type' => 'application/octet-stream',
'size' => strlen( $filedata ),
'tmp_name' => $tmp
);
}
}
}
class UploadFauxRequest extends DerivativeRequest {
function addUpload( $name, $filedata ) {
$this->uploads = array();
$this->uploads[ $name ] = new FauxWebRequestUpload( $this, $filedata );
}
function getUpload( $name ) {
if ( isset( $this->uploads[ $name ] ) ) {
return $this->uploads[ $name ];
} else {
return new FauxWebRequestUpload( $this, false );
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment