External Ticket Search

From Cerb Wiki

Jump to: navigation, search

Create a folder inside /storage/plugins: i.e.: user.externalsearches Put these 2 files into the folder:

Files

/storage/plugins/user.externalsearches/plugin.xml:

<!DOCTYPE plugin SYSTEM "../../libs/devblocks/plugin.dtd">
<plugin>
	<id>user.externalsearches</id>
	<name>[Cerb5] External Searches</name>
	<description>Allows ticket searches from other apps</description>
	<author>Gonzalo Lopez</author>
	<revision>0</revision> 	 
	

	<dependencies>
		<require plugin_id="cerberusweb.core" version="5.0.0-beta" />
	</dependencies>

	<extensions>

		

		<extension point="devblocks.controller">
			<id>user.externalsearches.controller</id>
			<name>Forums Controller</name>
			<class>
				<file>api/App.php</file>
				<name>ExternalSearchController</name>
			</class>
			<params>
				<param key="uri" value="externalsearch" />
			</params>
		</extension>

	</extensions>

</plugin>


/storage/plugins/user.externalsearches/api/App.php:

<?php

class ExternalSearchController extends DevblocksControllerExtension {

	const EXTENSION_ID = 'user.externalsearches.page';

	/**
	 * These must be defined as DevblocksSearchCriteria class constants.
	 *
	 * @var array
	 * @access private
	 */
	private $_operators = array(
		"OPER_EQ",
    	"OPER_EQ_OR_NULL",
    	"OPER_NEQ",
    	"OPER_IN",
    	"OPER_IS_NULL",
    	"OPER_NIN",
    	"OPER_FULLTEXT",
    	"OPER_LIKE",
    	"OPER_NOT_LIKE",
    	"OPER_GT",
    	"OPER_LT",
    	"OPER_GTE",
    	"OPER_LTE",
    	"OPER_BETWEEN"
	 );

	/**
	 * Search fields and data types association
	 * Keys must be defined as SearchFields_Ticket class constants
	 *
	 * @param array $_fields;
	 */
	private $_fields = array(
		"TICKET_ID",
		"TICKET_MASK",
		"TICKET_SUBJECT",
		"TICKET_FIRST_WROTE",
		"TICKET_LAST_WROTE",
		"REQUESTER_ADDRESS",
		"TICKET_INTERESTING_WORDS",
		"ORG_NAME",
		"TICKET_WAITING",
		"TICKET_DELETED",
		"TICKET_CLOSED",
		"TICKET_FIRST_WROTE_SPAM",
		"TICKET_FIRST_WROTE_NONSPAM",
		"TICKET_CREATED_DATE",
		"TICKET_UPDATED_DATE",
		"TICKET_DUE_DATE",
		"TICKET_SPAM_SCORE",
		"TICKET_SPAM_TRAINING",
		"TICKET_LAST_ACTION_CODE",
		"TICKET_LAST_WORKER_ID",
		"TICKET_NEXT_WORKER_ID",
		"TICKET_TEAM_ID",
		"TICKET_CATEGORY_ID",
		"FULLTEXT_MESSAGE_CONTENT"
	);

	function __construct($manifest) {
		parent::__construct($manifest);
	}

	public function handleRequest(DevblocksHttpRequest $request) {

		$session = DevblocksPlatform::getSessionService();
		$visit = $session->getVisit();

		if (empty($visit)) {
			DevblocksPlatform::redirect(new DevblocksHttpResponse(array('login')));
			return;
		}

		$params = $request->path;
		array_shift($params);

		$view = C4_AbstractViewLoader::getView("search");

		$filtered_criteria = $this->_parseParams($params);
		if ($filtered_criteria) {
			$view->params = array();
			foreach ($filtered_criteria as $criteria) {
				list ($field, $oper, $value) = $criteria;
				$view->params[$field] = new DevblocksSearchCriteria($field, $oper, $value);
			}
		} else {
			$view->doResetCriteria();
		}
		//$view->renderPage = 0;
		C4_AbstractViewLoader::setView("search", $view);

		DevblocksPlatform::redirect(new DevblocksHttpResponse(array('tickets', 'search')));
	}

	private function _parseParams($params) {

		$filtered_criteria = array();

		$criteria_regex = $this->_getCriteriaRegex();

		foreach ($params as $param) {

			$param = DevblocksPlatform::importGPC(urldecode($param),'string');
			if (preg_match($criteria_regex, $param, $match)) {

				array_shift($match);
				list($field, $operator, $value) = $match;

				if ($field_constant = constant("SearchFields_Ticket::" . $field)) {
					$field = $field_constant;
				}

				if ($operator_constant = constant("DevblocksSearchCriteria::" . $operator)) {
					$operator = $operator_constant;
				}

				if (strpos($value, "|") !== false) {
					$value = explode("|", $value);
				}

				$filtered_criteria[] = array($field, $operator, $value);
			}
		}

		return $filtered_criteria;

	}

	private function _getCriteriaRegex() {

		$valid_operators_array = array();
		foreach ($this->_operators as $operator_constant) {
			$valid_operators_array[] = $operator_constant;
			$valid_operators_array[] = constant("DevblocksSearchCriteria::$operator_constant");
		}
		$valid_operators = implode("|", $valid_operators_array);

		$valid_fields_array = array();
		foreach ($this->_fields as $field_constant) {
			$valid_fields_array[] = $field_constant;
			$valid_fields_array[] = constant("SearchFields_Ticket::" . $field_constant);
		}
		$valid_fields = implode("|", $valid_fields_array);

		return "/($valid_fields)\s*($valid_operators)\s*(.+)$/";

	}

}

Usage

The plugin activates a URL that receives search criteria via GET, and redirects the user to the ticket search tab, applying the specified criteria to the search.

The URLS are of the form:

http://cerberus.example.com/externalsearch/CRITERION_1/CRITERION_2/.../CRITERION_N

Where CRITERION is a string containing the FIELD, OPERATOR and VALUE.

$url = "http://cerberus.example/externalseatch/".urlencode("TICKET_ID = 1")."/".urlencode("TICKET_TEAM_ID in 5|6|78");

CRITERIA examples (every group of lines is equivalent):

TICKET_ID=1 t_ticket_id=1 TICKET_ID OPER_EQ 1 (must be url-encoded)

TICKET_IDOPER_IN1,2,3 t_ticket_id in 1,2,3 (must be url-encoded) TICKET_IDin1,2,3

TICKET_TEAM_ID>=260 t_team_idOPER_GT260

TICKET_TEAM_ID in (260,264,266) (must be url-encoded) t_team_idin260,264,266


Complete URL Examples:

http://cerberus.example.com/externalsearch/TICKET_ID=1

Notice how fields and operators are recognized even if there is no space characters between them, so you probably won't neeed to url-encode your URLS. This makes URLs hard to read, but allow to generate them more easily:

http://cerberus.example.com/externalsearch/TICKET_IDin1|2/TICKET_TEAM_IDOPERLT6

Examples (in these, criteria must be url-encoded):

http://cerberus.example.com/externalsearch/TICKET_IDin1|3|4

http://cerberus.example.com/externalsearch/TICKET_TEAM_IDOPER_GT56

TODO

If user is not logged in, redirect to login page passing URL.

Personal tools
Namespaces
Variants
Actions
Navigation
Toolbox