File: /var/www/html/wpemobiq/wp-content/plugins/zendesk/classes/zendesk-wordpress-ajax.php
<?php
/**
* The Zendesk Ajax Class
*
* Handles all the ajax calls to the plugin. Some examples are viewing tickets
* and converting of comments into tickets. This responds in json format, thus
* requires the json functions available in php5 (and php4 as a pear
* library).
*
* @uses json_encode
*/
class Zendesk_Wordpress_Ajax {
protected static $instance = null;
/*
* Get an instance of this class
*/
public static function get_instance() {
if ( is_null( self::$instance ) ) {
self::$instance = new self();
}
return self::$instance;
}
/**
* AJAX Response: Convert to Ticket
*
* This request responds when attempting to convert a comment into
* a ticket. Does not do any conversions, nor requests to the API,
* simply passes in the current user and the requested comment. The
* function below does the rest.
*
* @param Zendesk_Wordpress_Agents|null $agents
*/
public function _ajax_convert_to_ticket($agents = null) {
global $zendesk_support;
if ( empty( $agents ) ) {
$agents = Zendesk_Wordpress_Agents::get_instance();
}
if ( isset( $_REQUEST['comment_id'] ) && is_numeric( $_REQUEST['comment_id'] ) && $agents->_is_agent() ) {
$comment_id = $_REQUEST['comment_id'];
// Verify nonce
check_ajax_referer( 'zendesk-comment-convert-to-ticket-'.$comment_id );
$comment = get_comment( $comment_id );
// Comment found
if ( $comment ) {
$html = array();
$html[] = '<div class="zendesk-comment-to-ticket">';
$html[] = get_avatar( $comment->comment_author_email, 40 );
$html[] = '<div class="zendesk-comment-box">';
$html[] = '<div class="zendesk-comment-arrow"></div>';
$html[] = '<p class="zendesk-author">' . sprintf( __( '<strong>%s</strong> said...', 'zendesk' ), $comment->comment_author ) . '</p>';
$html[] = wpautop( Zendesk_Wordpress_Utilities::_excerpt( strip_tags( $comment->comment_content ), 70 ) );
$html[] = '<p class="zendesk-comment-date">' . date( get_option( 'date_format' ) . ' \a\t ' . get_option( 'time_format' ), strtotime( $comment->comment_date ) ) . '</p>';
$html[] = '</div>';
$html[] = '<br class="clear" />';
$html[] = '<p class="zendesk-after-comment-box">' . __( 'A new ticket will be created inside your Zendesk account, and your response below will be added as a comment to that ticket.', 'zendesk' ) . '</p>';
$html[] = get_avatar( $zendesk_support->zendesk_user['username'], 40 );
$html[] = '<div class="zendesk-comment-box">';
$html[] = '<div class="zendesk-comment-arrow"></div>';
$html[] = '<p class="zendesk-author">' . __( '<strong>You</strong> say:', 'zendesk' ) . '</p>';
$html[] = '<form class="zendesk-comment-to-ticket-form">';
$html[] = '<textarea name="zendesk-comment-reply" class="zendesk-comment-reply"></textarea>';
$html[] = '<br class="clear" />';
$html[] = '<div class="zendesk-options">';
$html[] = '<label><input name="zendesk-comment-public" value="1" type="checkbox" /> ' . __( 'Make this a public comment in the ticket', 'zendesk' ) . '</label>';
$html[] = '<label><input name="zendesk-post-reply" value="1" type="checkbox" /> ' . __( 'Post as a reply on this blog post', 'zendesk' ) . '</label>';
$html[] = '</div>';
$html[] = wp_nonce_field('zendesk-comment-convert-to-ticket-post'.$comment_id, '_wpnonce', true, false);
$html[] = '<input type="hidden" name="zendesk-comment-id" value="' . $comment->comment_ID . '" />';
$html[] = '<input type="submit" class="button-primary zendesk-submit" value="' . __( 'Create ticket', 'zendesk' ) . '" /><div class="zendesk-loader" style="display: none;">loading</div>';
$html[] = '<br class="clear" /><div class="zendesk-notices"></div>';
$html[] = '</form>';
$html[] = '</div>';
$html[] = '</div>';
$html[] = '<br class="clear" />';
$html = implode( "\n", $html );
$response = array(
'status' => 200,
'html' => $html
);
}
}
echo json_encode( $response );
$this->terminate();
}
/**
* AJAX Response: Convert to Ticket POST
*
* This requests responds upon the actual posting of the comments
* to tickets integration, i.e. when the agent has typed a response
* message and clicked the Create ticket button. The whole logics of
* creating the ticket, attaching a comment to the ticket (private,
* or public), associating a WordPress comment with the ticket and
* posting back a WordPress comment as a reply happens here.
*
* @param Zendesk_Wordpress_Agents|null $agents
*/
public function _ajax_convert_to_ticket_post($agents = null) {
global $zendesk_support;
if ( empty( $agents ) ) {
$agents = Zendesk_Wordpress_Agents::get_instance();
}
// If a different response is not set use this one.
$response = array(
'status' => 500,
'error' => __( 'Whoopsie! Problem communicating with Zendesk. Try that again.', 'zendesk' )
);
// Some validation
if ( isset( $_REQUEST['comment_id'] ) && is_numeric( $_REQUEST['comment_id'] ) && $agents->_is_agent() ) {
$comment_id = $_REQUEST['comment_id'];
// Verify nonce
check_admin_referer( 'zendesk-comment-convert-to-ticket-post'.$comment_id );
$comment = get_comment( $comment_id );
// Make sure it's a valid comment
if ( $comment && $comment->comment_type != 'pingback' ) {
// Fetch the associated post
$post = get_post( $comment->comment_post_ID );
// Fetch the incoming data
$message = trim( stripslashes( $_REQUEST['message'] ) );
if (isset( $_REQUEST['comment_public'] )) {
$comment_public = $_REQUEST['comment_public'];
}
else {
$comment_public = false;
}
if (isset( $_REQUEST['post_reply'] )) {
$post_reply = $_REQUEST['post_reply'];
}
else {
$post_reply = false;
}
// Let's format the new ticket
$subject = $post->post_title . ': ' . Zendesk_Wordpress_Utilities::_excerpt( strip_tags( $comment->comment_content ), 5 );
$description = strip_tags( $comment->comment_content );
$requester_name = $comment->comment_author;
$requester_email = $comment->comment_author_email;
// Create the ticket
$ticket_id = $zendesk_support->api->create_ticket( $subject, $description, $requester_name, $requester_email );
if ( ! is_wp_error( $ticket_id ) ) {
// Ticket went okay so update the comment meta to associated it.
update_comment_meta( $comment->comment_ID, 'zendesk-ticket', $ticket_id );
// If we have a message set
if ( strlen( $message ) ) {
// Post a comment to the ticket
$ticket_comment = $zendesk_support->api->create_comment( $ticket_id, $message, $comment_public );
if ( ! is_wp_error( $ticket_comment ) ) {
// Let's see if we need to post a comment back to WordPress.
if ( $post_reply == 'true' ) {
$wp_comment = array(
'comment_post_ID' => $post->ID,
'comment_author' => $zendesk_support->user->display_name,
'comment_author_email' => $zendesk_support->user->user_email,
'comment_content' => $message,
'comment_parent' => $comment_id,
'user_id' => $zendesk_support->user->ID,
'comment_date' => current_time( 'mysql' ),
'comment_approved' => 1
);
wp_insert_comment( $wp_comment );
}
$response = array(
'status' => 200,
'ticket_id' => $ticket_id,
'ticket_url' => Zendesk_Wordpress_Utilities::_ticket_url( $ticket_id )
);
} else {
// The ticket was created but the comment didn't get through.
$response = array(
'status' => 500,
'error' => __( 'A ticket has been created, but failed to post a comment to it.', 'zendesk' )
);
}
} else {
// A message is not set but the ticket was created.
$response = array(
'status' => 200,
'ticket_id' => $ticket_id,
'ticket_url' => Zendesk_Wordpress_Utilities::_ticket_url( $ticket_id )
);
}
} else {
// Failed to create the ticket.
$response = array(
'status' => 500,
'error' => $ticket_id->get_error_message()
);
}
}
}
// Return the response JSON
echo json_encode( $response );
$this->terminate();
}
/*
* AJAX Response: View Ticket Comments
*
* This is an AJAX response to the zendesk_view_comments request which
* displays a colorbox with the ticket comments. This is available
* to agents only.
*
*/
public function _ajax_view_comments($agents = null) {
global $zendesk_support;
if ( empty( $agents ) ) {
$agents = Zendesk_Wordpress_Agents::get_instance();
}
if ( isset( $_REQUEST['ticket_id'] ) && is_numeric( $_REQUEST['ticket_id'] ) && $agents->_is_agent() ) {
$ticket_id = $_REQUEST['ticket_id'];
// Verify nonce
check_ajax_referer( 'zendesk-view-comments-'.$ticket_id );
$comments = $zendesk_support->api->get_comments( $ticket_id );
if ( ! is_wp_error( $comments ) ) {
$html = array();
$html[] = '<div class="zendesk-comment-to-ticket">';
foreach ( $comments as $comment ) {
$author = $zendesk_support->api->get_user( $comment->author_id );
if ( is_wp_error( $author ) ) {
$author = new StdClass;
$author->name = 'Unknown';
$author->email = 'unknown@zendesk.com';
} else {
$author = $author->user;
}
$html[] = '<a target="_blank" href="' . Zendesk_Wordpress_Utilities::_user_url( $comment->author_id ) . '">' . get_avatar( $author->email, 40 ) . '</a>';
$html[] = '<div class="zendesk-comment-box">';
$html[] = '<div class="zendesk-comment-arrow"></div>';
$html[] = '<p class="zendesk-author">' . sprintf( __( '%s said...', 'zendesk' ), '<a target="_blank" href="' . Zendesk_Wordpress_Utilities::_user_url( $comment->author_id ) . '">' . $author->name . '</a>' ) . '</p>';
$html[] = wpautop( $comment->body );
// Let's see if we have any attachments there.
if ( isset( $comment->attachments ) && count( $comment->attachments ) ) {
$html[] = '<div class="zendesk-comment-attachments">';
foreach ( $comment->attachments as $attachment ) {
$html[] = '<p class="zendesk-comment-attachment"><a target="_blank" href="' . $attachment->url . '">' . $attachment->file_name . '</a> <span class="zendesk-attachment-size">(' . Zendesk_Wordpress_Utilities::_file_size( $attachment->size ) . ')</span></p>';
}
$html[] = '</div>';
}
$html[] = '<p class="zendesk-comment-date">' . date( get_option( 'date_format' ) . ' \a\t ' . get_option( 'time_format' ), strtotime( $comment->created_at ) ) . '</p>';
$html[] = '</div>';
$html[] = '<br class="clear" />';
}
$html[] = '</div>';
$html[] = '<br class="clear" />';
$html = implode( "\n", $html );
$response = array(
'status' => 200,
'html' => $html
);
} else {
$error_data = $comments->get_error_data();
$response = array(
'status' => $error_data['status'],
'error' => $comments->get_error_message()
);
}
}
echo json_encode( $response );
$this->terminate();
}
/*
* AJAX Response: Get View
*
* This method is fired by WordPress wehn requesting via the AJAX
* API and the zendesk_get_view action is set. Gathers the view
* into an HTML table and outputs as a JSON response.
*
*/
public function _ajax_get_view() {
global $zendesk_support;
$agents = Zendesk_Wordpress_Agents::get_instance();
if ( isset( $_REQUEST['view_id'] ) && is_numeric( $_REQUEST['view_id'] ) && $agents->_is_agent() ) {
$requested_view = $_REQUEST['view_id'];
// Verify nonce
check_ajax_referer( 'zendesk-get-view-'.$requested_view );
// Is somebody trying to cheat?
$dashboard_widget = Zendesk_Wordpress_Dashboard_Widget::get_instance();
if ( $dashboard_widget->_get_current_user_dashboard_widget() != 'tickets-widget' ) {
return;
}
$views = $zendesk_support->api->get_views();
if ( ! is_wp_error( $views ) ) {
foreach ( $views as $view ) {
if ( $view->id == $requested_view ) {
$zendesk_support->zendesk_user['default_view'] = array(
'id' => $view->id,
'title' => $view->title
);
update_user_meta( $zendesk_support->user->ID, 'zendesk_user_options', $zendesk_support->zendesk_user );
break;
}
}
}
// API requests based on the Zendesk role.
$tickets = $zendesk_support->api->get_tickets_from_view( (int) $zendesk_support->zendesk_user['default_view']['id'] );
// Empty the arrays if they are errors.
if ( is_wp_error( $tickets ) ) {
$tickets = array();
}
$response = array(
'status' => 200,
'html' => Zendesk_Wordpress_Tickets::_get_tickets_widget_html( $tickets )
);
} else {
$response = array(
'status' => 403,
'error' => __( 'Access denied', 'zendesk' )
);
}
echo json_encode( $response );
die();
}
/*
* AJAX Response: View Ticket
*
* This method is fired by WordPress when requesting via the AJAX
* API and the zendesk_view_ticket action is set. Gathers the info
* given the ticket id and returns a JSON object containing a status
* code, the ticket details, and the ticket data formatted in an
* HTML table.
*
*/
public function _ajax_view_ticket( $agents = null ) {
global $zendesk_support;
if ( empty( $agents ) ) {
$agents = Zendesk_Wordpress_Agents::get_instance();
}
if ( isset( $_REQUEST['ticket_id'] ) && is_numeric( $_REQUEST['ticket_id'] ) ) {
$ticket_id = $_REQUEST['ticket_id'];
// Verify nonce
check_ajax_referer( 'zendesk-ticket-view-'.$ticket_id );
// API requests based on the Zendesk role.
if ( $agents->_is_agent() ) {
$ticket = $zendesk_support->api->get_ticket_info( $ticket_id );
} else {
$request = $zendesk_support->api->get_request_info( $ticket_id );
$ticket = $request->request;
}
// If there was no error fetch further
if ( ! is_wp_error( $ticket ) ) {
// If there's a requester ID let's resolve it
if ( isset( $ticket->requester_id ) ) {
$requester = $zendesk_support->api->get_user( $ticket->requester_id );
if ( ! is_wp_error( $requester ) ) {
$requester = $requester->user->name;
} else {
$requester = __( 'Unknown', 'zendesk' );
}
// Otherwise set it to blank, blank fields don't show up.
} else {
$requester = '';
}
// Updated field is not viewable by end-users, so if it's
// not set then set it to blank.
if ( ! isset( $ticket->updated_at ) ) {
$ticket->updated_at = '';
}
// Create the table values, where key is the label and value
// is the value, doh!
$table_values = array(
__( 'Subject:', 'zendesk' ) => htmlspecialchars( $ticket->subject ),
__( 'Description:', 'zendesk' ) => nl2br( htmlspecialchars( $ticket->description ) ),
__( 'Ticket Status:', 'zendesk' ) => '<span class="zendesk-status-' . $ticket->status . '">' . $zendesk_support->_ticket_status( $ticket->status ) . '</span>',
__( 'Requested by:', 'zendesk' ) => '<a target="_blank" href="' . Zendesk_Wordpress_Utilities::_user_url( $ticket->requester_id ) . '">' . $requester . '</a>',
__( 'Created:', 'zendesk' ) => date( get_option( 'date_format' ) . ' \a\t ' . get_option( 'time_format' ), strtotime( $ticket->created_at ) ),
__( 'Updated:', 'zendesk' ) => date( get_option( 'date_format' ) . ' \a\t ' . get_option( 'time_format' ), strtotime( $ticket->updated_at ) )
);
// Agents only data
if ( $agents->_is_agent() ) {
// Custom fields
$table_custom_fields = array();
$ticket_fields = $zendesk_support->api->get_ticket_fields();
// Perhaps optimize this a little bit, though this is
// the way values come in from Zendesk.
if ( ! is_wp_error( $ticket_fields ) && ! empty( $ticket->custom_fields ) ) {
$custom_fields_array = array();
// Build an array with custom field values and ID as index
foreach ( $ticket->custom_fields as $custom_field ) {
$custom_fields_array[ $custom_field->id ] = $custom_field->value;
}
$custom_fields_ids = array_keys( $custom_fields_array );
foreach ( $ticket_fields as $ticket_field ) {
if ( ! in_array( $ticket_field->id, $custom_fields_ids ) ) {
continue;
}
// Use numeric index in case there are duplicate field titles
$table_custom_fields[ $ticket_field->id ] = array( 'title' => $ticket_field->title, 'value' => '' );
// Use readable value for 'tagger' types
if ( 'tagger' === $ticket_field->type ) {
foreach ( $ticket_field->custom_field_options as $custom_field_option ) {
if ( $custom_fields_array[ $ticket_field->id ] === $custom_field_option->value ) {
$table_custom_fields[ $ticket_field->id ]['value'] = $custom_field_option->name;
}
}
} else {
$table_custom_fields[ $ticket_field->id ]['value'] = $custom_fields_array[ $ticket_field->id ];
}
}
}
$nonce = wp_create_nonce( 'zendesk-view-comments-'.$ticket->id );
$table_actions = array(
__( 'Comments:', 'zendesk' ) => '<a data-id="' . $ticket->id . '" href="#" class="zendesk-view-comments" wpnonce="' . $nonce . '">' . __( 'View the comments thread', 'zendesk' ) . '</a>',
__( 'View:', 'zendesk' ) => '<a target="_blank" href="' . Zendesk_Wordpress_Utilities::_ticket_url( $ticket->id ) . '">' . __( 'View this ticket on Zendesk', 'zendesk' ) . '</a>'
);
}
// Use these for debug values
//$table_values['Ticket'] = print_r($ticket, true);
//$table_values['Fields'] = print_r($ticket_fields, true);
// Start formatting the general HTML table.
$html = '<table id="zendesk-ticket-details-table" class="zendesk-ticket-details-table">';
foreach ( $table_values as $label => $value ) {
if ( strlen( $value ) < 1 ) {
continue;
}
$html .= '<tr><td class="zendesk-first"><span class="description">' . $label . '</span></td>';
$html .= '<td>' . $value . '</td></tr>';
}
// Custom Fields Table (agents only)
if ( isset( $table_custom_fields ) && ! empty( $table_custom_fields ) ) {
$html .= '<tr><td colspan="2"><p class="zendesk-heading" style="margin-bottom: 0px;">' . __( 'Custom Fields', 'zendesk' ) . '</p></td></tr>';
foreach ( $table_custom_fields as $table_custom_field ) {
if ( strlen( $table_custom_field['value'] ) < 1 ) {
continue;
}
$html .= '<tr><td class="zendesk-first"><span class="description">' . esc_html( $table_custom_field['title'] ) . '</span></td>';
$html .= '<td>' . esc_html( $table_custom_field['value'] ) . '</td></tr>';
}
}
// Actions Table (agents only)
if ( isset( $table_actions ) && ! empty( $table_actions ) ) {
$html .= '<tr><td colspan="2"><p class="zendesk-heading" style="margin-bottom: 0px;">' . __( 'Actions', 'zendesk' ) . '</p></td></tr>';
foreach ( $table_actions as $label => $value ) {
$html .= '<tr><td class="zendesk-first"><span class="description">' . $label . '</span></td>';
$html .= '<td>' . $value . '</td></tr>';
}
}
$html .= '</table>';
// Format the response to output.
$response = array(
'status' => 200,
'ticket' => $ticket,
'html' => $html
);
} else {
// Something went wrong
$response = array(
'status' => 404,
'data' => $ticket->get_error_message()
);
}
} else {
// Something went really wrong
$response = array(
'status' => 404,
'data' => __( 'Ticket was not found.', 'zendesk' )
);
}
// Output the response array as a JSON object.
echo json_encode( $response );
$this->terminate();
}
/**
* This is a function to terminate the execution of the PHP. This is protected so we can mock it in the test.
*
* @param null|string $message
*/
protected function terminate( $message = null ) {
die( $message );
}
}