*
* Copyright 1999-2001, VA Linux Systems, Inc.
* Copyright 2002-2004, GForge, LLC
+ * Copyright 2009, Roland Mas
+ * Copyright 2009, Alcatel-Lucent
*
* This file is part of FusionForge.
*
* USA
*/
+/*
+ * Standard Alcatel-Lucent disclaimer for contributing to open source
+ *
+ * "The Artifact ("Contribution") has not been tested and/or
+ * validated for release as or in products, combinations with products or
+ * other commercial use. Any use of the Contribution is entirely made at
+ * the user's own responsibility and the user can not rely on any features,
+ * functionalities or performances Alcatel-Lucent has attributed to the
+ * Contribution.
+ *
+ * THE CONTRIBUTION BY ALCATEL-LUCENT IS PROVIDED AS IS, WITHOUT WARRANTY
+ * OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, COMPLIANCE,
+ * NON-INTERFERENCE AND/OR INTERWORKING WITH THE SOFTWARE TO WHICH THE
+ * CONTRIBUTION HAS BEEN MADE, TITLE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * ALCATEL-LUCENT BE LIABLE FOR ANY DAMAGES OR OTHER LIABLITY, WHETHER IN
+ * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * CONTRIBUTION OR THE USE OR OTHER DEALINGS IN THE CONTRIBUTION, WHETHER
+ * TOGETHER WITH THE SOFTWARE TO WHICH THE CONTRIBUTION RELATES OR ON A STAND
+ * ALONE BASIS."
+ */
+
require_once $gfcommon.'include/Error.class.php';
require_once $gfcommon.'tracker/ArtifactMessage.class.php';
require_once $gfcommon.'tracker/ArtifactExtraField.class.php';
+require_once $gfcommon.'tracker/ArtifactWorkflow.class.php';
// This string is used when sending the notification mail for identifying the
// user response
if ($data) {
//the db result handle was passed in
} else {
- $res=db_query("SELECT * FROM artifact_vw WHERE artifact_id='$artifact_id'");
+ $res = db_query_params ('SELECT * FROM artifact_vw WHERE artifact_id=$1',
+ array ($artifact_id)) ;
if (db_numrows($res) <1 ) {
$ARTIFACT_OBJ["_".$artifact_id."_"]=false;
return false;
//
// Only admins can post/modify private artifacts
//
- if (!$this->ArtifactType->userIsAdmin()) {
- $this->setError(_('Artifact: Only Artifact Admins Can Modify Private ArtifactTypes'));
- return false;
- }
+
+//
+// ape: Disabled, private means only restricted to members. So, no special rules #2503.
+// if (!$this->ArtifactType->userIsAdmin()) {
+// $this->setError(_('Artifact: Only Artifact Admins Can Modify Private ArtifactTypes'));
+// return false;
+// }
}
//
db_begin();
- $sql="INSERT INTO artifact
+ $res = db_query_params ('INSERT INTO artifact
(group_artifact_id,status_id,priority,
submitted_by,assigned_to,open_date,summary,details)
- VALUES
- ('".$this->ArtifactType->getID()."','$status_id','$priority',
- '$user','$assigned_to','". time() ."','". htmlspecialchars($summary)."','". htmlspecialchars($details)."')";
- $res=db_query($sql);
+ VALUES ($1,$2,$3,$4,$5,$6,$7,$8)',
+ array ($this->ArtifactType->getID(),
+ $status_id,
+ $priority,
+ $user,
+ $assigned_to,
+ time(),
+ htmlspecialchars($summary),
+ htmlspecialchars($details))) ;
if (!$res) {
$this->setError('Artifact: '.db_error());
db_rollback();
* @return boolean success.
*/
function fetchData($artifact_id) {
- $res=db_query("SELECT * FROM artifact_vw
- WHERE artifact_id='$artifact_id' AND group_artifact_id='".$this->ArtifactType->getID()."'");
+ $res = db_query_params ('SELECT * FROM artifact_vw WHERE artifact_id=$1 AND group_artifact_id=$2',
+ array ($artifact_id,
+ $this->ArtifactType->getID())) ;
if (!$res || db_numrows($res) < 1) {
$this->setError('Artifact: Invalid ArtifactID');
return false;
return false;
}
db_begin();
- $res = db_query("DELETE FROM artifact_extra_field_data WHERE artifact_id='".$this->getID()."'");
+ $res = db_query_params ('DELETE FROM artifact_extra_field_data WHERE artifact_id=$1',
+ array ($this->getID())) ;
if (!$res) {
$this->setError('Error deleting extra field data: '.db_error());
db_rollback();
return false;
}
- $res = db_query("DELETE FROM artifact_file WHERE artifact_id='".$this->getID()."'");
+ $res = db_query_params ('DELETE FROM artifact_file WHERE artifact_id=$1',
+ array ($this->getID())) ;
if (!$res) {
$this->setError('Error deleting file from db: '.db_error());
db_rollback();
return false;
}
- $res = db_query("DELETE FROM artifact_message WHERE artifact_id='".$this->getID()."'");
+ $res = db_query_params ('DELETE FROM artifact_message WHERE artifact_id=$1',
+ array ($this->getID())) ;
if (!$res) {
$this->setError('Error deleting message: '.db_error());
db_rollback();
return false;
}
- $res = db_query("DELETE FROM artifact_history WHERE artifact_id='".$this->getID()."'");
+ $res = db_query_params ('DELETE FROM artifact_history WHERE artifact_id=$1',
+ array ($this->getID())) ;
if (!$res) {
$this->setError('Error deleting history: '.db_error());
db_rollback();
return false;
}
- $res = db_query("DELETE FROM artifact_monitor WHERE artifact_id='".$this->getID()."'");
+ $res = db_query_params ('DELETE FROM artifact_monitor WHERE artifact_id=$1',
+ array ($this->getID())) ;
if (!$res) {
$this->setError('Error deleting monitor: '.db_error());
db_rollback();
return false;
}
- $res = db_query("DELETE FROM artifact WHERE artifact_id='".$this->getID()."'");
+ $res = db_query_params ('DELETE FROM artifact WHERE artifact_id=$1',
+ array ($this->getID())) ;
if (!$res) {
$this->setError('Error deleting artifact: '.db_error());
db_rollback();
}
if ($this->getStatusID() == 1) {
- $res = db_query("UPDATE artifact_counts_agg SET count=count-1,open_count=open_count-1
- WHERE group_artifact_id='".$this->getID()."'");
+ $res = db_query_params ('UPDATE artifact_counts_agg SET count=count-1,open_count=open_count-1
+ WHERE group_artifact_id=$1',
+ array ($this->getID())) ;
if (!$res) {
$this->setError('Error updating artifact_counts_agg (1): '.db_error());
db_rollback();
return false;
}
} elseif ($this->getStatusID() == 2) {
- $res = db_query("UPDATE artifact_counts_agg SET count=count-1
- WHERE group_artifact_id='".$this->getID()."'");
+ $res = db_query_params ('UPDATE artifact_counts_agg SET count=count-1
+ WHERE group_artifact_id=$1',
+ array ($this->getID())) ;
if (!$res) {
$this->setError('Error updating artifact_counts_agg (2): '.db_error());
db_rollback();
}
- $res=db_query("SELECT * FROM artifact_monitor
- WHERE artifact_id='". $this->getID() ."'
- AND user_id='$user_id'");
+ $res = db_query_params ('SELECT * FROM artifact_monitor WHERE artifact_id=$1 AND user_id=$2',
+ array ($this->getID(),
+ $user_id)) ;
if (!$res || db_numrows($res) < 1) {
//not yet monitoring
- $res=db_query("INSERT INTO artifact_monitor (artifact_id,user_id)
- VALUES ('". $this->getID() ."','$user_id')");
+ $res = db_query_params ('INSERT INTO artifact_monitor (artifact_id,user_id) VALUES ($1,$2)',
+ array ($this->getID(),
+ $user_id)) ;
if (!$res) {
$this->setError(db_error());
return false;
}
} else {
//already monitoring - remove their monitor
- db_query("DELETE FROM artifact_monitor
- WHERE artifact_id='". $this->getID() ."'
- AND user_id='$user_id'");
+ db_query_params ('DELETE FROM artifact_monitor
+ WHERE artifact_id=$1
+ AND user_id=$2',
+ array ($this->getID(),
+ $user_id)) ;
$this->setError(_('Artifact Monitoring Deactivated'));
return false;
}
if (!session_loggedin()) {
return false;
}
- $sql="SELECT count(*) AS count FROM artifact_monitor WHERE user_id='".user_getid()."' AND artifact_id='".$this->getID()."';";
- $result = db_query($sql);
+ $result = db_query_params ('SELECT count(*) AS count FROM artifact_monitor WHERE user_id=$1 AND artifact_id=$2',
+ array (user_getid(),
+ $this->getID())) ;
$row_count = db_fetch_array($result);
return $result && $row_count['count'] > 0;
}
* @return array of email addresses monitoring this Artifact.
*/
function getMonitorIds() {
- $res=db_query("SELECT user_id
- FROM artifact_monitor
- WHERE artifact_id='". $this->getID() ."'");
+ $res = db_query_params ('SELECT user_id FROM artifact_monitor WHERE artifact_id=$1',
+ array ($this->getID())) ;
return array_unique(array_merge($this->ArtifactType->getMonitorIds(),util_result_column_to_array($res)));
}
* @return database result set.
*/
function getHistory() {
- $sql="SELECT * ".
- "FROM artifact_history_user_vw ".
- "WHERE artifact_id='". $this->getID() ."' ".
- "ORDER BY entrydate DESC";
- return db_query($sql);
+ return db_query_params ('SELECT * FROM artifact_history_user_vw WHERE artifact_id=$1 ORDER BY entrydate DESC',
+ array ($this->getID())) ;
}
/**
* @return database result set.
*/
function getMessages() {
- $sql="select * ".
- "FROM artifact_message_user_vw ".
- "WHERE artifact_id='". $this->getID() ."' ORDER BY adddate DESC";
- return db_query($sql);
+ return db_query_params ('SELECT * FROM artifact_message_user_vw WHERE artifact_id=$1 ORDER BY adddate DESC',
+ array ($this->getID())) ;
}
/**
*/
function &getFiles() {
if (!isset($this->files)) {
- $sql="select * ".
- "FROM artifact_file_user_vw ".
- "WHERE artifact_id='". $this->getID() ."'";
- $res=db_query($sql);
+ $res = db_query_params ('SELECT id,artifact_id,description,filename,filesize,' .
+ 'filetype,adddate,submitted_by,user_name,realname
+ FROM artifact_file_user_vw WHERE artifact_id=$1',
+ array ($this->getID())) ;
$rows=db_numrows($res);
if ($rows > 0) {
for ($i=0; $i < $rows; $i++) {
*/
function getRelatedTasks() {
if (!$this->relatedtasks) {
- $this->relatedtasks=
- db_query("SELECT pt.group_project_id,pt.project_task_id,pt.summary,pt.start_date,pt.end_date,pgl.group_id
+ $this->relatedtasks = db_query_params ('SELECT pt.group_project_id,pt.project_task_id,pt.summary,pt.start_date,pt.end_date,pgl.group_id, pt.status_id
FROM project_task pt, project_group_list pgl
WHERE pt.group_project_id = pgl.group_project_id AND
EXISTS (SELECT project_task_id FROM project_task_artifact
WHERE project_task_id=pt.project_task_id
- AND artifact_id = ". $this->getID() . ")");
+ AND artifact_id = $1)',
+ array ($this->getID())) ;
}
return $this->relatedtasks;
}
* @param string The message being attached.
* @param string Email address of message creator.
* @param bool Whether to email out a followup.
- * @access private.
+ * @access private
* @return boolean success.
*/
function addMessage($body,$by=false,$send_followup=false) {
}
}
- $sql="insert into artifact_message (artifact_id,submitted_by,from_email,adddate,body) ".
- "VALUES ('". $this->getID() ."','$user_id','$by','". time() ."','". htmlspecialchars($body). "')";
- $res = db_query($sql);
+ $res = db_query_params ('INSERT INTO artifact_message (artifact_id,submitted_by,from_email,adddate,body) VALUES ($1,$2,$3,$4,$5)',
+ array ($this->getID(),
+ $user_id,
+ $by,
+ time(),
+ htmlspecialchars($body))) ;
if ($send_followup) {
$this->mailFollowup(2,false);
}
*
* @param string The name of the field in the database being modified.
* @param string The former value of this field.
- * @access private.
+ * @access private
* @return boolean success.
*/
function addHistory($field_name,$old_value) {
} else {
$user=user_getid();
}
- $sql="insert into artifact_history(artifact_id,field_name,old_value,mod_by,entrydate)
- VALUES ('". $this->getID() ."','$field_name','".addslashes($old_value)."','$user','". time() ."')";
- return db_query($sql);
+ return db_query_params ('INSERT INTO artifact_history(artifact_id,field_name,old_value,mod_by,entrydate) VALUES ($1,$2,$3,$4,$5)',
+ array ($this->getID(),
+ $field_name,
+ addslashes($old_value),
+ $user,
+ time())) ;
}
/**
* @param string Attaching another comment.
* @param int Allows you to move an artifact to another type.
* @param array Array of extra fields like: array(15=>'foobar',22=>'1');
+ * @param string The description.
* @return boolean success.
*/
function update($priority,$status_id,
- $assigned_to,$summary,$canned_response,$details,$new_artifact_type_id,$extra_fields=array()) {
+ $assigned_to,$summary,$canned_response,$details,$new_artifact_type_id,
+ $extra_fields=array(), $description='') {
/*
Field-level permission checking
} else {
//everyone else cannot modify these fields
$priority=$this->getPriority();
- $summary=addslashes($this->getSummary());
+ $summary=htmlspecialchars_decode($this->getSummary());
+ $description=htmlspecialchars_decode($this->getDetails());
$canned_response=100;
$new_artifact_type_id=$this->ArtifactType->getID();
$assigned_to=$this->getAssignedTo();
}
+ // Check that assigned_to is member of the project.
+ if ($assigned_to != 100) {
+ $res = $this->ArtifactType->getTechnicians();
+ $arr =& util_result_column_to_array($res,0);
+ if (!in_array($assigned_to, $arr)) {
+ $this->setError("Invalid assigned_to (assigned person is not a technician)");
+ return false;
+ }
+ }
+
// Array to record which properties were changed
$changes = array();
$update = false;
//
// Get a lock on this row in the database
//
- $lock=db_query("SELECT * FROM artifact WHERE artifact_id='".$this->getID()."' FOR UPDATE");
+ $lock = db_query_params ('SELECT * FROM artifact WHERE artifact_id=$1 FOR UPDATE',
+ array ($this->getID())) ;
$artifact_type_id = $this->ArtifactType->getID();
//
// Attempt to move this Artifact to a new ArtifactType
return false;
}
- //
- // Now set Assigned to 100 in the new ArtifactType
- //
- $status_id=1;
- $assigned_to='100';
+ // Add a message to explain that the tracker was moved.
+ $message = 'Moved from '.$this->ArtifactType->getName().' to '.$newArtifactType->getName();
+ $this->addHistory('type', $this->ArtifactType->getName());
+ $this->addMessage($message,'',0);
+
+ // Fake change to send a mail when moved.
+ $changes['Type'] = 1;
+
+ // Try to remap extra_fields values when possible.
+ // If there is an extra_field with the same alias
+ // and if the value exist in the new one, then recode
+ // the value to keep it.
+ $new_extra_fields = array();
+ $ef = $this->ArtifactType->getExtraFields();
+ $ef_new = $newArtifactType->getExtraFields();
+ foreach($extra_fields as $extra_id => $value) {
+ $alias = $ef[$extra_id]['alias'];
+ $type = $ef[$extra_id]['field_type'];
+
+ // Search if there is an extra field with the same alias.
+ $new_id = 0;
+ foreach($ef_new as $id => $arr) {
+ if ($arr['alias'] == $alias) {
+ $new_id = $id;
+ }
+ }
+
+ // If we found one, copy for simple fields or
+ // search if there is the same value.
+ if ($new_id) {
+ if ($type == ARTIFACT_EXTRAFIELDTYPE_TEXT ||
+ $type == ARTIFACT_EXTRAFIELDTYPE_INTEGER ||
+ $type == ARTIFACT_EXTRAFIELDTYPE_TEXTAREA ||
+ $type == ARTIFACT_EXTRAFIELDTYPE_RELATION) {
+ $new_extra_fields[$new_id] = $value;
+ } else {
+ $values = $newArtifactType->getExtraFieldElements($new_id);
+ if (is_array($value)) {
+ foreach($value as $v) {
+ $v = $this->ArtifactType->getElementName($v);
+ foreach($values as $ev) {
+ if ($ev['element_name'] == $v) {
+ $new_extra_fields[$new_id][] = $ev['element_id'];
+ }
+ }
+ }
+ } else {
+ $value = $this->ArtifactType->getElementName($value);
+ foreach($values as $ev) {
+ if ($ev['element_name'] == $value) {
+ $new_extra_fields[$new_id] = $ev['element_id'];
+ }
+ }
+ }
+ }
+ }
+ }
+
+ // Special case if moving to a tracker with custom status (previous has not).
+ $custom_status_id = $newArtifactType->getCustomStatusField();
+ if ($custom_status_id && !$new_extra_fields[$custom_status_id]) {
+ $atw = new ArtifactWorkflow($newArtifactType, $custom_status_id);
+ $nodes = $atw->getNextNodes(100);
+ if ($nodes) {
+ $new_extra_fields[$custom_status_id] = $nodes[0];
+ }
+ }
+ $extra_fields = $new_extra_fields;
+
+ $res = db_query_params ('DELETE FROM artifact_extra_field_data WHERE artifact_id=$1',
+ array ($this->getID()));
+ if (!$res) {
+ $this->setError('Removal of old artifact_extra_field_data failed: '.db_error());
+ db_rollback();
+ return false;
+ }
+
+ // Check that assigned_to is member of the project.
+ if ($assigned_to != 100) {
+ $res = $newArtifactType->getTechnicians();
+ $arr =& util_result_column_to_array($res,0);
+ if (!in_array($assigned_to, $arr)) {
+ $assigned_to = 100;
+ }
+ }
+
//can't send a canned response when changing ArtifactType
$canned_response=100;
$this->ArtifactType =& $newArtifactType;
$update = true;
-
- //
- // This is a major problem - the extra fields
- // are completely different IDs, and may not even
- // exist in the new tracker. All extra_fields will be deleted and
- // then set to 100 in the new tracker.
- //
- $res=db_query("DELETE FROM artifact_extra_field_data WHERE artifact_id='".$this->getID()."'");
- $extra_fields=array();
}
-
-
- $sqlu='';
-
//
- // handle audit trail & build SQL statement
+ // handle audit trail
//
+ $close_date = $this->getCloseDate();
if ($this->getStatusID() != $status_id) {
$this->addHistory('status_id',$this->getStatusID());
- $sqlu .= " status_id='$status_id', ";
$changes['status'] = 1;
$update = true;
- // Reset the close_date if bug is re-opened
- // (otherwise stat reports will be wrong).
- if ($status_id == 1) {
- $sqlu .= " close_date='0', ";
- $this->addHistory('close_date',0);
+ if ($status_id != 1) {
+ $close_date = time () ;
+ } else {
+ $close_date = 0 ;
}
+ $this->addHistory('close_date', $this->getCloseDate());
}
if ($this->getPriority() != $priority) {
$this->addHistory('priority',$this->getPriority());
- $sqlu .= " priority='$priority', ";
$changes['priority'] = 1;
$update = true;
}
if ($this->getAssignedTo() != $assigned_to) {
$this->addHistory('assigned_to',$this->getAssignedTo());
- $sqlu .= " assigned_to='$assigned_to', ";
$changes['assigned_to'] = 1;
$update = true;
}
- if ($summary && (addslashes($this->getSummary()) != htmlspecialchars($summary))) {
- $this->addHistory('summary', addslashes($this->getSummary()));
- $sqlu .= " summary='". htmlspecialchars($summary) ."', ";
+ if ($summary && ($this->getSummary() != htmlspecialchars($summary))) {
+ $this->addHistory('summary', $this->getSummary());
$changes['summary'] = 1;
$update = true;
}
-
+ if ($description && ($this->getDetails() != htmlspecialchars($description))) {
+ $this->addHistory('details', $this->getDetails());
+ $changes['details'] = 1;
+ $update = true;
+ }
if ($details) {
$this->addMessage($details,'',0);
$changes['details'] = 1;
$send_message=true;
}
- //
- // Enter the timestamp if we are changing to closed
- //
- if ($status_id != 1) {
- $now=time();
- $sqlu .= " close_date='$now', ";
- $this->addHistory('close_date',$now);
- $update = true;
- }
-
/*
Finally, update the artifact itself
*/
if ($update){
- $sql = "UPDATE artifact
+ $result = db_query_params ('UPDATE artifact
SET
- $sqlu
- group_artifact_id='$new_artifact_type_id'
+ status_id=$1,
+ priority=$2,
+ assigned_to=$3,
+ summary=$4,
+ details=$5,
+ close_date=$6,
+ group_artifact_id=$7
WHERE
- artifact_id='". $this->getID() ."'
- AND group_artifact_id='$artifact_type_id'";
- $result=db_query($sql);
+ artifact_id=$8 AND group_artifact_id=$9',
+ array ($status_id,
+ $priority,
+ $assigned_to,
+ htmlspecialchars($summary),
+ htmlspecialchars($description),
+ $close_date,
+ $new_artifact_type_id,
+ $this->getID(),
+ $artifact_type_id)) ;
if (!$result || db_affected_rows($result) < 1) {
$this->setError('Error - update failed!'.db_error());
}
if ($update || $send_message){
- /*
- now send the email
- */
- $this->mailFollowup(2, false, $changes);
+ if (!empty($changes)) {
+ // Send the email with changes
+ $this->mailFollowup(2, false, $changes);
+ }
db_commit();
return true;
} else {
$ef = $this->ArtifactType->getExtraFields();
$efk=array_keys($ef);
+ // If there is a status field, then check against the workflow.
+ for ($i=0; $i<count($efk); $i++) {
+ $efid=$efk[$i];
+ $type=$ef[$efid]['field_type'];
+ if ($type == ARTIFACT_EXTRAFIELDTYPE_STATUS) {
+ // Get previous value.
+
+ $res = db_query_params ('SELECT field_data FROM artifact_extra_field_data
+ WHERE artifact_id=$1 AND extra_field_id=$2',
+ array($this->getID(),
+ $efid));
+ $old = (db_numrows($res)>0) ? db_result($res,0,'field_data') : 100;
+ if ($old != $extra_fields[$efid]) {
+ $atw = new ArtifactWorkflow($this->ArtifactType, $efid);
+ if (!$atw->checkEvent($old, $extra_fields[$efid])) {
+ $this->setError('Workflow error: You are not authorized to change the Status');
+ return false;
+ }
+ }
+ }
+ }
+
//now we'll update this artifact for each extra field
for ($i=0; $i<count($efk); $i++) {
$efid=$efk[$i];
$type=$ef[$efid]['field_type'];
+ // check required fields
+ if ($ef[$efid]['is_required']) {
+ if (!array_key_exists($efid, $extra_fields)) {
+ if ($type == ARTIFACT_EXTRAFIELDTYPE_STATUS) {
+ $this->setError('Status Custom Field Must Be Set');
+ }
+ else {
+ $this->setMissingParamsError($ef[$efid]['field_name']);
+ }
+ return false;
+ }
+ else {
+ if ($extra_fields[$efid] === '') {
+ if ($type == ARTIFACT_EXTRAFIELDTYPE_STATUS) {
+ $this->setError('Status Custom Field Must Be Set');
+ }
+ else {
+ $this->setMissingParamsError($ef[$efid]['field_name']);
+ }
+ return false;
+ }
+ else {
+ if (($type == ARTIFACT_EXTRAFIELDTYPE_SELECT || $type == ARTIFACT_EXTRAFIELDTYPE_RADIO) &&
+ $extra_fields[$efid] == '100') {
+ $this->setMissingParamsError($ef[$efid]['field_name']);
+ return false;
+ }
+ elseif (($type == ARTIFACT_EXTRAFIELDTYPE_MULTISELECT || $type == ARTIFACT_EXTRAFIELDTYPE_CHECKBOX) &&
+ (count($extra_fields[$efid]) == 1 && $extra_fields[$efid][0] == '100')) {
+ $this->setMissingParamsError($ef[$efid]['field_name']);
+ return false;
+ }
+ }
+ }
+ }
//
// Force each field to have some value if it is a numeric field
// text fields will just be purged and skipped
//
- if (!array_key_exists($efid, $extra_fields) || !$extra_fields[$efid]) {
- if ($type == ARTIFACT_EXTRAFIELDTYPE_STATUS) {
- $this->setError('Status Custom Field Must Be Set');
- return false;
- } elseif (($type == ARTIFACT_EXTRAFIELDTYPE_SELECT) || ($type == ARTIFACT_EXTRAFIELDTYPE_RADIO)) {
+ if (!array_key_exists($efid, $extra_fields) || $extra_fields[$efid] === '') {
+ if (($type == ARTIFACT_EXTRAFIELDTYPE_SELECT) || ($type == ARTIFACT_EXTRAFIELDTYPE_RADIO)) {
$extra_fields[$efid]='100';
} elseif (($type == ARTIFACT_EXTRAFIELDTYPE_MULTISELECT) || ($type == ARTIFACT_EXTRAFIELDTYPE_CHECKBOX)) {
$extra_fields[$efid]=array('100');
} else {
- $resdel=db_query("DELETE FROM artifact_extra_field_data
- WHERE
- artifact_id='".$this->getID()."'
- AND extra_field_id='".$efid."'");
+ $resdel = db_query_params ('DELETE FROM artifact_extra_field_data WHERE artifact_id=$1 AND extra_field_id=$2',
+ array ($this->getID(),
+ $efid)) ;
continue;
}
}
//
// get the old rows of data
//
- $resd=db_query("SELECT * FROM artifact_extra_field_data
- WHERE
- artifact_id='".$this->getID()."'
- AND extra_field_id='".$efid."'");
+ $resd = db_query_params ('SELECT * FROM artifact_extra_field_data WHERE artifact_id=$1 AND extra_field_id=$2',
+ array ($this->getID(),
+ $efid)) ;
$rows=db_numrows($resd);
if ($resd && $rows) {
//
if (!empty($added_values) || !empty($deleted_values)) { // there are differences...
$field_name = $ef[$efid]['field_name'];
- $changes["extra_fields"][$efid] = 1;
-
- // Do a history entry only for deleted values
- if (!empty($deleted_values)) {
- $this->addHistory($field_name, $this->ArtifactType->getElementName($deleted_values));
+ if (!preg_match('/^@/', $ef[$efid]['alias'])) {
+ $changes["extra_fields"][$efid] = 1;
}
-
- $resdel=db_query("DELETE FROM artifact_extra_field_data
- WHERE
- artifact_id='".$this->getID()."'
- AND extra_field_id='".$efid."'");
+ $this->addHistory($field_name, $this->ArtifactType->getElementName(array_reverse($old_values)));
+
+ $resdel = db_query_params ('DELETE FROM artifact_extra_field_data WHERE artifact_id=$1 AND extra_field_id=$2',
+ array ($this->getID(),
+ $efid)) ;
} else {
continue;
}
} else {
//element DID change - do a history entry
$field_name = $ef[$efid]['field_name'];
- $changes["extra_fields"][$efid] = 1;
- $resdel=db_query("DELETE FROM artifact_extra_field_data
- WHERE
- artifact_id='".$this->getID()."'
- AND extra_field_id='".$efid."'");
+ if (!preg_match('/^@/', $ef[$efid]['alias'])) {
+ $changes["extra_fields"][$efid] = 1;
+ }
+ $resdel = db_query_params ('DELETE FROM artifact_extra_field_data WHERE artifact_id=$1 AND extra_field_id=$2',
+ array ($this->getID(),
+ $efid)) ;
+
+ // Adding history with previous value.
if (($type == ARTIFACT_EXTRAFIELDTYPE_SELECT) || ($type == ARTIFACT_EXTRAFIELDTYPE_RADIO) || ($type == ARTIFACT_EXTRAFIELDTYPE_STATUS)) {
-//don't add history for text fields
$this->addHistory($field_name,$this->ArtifactType->getElementName(db_result($resd,0,'field_data')));
+ } else {
+ $this->addHistory($field_name, db_result($resd,0,'field_data'));
}
}
} else {
//no history for this extra field exists
}
+
+ //
+ // Some rewrite & consistency checks on the relation type field.
+ //
+ // 1) Convert syntax [#NNN] to NNN
+ // 2) Allow multiple spaces as separator.
+ // 3) Ensure that only integers are given.
+ // 4) Ensure that id corresponds to valid tracker id.
+ //
+ if ($type == ARTIFACT_EXTRAFIELDTYPE_RELATION) {
+ $value = preg_replace('/\[\#(\d+)\]/', "\\1", trim($extra_fields[$efid]));
+ $value = preg_replace('/\\s+/', ' ', $value);
+ $new = '';
+ foreach (explode(' ',$value) as $id) {
+ if (preg_match('/^(\d+)$/', $id)) {
+ // Control that the id is present in the db
+
+ $res = db_query_params ('SELECT artifact_id FROM artifact WHERE artifact_id=$1',
+ array($id));
+ if (db_numrows($res) == 1) {
+ $new .= $id.' ';
+ } else {
+ $this->setError('Illegal id '.$id.', it\'s not a valid tracker id for field: '.$ef[$efid]['field_name'].'.'); // @todo: lang
+ return false;
+ }
+ } else {
+ $this->setError('Illegal value '.$id.', only trackers id are allowed for field: '.$ef[$efid]['field_name'].'.'); // @todo: lang
+ return false;
+ }
+ }
+ $extra_fields[$efid] = trim($new);
+ }
+
+ // Ensure that only integer are allowed for type ARTIFACT_EXTRAFIELDTYPE_INTEGER
+ if ($type == ARTIFACT_EXTRAFIELDTYPE_INTEGER) {
+ $extra_fields[$efid] = trim($extra_fields[$efid]);
+ if (!preg_match('/^[-+]?(\d+)$/', $extra_fields[$efid])) {
+ $this->setError('Illegal value '.$extra_fields[$efid].' for field '.$ef[$efid]['field_name'].': Only integer is allowed.');
+ return false;
+ }
+ if ($extra_fields[$efid] < -2147483648 || $extra_fields[$efid] > 2147483647) {
+ $this->setError('Illegal value '.$extra_fields[$efid].' for field '.$ef[$efid]['field_name'].': Integer out of range (-2147483648 to +2147483647).');
+ return false;
+ }
+ $extra_fields[$efid] = intval($extra_fields[$efid]);
+ }
+
//
// See if anything was even passed for this extra_field_id
//
- if (!$extra_fields[$efid]) {
+ if ($extra_fields[$efid] === '') {
//nothing in field to update - text fields may be blank
} else {
//determine the type of field and whether it should have multiple rows supporting it
$multi_rows=true;
$count=count($extra_fields[$efid]);
for ($fin=0; $fin<$count; $fin++) {
- $sql="INSERT INTO artifact_extra_field_data (artifact_id,extra_field_id,field_data)
- values ('".$this->getID()."','".$efid."',
- '".$extra_fields[$efid][$fin]."')";
- $res=db_query($sql);
+ $res = db_query_params ('INSERT INTO artifact_extra_field_data (artifact_id,extra_field_id,field_data) VALUES ($1,$2,$3)',
+ array ($this->getID(),
+ $efid,
+ $extra_fields[$efid][$fin])) ;
if (!$res) {
- $this->setError('Artifact::updateExtraFields:: '.$sql.db_error());
+ $this->setError(db_error());
return false;
}
}
} else {
$multi_rows=false;
$count=1;
- $res=db_query("INSERT INTO artifact_extra_field_data (artifact_id,extra_field_id,field_data)
- values ('".$this->getID()."','".$efid."',
- '".htmlspecialchars($extra_fields[$efid])."')");
+ $res = db_query_params ('INSERT INTO artifact_extra_field_data (artifact_id,extra_field_id,field_data) VALUES ($1,$2,$3)',
+ array ($this->getID(),
+ $efid,
+ htmlspecialchars($extra_fields[$efid]))) ;
if (!$res) {
- $this->setError('Artifact::updateExtraFields:: '.db_error());
+ $this->setError(db_error());
return false;
}
}
function &getExtraFieldData() {
if (!isset($this->extra_field_data)) {
$this->extra_field_data = array();
- $res=db_query("SELECT * FROM artifact_extra_field_data
- WHERE artifact_id='".$this->getID()."' ORDER BY extra_field_id");
+ $res = db_query_params ('SELECT * FROM artifact_extra_field_data WHERE artifact_id=$1 ORDER BY extra_field_id',
+ array ($this->getID())) ;
$ef = $this->ArtifactType->getExtraFields();
while ($arr = db_fetch_array($res)) {
$type=$ef[$arr['extra_field_id']]['field_type'];
* @param int (1) initial/creation (2) update.
* @param array Array of additional addresses to mail to.
* @param array Array of fields changed in this update .
- * @access private.
+ * @access private
* @return boolean success.
*/
function mailFollowup($type, $more_addresses=false, $changes='') {
+
+ $monitor_ids = array();
+
if (!$changes) {
$changes=array();
}
"&group_id=". $this->ArtifactType->Group->getID()) .
"\nOr by replying to this e-mail entering your response between the following markers: ".
"\n".ARTIFACT_MAIL_MARKER.
- "\n(enter your response here)".
+ "\n(enter your response here, only in plain text format)".
"\n".ARTIFACT_MAIL_MARKER.
"\n\n".
$this->marker('status',$changes).
}
}
-// print($body);
-
//now remove all duplicates from the email list
if (count($emails) > 0) {
$BCC=implode(',',array_unique($emails));
foreach ($efs as $efid => $ef) {
$name = $ef["field_name"];
+ $type = $ef["field_type"];
// Get the value according to the type
- switch ($ef["field_type"]) {
+ switch ($type) {
- // for these types, the associated value comes straight
- case ARTIFACT_EXTRAFIELDTYPE_TEXT:
- case ARTIFACT_EXTRAFIELDTYPE_TEXTAREA:
- $value = isset($efd[$efid]) ? $efd[$efid]: '';
- break;
-
- // the other types have and ID or an array of IDs associated to them
- default:
- $value = $this->ArtifactType->getElementName($efd[$efid]);
+ // for these types, the associated value comes straight
+ case ARTIFACT_EXTRAFIELDTYPE_TEXT:
+ case ARTIFACT_EXTRAFIELDTYPE_TEXTAREA:
+ case ARTIFACT_EXTRAFIELDTYPE_RELATION:
+ case ARTIFACT_EXTRAFIELDTYPE_INTEGER:
+ if (isset($efd[$efid])) {
+ $value = $efd[$efid];
+ } else {
+ $value = '';
+ }
+ break;
+
+ // the other types have and ID or an array of IDs associated to them
+ default:
+ if (isset($efd[$efid])) {
+ $value = $this->ArtifactType->getElementName($efd[$efid]);
+ } else {
+ $value = 'None';
+ }
}
- $return[$efid] = array("name" => $name, "value" => $value);
+ $return[$efid] = array("name" => $name, "value" => $value, 'type' => $type);
}
return $return;