/** * Update an artifact. Rk: vfl is an variable list of fields, Vary from one project to another * return true if artifact updated, false if nothing changed or DB update failed * * @param artifact_id_dependent: artifact dependencies * @param canned_response: canned responses * @param changes (OUT): array of changes (for notifications) * * @return boolean */ function handleUpdate($artifact_id_dependent, $canned_response, &$changes, $masschange = false, $vfl = false, $import = false) { global $art_field_fact, $HTTP_POST_VARS, $Language; if ($masschange && !$this->ArtifactType->userIsAdmin()) { exit_permission_denied(); } if (!$import) { // Retrieve HTTP GET variables and store them in $vfl array $vfl = $art_field_fact->extractFieldList(); // make sure required fields are not empty if ($art_field_fact->checkEmptyFields($vfl) == false) { exit_missing_param(); } } //get this artifact from the db $result = $this->getFieldsValues(); // // See which fields changed during the modification // and if we must keep history then do it. Also add them to the update // statement // $reference_manager =& ReferenceManager::instance(); $text_value_list = array(); $changes = array(); $upd_list = ''; reset($vfl); while (list($field_name, $value) = each($vfl)) { $field = $art_field_fact->getFieldFromName($field_name); // skip over special fields except for details which in this // particular case can be processed normally if ($field->isSpecial()) { continue; } if ($field->isInt() && $value == '' && $field->getRequired() == 0) { $value = 0; } // we check if the given value is authorized for this field (for select box fields only) // we don't check here the none value, we have already check it before (we can't check here the none value because the function checkValueInPredefinedValues don't take the none value into account) // if the value did not change, we don't do the check (because of stored values that can be deleted now) if (!$masschange && $result[$field_name] != $value && $field->isSelectBox() && $value != 100 && !$field->checkValueInPredefinedValues($this->ArtifactType->getID(), $value)) { $this->setError($Language->getText('tracker_common_artifact', 'bad_field_value', array($field->getLabel(), $value))); return false; } if (!$masschange && $field->isMultiSelectBox()) { if (is_array($value)) { foreach ($value as $a_value) { if ($a_value != 100 && !$field->checkValueInPredefinedValues($this->ArtifactType->getID(), $a_value)) { $this->setError($Language->getText('tracker_common_artifact', 'bad_field_value', array($field->getLabel(), $value))); return false; } } } } $is_text = $field->isTextField() || $field->isTextArea(); if ($field->isMultiSelectBox() && is_array($value)) { if ($masschange && in_array($Language->getText('global', 'unchanged'), $value)) { continue; } // The field is a multi values field and it has multi assigned values $values = $value; // check if the user can update the field or not if (!$field->userCanUpdate($this->ArtifactType->getGroupID(), $this->ArtifactType->getID(), user_getid())) { // we only throw an error if the values has changed $old_values = $field->getValues($this->getID()); list($deleted_values, $added_values) = util_double_diff_array($old_values, $values); if (count($deleted_values) > 0 || count($added_values) > 0) { // The user does not have the permissions to update the current field, // we exit the function with an error message $this->setError($Language->getText('tracker_common_artifact', 'bad_field_permission_update', $field->getLabel())); return false; } } //don't take into account the none value if there are several values selected if (count($values) > 1) { $temp = array(); while (list($i, $v) = each($values)) { if ($v == 100) { unset($values[$i]); $unset = true; } else { $temp[] = $v; } } if (isset($unset) && $unset) { $values = $temp; } } $old_values = $field->getValues($this->getID()); list($deleted_values, $added_values) = util_double_diff_array($old_values, $values); // Check if there are some differences if (count($deleted_values) > 0 || count($added_values) > 0) { // Add values in the history $a = $field->getLabelValues($this->ArtifactType->getID(), $old_values); $val = join(",", $a); $b = $field->getLabelValues($this->ArtifactType->getID(), $values); $new_val = join(",", $b); $this->addHistory($field, $val, $new_val); // Update the field value if (!$field->updateValues($this->getID(), $values)) { $GLOBALS['Response']->addFeedback('error', $Language->getText('tracker_common_artifact', 'field_upd_fail', $field->getLabel())); } if ($is_text) { //Log for Cross references $text_value_list[] = $values; } // Keep track of the change $field_html = new ArtifactFieldHtml($field); if (count($deleted_values) > 0) { $val = join(",", $field->getLabelValues($this->ArtifactType->getID(), $deleted_values)); $changes[$field_name]['del'] = $val; } if (count($added_values) > 0) { $val = join(",", $field->getLabelValues($this->ArtifactType->getID(), $added_values)); $changes[$field_name]['add'] = $val; } } } else { if ($masschange && $value == $Language->getText('global', 'unchanged')) { continue; } $old_value = $result[$field_name]; if ($is_text) { $differ = $old_value != htmlspecialchars($value); //Log for Cross references $text_value_list[] = $value; } else { if ($field->isDateField()) { // if it's a date we must convert the format to unix time if ($value != '') { list($value, $ok) = util_date_to_unixtime($value); } else { $value = '0'; } //first have a look if both dates are uninitialized if (($old_value == 0 || $old_value == '') && ($value == 0 || !$ok)) { $differ = false; } else { // and make also sure that the old_value has been treated as the new value // i.e. old_value (unix timestamp) -> local date (with hours cut off, so change the date by x hours) -> unixtime $old_date = format_date("Y-m-j", $old_value); list($old_val, $ok) = util_date_to_unixtime($old_date); $differ = $old_val != $value; } } else { $differ = $old_value != $value; } } if ($differ) { // The userCanUpdate test is only done on modified fields if ($field->userCanUpdate($this->ArtifactType->getGroupID(), $this->ArtifactType->getID(), user_getid())) { if ($is_text) { if ($field->isStandardField()) { $upd_list .= "{$field_name}='" . db_es(htmlspecialchars($value)) . "',"; } else { $update_value = htmlspecialchars($value); } $this->addHistory($field, $old_value, $value); $value = stripslashes($value); } else { if ($field->isStandardField()) { $upd_list .= "{$field_name}='" . db_es($value) . "',"; } else { $update_value = $value; } $this->addHistory($field, $old_value, $value); } // Update the field value if (!$field->isStandardField()) { if (!$field->updateValue($this->getID(), $update_value)) { $GLOBALS['Response']->addFeedback('error', $Language->getText('tracker_common_artifact', 'field_upd_fail', $field->getLabel())); } } // Keep track of the change $field_html = new ArtifactFieldHtml($field); $changes[$field_name]['del'] = $field_html->display($this->ArtifactType->getID(), $old_value, false, false, true, true); $changes[$field_name]['add'] = $field_html->display($this->ArtifactType->getID(), $value, false, false, true, true); } else { // The user does not have the permissions to update the current field, // we exit the function with an error message $this->setError($Language->getText('tracker_common_artifact', 'bad_field_permission_update', $field->getLabel())); return false; } } } } // while for ($i = 0; $i < sizeof($text_value_list); $i++) { $reference_manager->extractCrossRef($text_value_list[$i], $this->getID(), ReferenceManager::REFERENCE_NATURE_ARTIFACT, $this->ArtifactType->getGroupID()); } $request = HTTPRequest::instance(); //for masschange look at the special case of changing the submitted_by param if ($masschange) { reset($HTTP_POST_VARS); while (list($key, $val) = each($HTTP_POST_VARS)) { $val = $request->get($key); //Don't use HTTP_POST_VARS if ($key == 'submitted_by' && $val != $Language->getText('global', 'unchanged')) { $sql = "UPDATE artifact SET submitted_by=" . db_ei($val) . " WHERE artifact_id = " . db_ei($this->getID()); $res = db_query($sql); $field = $art_field_fact->getFieldFromName('submitted_by'); if ($this->getSubmittedBy() != $val) { $this->addHistory('submitted_by', $this->getSubmittedBy(), $val); } } } } // Comment field history is handled a little differently. Followup comments // are added in the bug history along with the comment type. // // If a canned response is given it overrides anything typed in the followup // comment text area. $comment = $request->get('comment'); $comment_type_id = array_key_exists('comment_type_id', $vfl) ? $vfl['comment_type_id'] : ''; $vFormat = new Valid_WhiteList('comment_format', array(self::FORMAT_HTML, self::FORMAT_TEXT)); $comment_format = $request->getValidated('comment_format', $vFormat, self::FORMAT_TEXT); $this->addFollowUpComment($comment, $comment_type_id, $canned_response, $changes, $comment_format); // // Enter the timestamp if we are changing to closed or declined // if (isset($changes['status_id']) && $this->isStatusClosed($vfl['status_id'])) { $now = time(); $upd_list .= "close_date='{$now}',"; $field = $art_field_fact->getFieldFromName('close_date'); if ($field) { $this->addHistory($field, $result['close_date'], ''); } } // // Reset the timestamp if we are changing from closed or declined // if (isset($changes['status_id']) && !$this->isStatusClosed($vfl['status_id'])) { $upd_list .= "close_date='',"; $field = $art_field_fact->getFieldFromName('close_date'); if ($field) { $this->addHistory($field, $result['close_date'], ''); } } // // Insert the list of dependencies // if ($import && $artifact_id_dependent) { if (!$this->deleteAllDependencies()) { return false; } if ($artifact_id_dependent == $Language->getText('global', 'none')) { unset($artifact_id_dependent); } } if (isset($artifact_id_dependent)) { if (!$this->addDependencies($artifact_id_dependent, $changes, $masschange, $import)) { return false; } } // // Finally, build the full SQL query and update the artifact itself (if need be) // $res_upd = true; if ($upd_list) { // strip the excess comma at the end of the update field list $upd_list = substr($upd_list, 0, -1); $sql = "UPDATE artifact SET {$upd_list} " . " WHERE artifact_id=" . db_ei($this->getID()); $res_upd = db_query($sql); } if (!$res_upd) { exit_error($Language->getText('tracker_common_artifact', 'upd_fail') . ': ' . $sql, $Language->getText('tracker_common_artifact', 'upd_fail')); return false; } else { if (!$request->exist('change_permissions') || $request->get('change_permissions')) { $this->setPermissions($request->get('use_artifact_permissions_name'), $request->get('ugroups')); } return true; } }
break; case 'show_one_user': // Prepare params $urlParam = ''; echo '<h2>' . $GLOBALS['Language']->getText('plugin_statistics_show_one_user', 'user_growth') . '</h2>'; echo '<form name="progress_by_user" method="get" action="?">'; echo '<input type="hidden" name="func" value="show_one_user" />'; echo '<label>User: </label>'; echo '<input type="text" name="user_id" id="plugin_statistics_project" value="' . $userId . '" />'; echo '<label>Group by:</label>'; echo html_build_select_box_from_array($groupByDate, 'group_by', $selectedGroupByDate, 1) . '<br />'; echo '<label>Start: </label>'; list($timestamp, ) = util_date_to_unixtime($startDate); echo html_field_date('start_date', $startDate, false, 10, 10, 'progress_by_user', false) . ' <em>' . html_time_ago($timestamp) . '</em><br />'; echo '<label>End: </label>'; list($timestamp, ) = util_date_to_unixtime($endDate); echo html_field_date('end_date', $endDate, false, 10, 10, 'progress_by_user', false) . ' <em>' . html_time_ago($timestamp) . '</em><br />'; $sel = ''; if ($relative) { $sel = ' checked="checked"'; $urlParam .= '&relative=true'; } echo '<input type="checkbox" name="relative" value="true" ' . $sel . '/>'; echo '<label>Relative Y-axis (depend of data set values):</label><br/>'; echo '<input type="submit" value="' . $GLOBALS['Language']->getText('global', 'btn_submit') . '"/>'; echo '</form>'; if ($userId && $startDate && $endDate) { echo '<h3>' . $GLOBALS['Language']->getText('plugin_statistics_show_one_user', 'user_detail') . '</h3>'; $duHtml->getUserDetails($userId); $urlParam .= 'start_date=' . $startDate . '&end_date=' . $endDate; $urlParam .= '&group_by=' . $selectedGroupByDate;
function _getStartStatement($value) { $stmt = ''; list($time, $ok) = util_date_to_unixtime($value); if ($ok) { list($year, $month, $day) = util_date_explode($value); $time_after = mktime(0, 0, 0, $month, $day + 1, $year); $stmt = $this->field . " >= " . $time_after; } return $stmt; }
/** * Return the value to find for a field, for the current query * * @param field: the field object * @param prefs: field values array (HTTP GET variable) * @param field_value: the field name * @param advsrch: advance search or simple search * @param notany: is true if the value of the field is not "Any" * * @return string */ function getValuesWhereClause($field, $prefs, $field_name, $advsrch, &$notany) { $notany = true; $where = ''; //echo $field_name."->prefs[".$field->getName()."]=".$prefs[$field->getName()][0]."<br>"; if (($field->isSelectBox() || $field->isMultiSelectBox()) && (isset($prefs[$field->getName()]) && !$this->isvarany($prefs[$field->getName()]))) { // Only select box criteria to where clause if argument is not ANY return " AND " . $field_name . " IN (" . db_es(implode(",", $prefs[$field->getName()])) . ") "; } else { if ($field->isDateField() && (isset($prefs[$field->getName()]) && $prefs[$field->getName()][0] || isset($prefs[$field->getName() . '_end']) && $prefs[$field->getName() . '_end'][0])) { // transform a date field into a unix time and use <, > or = list($time, $ok) = util_date_to_unixtime($prefs[$field->getName()][0]); if ($advsrch) { list($time_end, $ok_end) = util_date_to_unixtime($prefs[$field->getName() . '_end'][0]); if ($ok) { list($year, $month, $day) = util_date_explode($prefs[$field->getName()][0]); $time_after = mktime(0, 0, 0, $month, $day, $year); $where .= " AND " . $field_name . " >= " . $time_after; } if ($ok_end) { list($year, $month, $day) = util_date_explode($prefs[$field->getName() . '_end'][0]); $time_before = mktime(23, 59, 59, $month, $day, $year); $where .= " AND " . $field_name . " <= " . $time_before; } } else { if (isset($prefs[$field->getName()][1])) { $operator = $prefs[$field->getName()][1]; } else { $operator = $prefs[$field->getName() . '_op'][0]; } // '=' means that day between 00:00 and 23:59 if ($operator == '=') { list($year, $month, $day) = util_date_explode($prefs[$field->getName()][0]); $time_end = mktime(23, 59, 59, $month, $day, $year); $where = " AND " . $field_name . " >= " . $time . " AND " . $field_name . " <= " . $time_end; } else { if ($operator == '>') { list($year, $month, $day) = util_date_explode($prefs[$field->getName()][0]); $time_after = mktime(0, 0, 0, $month, $day + 1, $year); $where = " AND " . $field_name . " " . $operator . "=" . $time_after; } else { if ($operator == '<') { list($year, $month, $day) = util_date_explode($prefs[$field->getName()][0]); $time_before = mktime(23, 59, 59, $month, $day - 1, $year); $where = " AND " . $field_name . " " . $operator . "=" . $time_before; } } } } // Always exclude undefined dates (0) $where .= " AND " . $field_name . " <> 0 "; return $where; } else { if (($field->isTextField() || $field->isTextArea()) && isset($prefs[$field->getName()][0]) && $prefs[$field->getName()][0]) { // It's a text field accept. Process INT or TEXT,VARCHAR fields differently return " AND " . $field->buildMatchExpression($field_name, $prefs[$field->getName()][0]); } } } $notany = false; }
/** * Update the default_value attribute * * @param group_artifact_id: the group artifact id * @param default_value: the default value * @param mixed computed_value: indication for computed field values (used for instance for current date field value) * * @return boolean - succeed or failed */ function updateDefaultValue($group_artifact_id, $default_value, $computed_value = false) { global $Language; if ($this->isDateField()) { if ($computed_value != false) { // value '' match with current date if ($computed_value == 'current_date') { $value = ''; } } else { // value 0 match with empty date list($value, $ok) = util_date_to_unixtime($default_value); } } else { if (($this->data_type == $this->DATATYPE_INT || $this->data_type == $this->DATATYPE_USER) && is_array($default_value)) { $value = implode(",", $default_value); } else { $value = $default_value; } } // Update the artifact_field $sql = "UPDATE artifact_field SET " . "default_value='" . db_es($value) . "' " . "WHERE group_artifact_id=" . db_ei($group_artifact_id) . " AND field_id=" . db_ei($this->field_id); $res = db_query($sql); if (!$res) { $this->setError($Language->getText('tracker_common_field', 'upd_err', array($field_id, $group_artifact_id, db_error()))); return false; } // Reload the field $this->fetchData($group_artifact_id, $this->field_name); return true; }
/** * Builds the group history filter * * @param String $event Events category used to filter results * @param String $subEventsBox Event used to filter results * @param String $value Value used to filter results * @param Integer $startDate Start date used to filter results * @param Integer $endDate End date used to filter results * @param String $by User name used to filter results * * @return String */ function build_grouphistory_filter($event = null, $subEventsBox = null, $value = null, $startDate = null, $endDate = null, $by = null) { $filter = ''; if (!empty($by)) { $uh = UserHelper::instance(); $filter .= $uh->getUserFilter($by); } if (!empty($startDate)) { list($timestamp, ) = util_date_to_unixtime($startDate); $filter .= " AND group_history.date > '" . $timestamp . "'"; } if (!empty($endDate)) { list($timestamp, ) = util_date_to_unixtime($endDate); // Add 23:59:59 to timestamp $timestamp = $timestamp + 86399; $filter .= " AND group_history.date < '" . $timestamp . "'"; } if (!empty($value)) { //all_users need specific treatement if (stristr($value, $GLOBALS["Language"]->getText('project_ugroup', 'ugroup_anonymous_users_name_key'))) { $value = 'ugroup_anonymous_users_name_key'; } $filter .= " AND group_history.old_value LIKE '%" . $value . "%'"; } if (!empty($event) && strcmp($event, 'any')) { $filter .= " AND ( 0 "; if (!empty($subEventsBox)) { foreach ($subEventsBox as $key => $value) { $filter .= " OR group_history.field_name LIKE '" . $key . "%'"; } } else { $subEventsList = get_history_entries(); foreach ($subEventsList[$event] as $key => $value) { $filter .= " OR group_history.field_name LIKE '" . $value . "%'"; } } $filter .= " ) "; } return $filter; }