Location: PHPKode > projects > BugIn and Ticketing System > bugin-0.65/lib/trigger.inc.php
<?php

$triggerOptionList = array();

/* Trigger Bit Flags {{{2 */
define ("TRIGGER_FLAG_DISABLED", 1); // Disabled Ticket
define ("TRIGGER_FLAG_MATCH_ANY", 2); // Match any rule
define ("TRIGGER_FLAG_ADD", 4); // Check rules on ADD
define ("TRIGGER_FLAG_MODIFY", 8); // Check rules on MODIFY
define ("TRIGGER_FLAG_TIME", 16); // Check rules on SCHEDULER

/* }}}2 */

/* Trigger Bit Flags }}}2 */

/* Trigger Rule Type Definitions {{{2 */
define ("TRIGGER_RULE_AFTER_TIME", 1); // Scheduled run at X UNIX time
define ("TRIGGER_RULE_AFTER_UNMODIFIED", 2); // Run after unmodified for X amount of time
define ("TRIGGER_RULE_FIELD_CHANGE", 3); // Run when X field changes
define ("TRIGGER_RULE_FIELD_CHANGED_TO", 4); // Run when X field changes
define ("TRIGGER_RULE_FIELD_IS", 5); // Run when field X is set to Y
define ("TRIGGER_RULE_IS_CLOSED", 6); // Run when ticket is closed
define ("TRIGGER_RULE_REGEXP", 7); // Regexp on Short and Long Description
define ("TRIGGER_RULE_REGEXP_SHORTDESC", 8); // Regexp on Short Description
define ("TRIGGER_RULE_REGEXP_LONGDESC", 9); // Regexp on Long Description
define ("TRIGGER_RULE_REGEXP_MODIFICATION", 10); // Regexp on Long Description

$triggerOptionList['RULE'] = "";
$triggerOptionList['RULE'] .= "<option name=\"When time is later than\" value=\"".TRIGGER_RULE_AFTER_TIME."\">\n";
$triggerOptionList['RULE'] .= "<option name=\"When unmodified for X minutes\" value=\"".TRIGGER_RULE_AFTER_UNMODIFIED."\">\n";
$triggerOptionList['RULE'] .= "<option name=\"When field changes\" value=\"".TRIGGER_RULE_FIELD_CHANGE."\">\n";
$triggerOptionList['RULE'] .= "<option name=\"When field  X is changed to Y\" value=\"".TRIGGER_RULE_FIELD_CHANGED_TO."\">\n";
$triggerOptionList['RULE'] .= "<option name=\"When field is X\" value=\"".TRIGGER_RULE_FIELD_IS."\">\n";
$triggerOptionList['RULE'] .= "<option name=\"When ticket is set to CLOSED state\" value=\"".TRIGGER_RULE_IS_CLOSED."\">\n";
$triggerOptionList['RULE'] .= "<option name=\"Regular Expression on ALL\" value=\"".TRIGGER_RULE_REGEXP."\">\n";
$triggerOptionList['RULE'] .= "<option name=\"Regular Expression on Short Description\" value=\"".TRIGGER_RULE_REGEXP_SHORTDESC."\">\n";
$triggerOptionList['RULE'] .= "<option name=\"Regular Expression on Long Description\" value=\"".TRIGGER_RULE_REGEXP_LONGDESC."\">\n";
$triggerOptionList['RULE'] .= "<option name=\"Regular Expression on Modification\" value=\"".TRIGGER_RULE_REGEXP_MODIFICATION."\">\n";

/* Trigger Rule Type Definitions }}}2 */

/* Trigger Affect Bit Flags {{{2 */
define ("TRIGGER_ACTION_NOTIFY", 1); // Run Notification
define ("TRIGGER_ACTION_NOTIFY_PROJECT", 2); // Run Notification for project e-mail
define ("TRIGGER_ACTION_NOTIFY_OWNER", 3); // Run Notification for ticket owner
define ("TRIGGER_ACTION_NOTIFY_CREATOR", 4); // Run Notification for creator
define ("TRIGGER_ACTION_NOTIFY_ALSONOTIFY", 5); // Run Notification for other (specify)
define ("TRIGGER_ACTION_NOTIFY_OTHER", 6); // Run Notification for other (specify)
define ("TRIGGER_ACTION_UPDATE_FIELD", 7); // Update the ticket
define ("TRIGGER_ACTION_MODIFICATION", 8); // Add update text...
define ("TRIGGER_ACTION_DISABLE_TRIGGER", 128); // Disable the trigger (for one-time runs)
/* Trigger Affect Bit Flags }}}2 */

/* Trigger Functions {{{1 */

/* function getTriggerRuleDescription($rule) {{{2
   This function returns the trigger rule type for the rule */
function getTriggerRuleDescription($rule) {
	switch($rule['type']) {
	case TRIGGER_RULE_AFTER_TIME:
		$type = "Run rule on or after ".date("l dS of F Y h:i:s A", $rule['value']);
		break;
	case TRIGGER_RULE_AFTER_UNMODIFIED:
		$type = "Run after unmodified for {$rule['value']} hours";
		break;
	case TRIGGER_RULE_FIELD_CHANGE:
		$type = "Field: {$rule['value']} is modified";
		break;
	case TRIGGER_RULE_FIELD_CHANGED_TO:
		if (isset($bugDatabase->lists[$rule['value']]))
			$setTo = $bugDatabase->lists[$rule['value']][$rule['fid']]['name'];
		else
			$setTo = $rule['fid'];
		$type = "Field: {$rule['value']} is changed to {$setTo}";
		break;
	case TRIGGER_RULE_FIELD_IS:
		if (isset($bugDatabase->lists[$rule['value']]))
			$setTo = $bugDatabase->lists[$rule['value']][$rule['fid']]['name'];
		else
			$setTo = $rule['fid'];
		$type = "Field: {$rule['value']} is {$setTo}";
		break;
	case TRIGGER_RULE_IS_NOT_CLOSED:
		$type = "Ticket is not closed";
		break;
	case TRIGGER_RULE_REGEXP:
		$type = "Short or Long description regexp({$rule['value']})";
		break;
	case TRIGGER_RULE_REGEXP_SHORTDESC:
		$type = "Short description regexp({$rule['value']})";
		break;
	case TRIGGER_RULE_REGEXP_LONGDESC:
		$type = "Long description regexp({$rule['value']})";
		break;
	default:
		$type = "Unknown Type {$rule['type']}";
		break;
	}
	return $type;
}
/* }}}2 */

/* function runTriggers($type, $ticket, $mod) {{{2
   This function makes a table from the requested info */
function runTriggers($type, $ticket, $mod = array()) {
	global $bugDatabase;
	global $options;


	if (empty($mod))
		$mod = $ticket;

	$newTicket = $bugDatabase->getTicket($ticket['id']);

	$notifyList = array();
	$modifyList = array();
	$triggers = array();
	reset($bugDatabase->lists['trigger']);
	while (list($key, $value) = each($bugDatabase->lists['trigger'])) {
		if (!($value['flags'] & TRIGGER_FLAG_DISABLED) &&
				($value['flags'] & $type) && (
 					// Affects this project OR
					($value['type'] == 'p' && (($value['typeid'] == 0) || ($value['typeid'] == $ticket['project']))) ||
					// Is a ticket trigger for this ticket
					(($value['type'] == 't') && ($value['typeid'] == $ticket['id']))
				)
			 ) {
			$triggers[$key] = $value;
		}
	}

	if (!count($triggers)) {
		buginError("No triggers to run", MESSAGE_DEBUG);
		return;
	}
	else {
		while (list($key, $trigger) = each($triggers)) {
			$affectsToRun = array();
			// Do we match any trigger, or match all?
			if ($trigger['flags'] & TRIGGER_FLAG_MATCH_ANY)
				$matchany = 1;
			else
				$matchany = 0;

			$runAffects = 0;
			$blocked = 0;
			$disable = 0;
			$isClosedRule = 0;
			$ud = array();
			$notify = array();

			buginError ("+Testing Trigger {$trigger['id']}", MESSAGE_DEBUG);

			if (count($trigger['rules'])) {
				reset($trigger['rules']);
				while (list($ruleKey, $rule) = each($trigger['rules'])) {
					$break = 0;
					switch ($rule['type']) {
						case TRIGGER_RULE_AFTER_TIME:
							if (!($rule['value'] >= time()))
								$break = 1;
							break;
						case TRIGGER_RULE_AFTER_UNMODIFIED:
							if ($ticket['age'] < ($rule['value'] * 3600))
								$break = 1;
							break;
						case TRIGGER_RULE_FIELD_CHANGE:
							if ($ticket[$rule['value']] != $newTicket[$rule['value']])
								$break = 1;
							break;
						case TRIGGER_RULE_FIELD_CHANGED_TO:
							if ($mod[$rule['value']] == $rule['fid'])
								$break = 1;
							break;
						case TRIGGER_RULE_FIELD_IS:
							if ($ticket[$rule['value']] != $rule['fid'])
								$break = 1;
							break;
						case TRIGGER_RULE_IS_CLOSED:
							$isClosedRule = 1;
							if (!in_array($ticket['status'], explode(",", $options['closedNum'])))
								$break = 1;
							break;
						case TRIGGER_RULE_REGEXP:
								if (!eregi($rule['value'], $ticket['short_desc']) ||
								    !eregi($rule['value'], $ticket['long_desc']))
									$break = 1;
							break;
						case TRIGGER_RULE_REGEXP_SHORTDESC:
								if (!eregi($rule['value'], $ticket['short_desc']))
									$break = 1;
							break;
						case TRIGGER_RULE_REGEXP_LONGDESC:
								if (!eregi($rule['value'], $ticket['long_desc']))
									$break = 1;
							break;
						default:
							buginError("Unknown Type {$rule['type']} on rule {$ruleKey}", MESSAGE_ERROR);
							exit();
							break;
					}
					buginError("++Testing condition ".getTriggerRuleDescription($rule).": ".$break, MESSAGE_DEBUG);

					// Have we got a match on a "match any"?
					if ($matchany) {
						// We're not blocked, because one of the rules passed.
						if (!$break) {
							$blocked = 0;
							break;
						}
						else {
							// Blocked, but keep processing...
							$blocked = 1;
						}
					}
					elseif ($break) {
						// We're blocked on a match all set
						$blocked = 1;
						break;
					}
				}

				if (!$blocked) {
					buginError ("++ **Running Trigger {$trigger['id']}", MESSAGE_DEBUG);
					$runAffects = 1;
				}
			}
			else {
				$runAffects = 1;
			}

			if ($runAffects &&
			    (($isClosedRule == 0) || in_array($ticket['status'], explode(",", $options['closedNum']))) ) {
				// Go throgh all the affects and execute them.
				while (list($affectKey, $affect) = each($trigger['affects'])) {
					$affectsToRun[] = $affect;
				}
			}
		}
	}
	
	// Check to see if we have any affects to run...
	if (count($affectsToRun)) {
		reset($affectsToRun);
		buginError("+* Running Affects", MESSAGE_DEBUG);
		while (list($affectKey, $affect) = each($affectsToRun)) {
			switch ($affect['type']) {
				case TRIGGER_ACTION_NOTIFY:
					buginError("+Notify: Project, Owner, and Creator", MESSAGE_DEBUG);
					if ($_REQUEST['alsoNotify']) {
						$t = explode(",", str_replace(";", ",", $_REQUEST['alsoNotify']));
						while (list($key, $name) = each($t)) {
							$notify[$name] = "";
						}
						unset($t);
					}
				case TRIGGER_ACTION_NOTIFY_PROJECT:
					buginError("+Notify: New Project List ({$bugDatabase->lists['project'][$ticket['project']]['name']})", MESSAGE_DEBUG);
					$notify[$bugDatabase->lists['project'][$ticket['project']]['email']] = "";
					if ($ticket['project'] != $newTicket['project']) {
						buginError("Notify: Project ({$bugDatabase->lists['project'][$newTicket['project']]['name']})", MESSAGE_DEBUG);
						$notify[$bugDatabase->lists['project'][$newTicket['project']]['email']] = "";
					}
					if ($affect['type'] != TRIGGER_ACTION_NOTIFY) {
						break;
					}
				case TRIGGER_ACTION_NOTIFY_OWNER:
					buginError("+Notify: Owner", MESSAGE_DEBUG);
					if ($ticket['owner'] != 0)
						$notify[$bugDatabase->lists['user'][$ticket['owner']]['email']] = $bugDatabase->lists['user'][$ticket['owner']]['name'];
					if (($ticket['owner'] != $newTicket['owner']) && $newTicket['owner'] != 0) {
						buginError("+Notify: New Owner ({$bugDatabase->lists['user'][$newTicket['owner']]['name']})", MESSAGE_DEBUG);
						$notify[$bugDatabase->lists['user'][$newTicket['owner']]['email']] = $bugDatabase->lists['user'][$newTicket['owner']]['name'];
					}
					if ($affect['type'] != TRIGGER_ACTION_NOTIFY) {
						break;
					}
				case TRIGGER_ACTION_NOTIFY_CREATOR:
					buginError("+Notify: Creator ({$bugDatabase->lists['user'][$ticket['creator']]['email']})", MESSAGE_DEBUG);
					if ($ticket['creator'] != 0)
						$notify[$bugDatabase->lists['user'][$ticket['creator']]['email']] = $bugDatabase->lists['user'][$ticket['creator']]['name'];
					break;
				case TRIGGER_ACTION_NOTIFY_OTHER:
					buginError(htmlentities("+Notify: User ({$bugDatabase->lists['user'][$affect['fid']]['name']})"), MESSAGE_DEBUG);
					$notify[$bugDatabase->lists['user'][$affect['fid']]['email']] = $bugDatabase->lists['user'][$affect['fid']]['name'];
					break;
				case TRIGGER_ACTION_NOTIFY_ALSONOTIFY:
					$mailReg = "(([\x21\x23-\x27\x2A-\x2B\x2D\w\x3D\x3F]+(?:\.[\x21\x23-\x27\x2A-\x2B\x2D\w\x3D\x3F]+)*)\@(\w[-\w]*(?:\.\w[-\w]*)*|\[\d{1,3}(?:\.\d{1,3}){3}\]))";
					if (isset($_REQUEST['alsoNotify']) && $_REQUEST['alsoNotify'] != "") {
						$l = split(",", split(str_replace(";", ",", $_REQUEST['alsoNotify'])));
						while (list($junk, $emailaddy) = each($l)) {
							buginError(htmlentities("+Notify: ({$_REQUEST['alsoNotify']})"), MESSAGE_DEBUG);
							$emailaddy = strip($emailaddy);
							$notify[ereg($mailReg,$emailaddy)] = $emailaddy;
						}
					}
					break;
				case TRIGGER_ACTION_UPDATE_FIELD:
					buginError("+Update {$affect['value']} to {$bugDatabase->lists['project'][$affect['fid']]['name']}", MESSAGE_DEBUG);
					$ud[$affect['value']] = $affect['fid'];
					break;
				case TRIGGER_ACTION_DISABLE_TRIGGER:
					buginError("+Disable trigger after run", MESSAGE_DEBUG);
					$disable = 1;
					break;
				case TRIGGER_ACTION_MODIFICATION:
					buginError("+Add modification text...", MESSAGE_DEBUG);
						if (!isset($mod['modification']))
							$mod['modification'] = "";
						$mod['modification'] .= $affect['value']."\n";
					break;
				default:
					echo "Unknown Type {$affect['type']}<br />";
			}
		}
	}

	$result = array();

	if (count($notify)) {
		// Run Notification
		$notifyList = array();
		while (list($email, $name) = each($notify)) {
			if (!empty($name)) {
				// $notifyList[] = "\"{$name}\" <{$email}>";
				// CLM Hack
				// The above commmented code does not work on 
				// Win2K, IIS, with Win2K SMTP anyway
				$notifyList[] = $email;
			}
			else {
				$notifyList[] = $email;
			}
		}
		$notifyList = implode(",", $notifyList);
		$result['notifyList'] = $notifyList;
	}

	if(count($ud))
		$result['ud'] = $ud;

	$result['mod'] = $mod;
	$result['newTicket'] = $newTicket;

	return($result);



}

/* }}}2 */

/* function makeTriggerTable($type, $id) {{{2
   This function makes a table from the requested info */
function makeTriggerTable($type, $id = 0) {
	global $bugDatabase;
	global $options;

	$table = <<<EOT

<table class="list" border="1">
<tr class="list">
	<td><b>ID</b></td>
	<td><b>Flags</b></td>
	<td><b>Rules</b></td>
	<td><b>Actions</b></td>
	<td><b>Delete</b></td>
</tr>

EOT;
	$triggers = array();
	switch($type) {
		case 't':
		case 'p':
			while (list($key, $value) = each($bugDatabase->lists['trigger'])) {
				if (($value['type'] == $type) && ($value['typeid'] == $id)) {
					$triggers[$key] = $value;
				}
			}
			break;
		case 'a':
			$triggers = $bugDatabase->lists['trigger'];
			break;
	}

	if (count($triggers)) {
		while (list($trigger_id, $trigger) = each($triggers)) {

			$flags = array();

			/* Trigger Flags {{{3 */
			if ($trigger['flags'] & TRIGGER_FLAG_DISABLED) {
				$flags[] = 'disabled';
			}
			else {
				$flags[] = 'enabled';
			}

			if ($trigger['flags'] & TRIGGER_FLAG_MATCH_ANY) {
				$flags[] = 'Match Any Rule';
			}
			else {
				$flags[] = 'Match All Rules';
			}

			if ($trigger['flags'] & TRIGGER_FLAG_ADD) {
				$flags[] = 'Check on ADD';
			}

			if ($trigger['flags'] & TRIGGER_FLAG_MODIFY) {
				$flags[] = 'Check on MODIFY';
			}

			if ($trigger['flags'] & TRIGGER_FLAG_TIME) {
				$flags[] = 'Check on SCHEDULE';
			}

			$flags = implode("\n", $flags);
			$f = str_replace("\n", "<br />\n", htmlentities($flags));
			$table .= <<<EOT

<tr>
	<td><a href="{$options['baseURL']}?area=admin&action=trigger_edit&sub=trigger&num={$trigger['id']}">{$trigger['id']}</a></td>
	<td><b>{$trigger['flags']}</b>:<br />
	$f
	</td>

EOT;
			/* Trigger Flags }}}3 */

			/* Trigger Rules Table {{{3 */
			if (count($trigger['rules'])) {
				// Assemble rule table
				$table .=  <<<EOT
	<td valign="top">
		<table class="list">
			<tr>
				<td>ID</td>
				<td>Type</td>
			</tr>
EOT;
				while (list($ruleid, $rule) = each($trigger['rules'])) {
					$type = getTriggerRuleDescription($rule);
					$table .=  <<< EOT
			<tr>
				<td><a href="{$options['baseURL']}?area=admin&action=trigger_edit&sub=rule&num={$trigger['id']}&rnum={$rule['id']}">{$rule['id']}</a></td>
				<td><b>{$rule['type']}</b>: {$type}</td>
				<td><a href="{$options['baseURL']}?area=admin&action=trigger_delete&sub=rule&num={$trigger['id']}&rnum={$rule['id']}">[Delete]</a></td>
			</tr>

EOT;
				}
				$table .= "\t</table>\n</td>\n";
			}
			else {
				$table .= "<td>NO RULES</td>\n";
			}
			/* Trigger Rules Table }}}3 */

			/* Trigger Affect Table {{{3 */
			// Assemble affect table...
			$table .=  <<<EOT
	<td valign="top">
		<table class="list">
			<tr>
				<td>ID</td>
				<td>Action</td>
			</tr>
EOT;
			while (list($affectid, $affect) = each($trigger['affects'])) {
				switch ($affect['type']) {
					case TRIGGER_ACTION_NOTIFY:
						$type = "Notify: Project, Owner, and Creator";
						break;
					case TRIGGER_ACTION_NOTIFY_PROJECT:
						$type = "Notify: Project List ({$bugDatabase->lists['project'][$affect['fid']]['name']})";
						break;
					case TRIGGER_ACTION_NOTIFY_OWNER:
						$type = "Notify: Owner";
						break;
					case TRIGGER_ACTION_NOTIFY_CREATOR:
						$type = "Notify: Creator";
						break;
					case TRIGGER_ACTION_NOTIFY_OTHER:
						$type = htmlentities("Notify: User ({$bugDatabase->lists['user'][$affect['fid']]['name']})");
						break;
					case TRIGGER_ACTION_UPDATE_FIELD:
						$type = "Update {$affect['value']} to {$bugDatabase->lists['project'][$affect['fid']]['name']}";
						break;
					case TRIGGER_ACTION_DISABLE_TRIGGER:
						$type = "Disable trigger after run";
						break;
					case TRIGGER_ACTION_MODIFICATION:
						$type = "Modification Text: {$affect['value']}";
						break;
					default:
						$type = "Unknown Type {$affect['type']}";
				}
				$table .=  <<<EOT

			<tr>
				<td><a href="{$options['baseURL']}?area=admin&action=trigger_edit&sub=affect&num={$trigger['id']}&anum={$affect['id']}">{$affect['id']}</a></td>
				<td><b>{$affect['type']}</b>: {$type}</td>
				<td><a href="{$options['baseURL']}?area=admin&action=trigger_delete&sub=affect&num={$trigger['id']}&anum={$affect['id']}">[Delete]</a></td>
			</tr>
EOT;
			}
			$table .= <<<EOT

</table></td>
<td><a href="{$options['baseURL']}?area=admin&action=trigger_delete&sub=trigger&num={$trigger['id']}">[Delete]</a></td>

EOT;

			$table .= "</tr>\n";
		}
		return $table."</table>\n";
		/* Trigger Affect Table }}}3 */
	}
	return "No Triggers";
}
/* }}}2 */

/* function makeTriggerTable($type, $id) {{{2
   This function makes a table from the requested info */

/* }}}2 */

/* Trigger Functions }}}1 */

?>
Return current item: BugIn and Ticketing System