5 * Copyright 1999-2001, VA Linux Systems, Inc.
6 * Copyright 2002-2004, GForge, LLC
7 * Copyright 2009, Roland Mas
8 * Copyright (C) 2011 Alain Peyrat - Alcatel-Lucent
10 * This file is part of FusionForge. FusionForge is free software;
11 * you can redistribute it and/or modify it under the terms of the
12 * GNU General Public License as published by the Free Software
13 * Foundation; either version 2 of the Licence, or (at your option)
16 * FusionForge is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License along
22 * with FusionForge; if not, write to the Free Software Foundation, Inc.,
23 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
26 require_once $gfcommon.'include/Error.class.php';
27 require_once $gfcommon.'tracker/ArtifactExtraFieldElement.class.php';
28 require_once $gfcommon.'tracker/ArtifactStorage.class.php';
31 * Gets an ArtifactType object from the artifact type id
33 * @param int $artType_id The ArtifactType id
34 * @param resource|bool $res The DB handle if passed in (optional)
35 * @return ArtifactType The ArtifactType object
37 function &artifactType_get_object($artType_id, $res = false) {
38 global $ARTIFACTTYPE_OBJ;
39 if (!isset($ARTIFACTTYPE_OBJ["_".$artType_id."_"])) {
41 //the db result handle was passed in
43 $res = db_query_params('SELECT * FROM artifact_group_list_vw WHERE group_artifact_id=$1',
46 if (!$res || db_numrows($res) < 1) {
47 $ARTIFACTTYPE_OBJ["_".$artType_id."_"] = false;
49 $data = db_fetch_array($res);
50 $Group = group_get_object($data["group_id"]);
51 $ARTIFACTTYPE_OBJ["_".$artType_id."_"] = new ArtifactType($Group, $data["group_artifact_id"], $data);
54 return $ARTIFACTTYPE_OBJ["_".$artType_id."_"];
57 function artifacttype_get_groupid($artifact_type_id) {
58 global $ARTIFACTTYPE_OBJ;
59 if (isset($ARTIFACTTYPE_OBJ["_".$artifact_type_id."_"])) {
60 return $ARTIFACTTYPE_OBJ["_".$artifact_type_id."_"]->Group->getID();
63 $res = db_query_params('SELECT group_id FROM artifact_group_list WHERE group_artifact_id=$1',
64 array($artifact_type_id));
65 if (!$res || db_numrows($res) < 1) {
68 $arr = db_fetch_array($res);
69 return $arr['group_id'];
72 class ArtifactType extends Error {
82 * extra_fields 3d array - the IDs and Names of the extra fields
84 * @var array extra_fields;
86 var $extra_fields = array();
89 * extra_field[extra_field_id] array - the IDs and Names of elements on the extra fields
91 * @var array extra_field
96 * Technicians db resource ID.
98 * @var int $technicians_res.
100 var $technicians_res;
103 * Submitters db resource ID.
105 * @var int $submitters_res.
110 * Status db resource ID.
112 * @var int $status_res.
117 * Canned responses resource ID.
119 * @var int $canned_responses_res.
121 var $canned_responses_res;
124 * Array of artifact data.
126 * @var array $data_array.
131 * Array of element names so they only have to be fetched once from db.
133 * @var array $data_array.
138 * Array of element status so they only have to be fetched once from db.
140 * @var array $data_array.
145 * ArtifactType - constructor.
147 * @param Group $Group The Group object.
148 * @param int|bool $artifact_type_id The id # assigned to this artifact type in the db.
149 * @param array|bool $arr The associative array of data.
151 function __construct($Group, $artifact_type_id = false, $arr = false) {
153 if (!$Group || !is_object($Group)) {
154 $this->setError(_('No Valid Group Object'));
157 if ($Group->isError()) {
158 $this->setError('ArtifactType: '.$Group->getErrorMessage());
161 $this->Group = $Group;
162 if ($artifact_type_id) {
163 if (!$arr || !is_array($arr)) {
164 if (!$this->fetchData($artifact_type_id)) {
168 $this->data_array =& $arr;
169 if ($this->data_array['group_id'] != $this->Group->getID()) {
170 $this->setError('Group_id in db result does not match Group Object');
171 $this->data_array = null;
176 // Make sure they can even access this object
178 if (!forge_check_perm ('tracker', $this->getID(), 'read')) {
179 $this->setPermissionDeniedError();
180 $this->data_array = null;
187 * create - use this to create a new ArtifactType in the database.
189 * @param string $name The type name.
190 * @param string $description The type description.
191 * @param bool $email_all (1) true (0) false - whether to email on all updates.
192 * @param string $email_address The address to send new entries and updates to.
193 * @param int $due_period Days before this item is considered overdue.
194 * @param bool $use_resolution (1) true (0) false - whether the resolution box should be shown.
195 * @param string $submit_instructions Free-form string that project admins can place on the submit page.
196 * @param string $browse_instructions Free-form string that project admins can place on the browse page.
197 * @param int $datatype (1) bug tracker, (2) Support Tracker, (3) Patch Tracker, (4) features (0) other.
198 * @return int id on success, false on failure.
200 function create($name, $description, $email_all, $email_address,
201 $due_period, $use_resolution, $submit_instructions, $browse_instructions, $datatype = 0) {
203 if (!forge_check_perm('tracker_admin', $this->Group->getID())) {
204 $this->setPermissionDeniedError();
208 if (!$name || !$description || !$due_period) {
209 $this->setError(_('ArtifactType: Name, Description, Due Period, and Status Timeout are required'));
213 if ($email_address) {
214 $invalid_emails = validate_emails($email_address);
215 if (count($invalid_emails) > 0) {
216 $this->SetError(_('E-mail address(es) appeared invalid').': '.implode(',', $invalid_emails));
221 $use_resolution = ((!$use_resolution) ? 0 : $use_resolution);
222 $email_all = ((!$email_all) ? 0 : $email_all);
226 $res = db_query_params('INSERT INTO
239 ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10)',
240 array($this->Group->getID(),
241 htmlspecialchars($name),
242 htmlspecialchars($description),
245 $due_period*(60*60*24),
247 htmlspecialchars($submit_instructions),
248 htmlspecialchars($browse_instructions),
251 $id = db_insertid($res, 'artifact_group_list', 'group_artifact_id');
254 $this->setError('ArtifactType: '.db_error());
258 if (!$this->fetchData($id)) {
262 $this->Group->normalizeAllRoles();
270 * fetchData - re-fetch the data for this ArtifactType from the database.
272 * @param int $artifact_type_id The artifact type ID.
273 * @return boolean success.
275 function fetchData($artifact_type_id) {
276 $res = db_query_params('SELECT * FROM artifact_group_list_vw
277 WHERE group_artifact_id=$1
279 array($artifact_type_id,
280 $this->Group->getID()));
281 if (!$res || db_numrows($res) < 1) {
282 $this->setError('ArtifactType: Invalid ArtifactTypeID');
285 $this->data_array = db_fetch_array($res);
286 db_free_result($res);
291 * getGroup - get the Group object this ArtifactType is associated with.
293 * @return Object The Group object.
295 function &getGroup() {
300 * getID - get this ArtifactTypeID.
302 * @return int The group_artifact_id #.
305 return $this->data_array['group_artifact_id'];
309 * getOpenCount - get the count of open tracker items in this tracker type.
311 * @return int The count.
313 function getOpenCount() {
314 return $this->data_array['open_count'];
318 * getTotalCount - get the total number of tracker items in this tracker type.
320 * @return int The total count.
322 function getTotalCount() {
323 return $this->data_array['count'];
327 * getSubmitInstructions - get the free-form string strings.
329 * @return string instructions.
331 function getSubmitInstructions() {
332 return $this->data_array['submit_instructions'];
336 * getBrowseInstructions - get the free-form string strings.
338 * @return string instructions.
340 function getBrowseInstructions() {
341 return $this->data_array['browse_instructions'];
345 * emailAll - determine if we're supposed to email on every event.
347 * @return boolean email_all.
349 function emailAll() {
350 return $this->data_array['email_all_updates'];
354 * emailAddress - defined email address to send events to.
356 * @return string email.
358 function getEmailAddress() {
359 return $this->data_array['email_address'];
363 * getName - the name of this ArtifactType.
365 * @return string name.
368 return $this->data_array['name'];
372 * getFormattedName - formatted name of this ArtifactType
374 * @return string formatted name
376 function getFormattedName() {
377 $name = preg_replace('/[^[:alnum:]]/', '', $this->getName());
378 $name = strtolower($name);
383 * getUnixName - returns the name used by email gateway
385 * @return string unix name
387 function getUnixName() {
388 return strtolower($this->Group->getUnixName()).'-'.$this->getFormattedName();
392 * getReturnEmailAddress() - return the return email address for notification emails
394 * @return string return email address
396 function getReturnEmailAddress() {
399 if (forge_get_config('use_gateways')) {
400 $address .= strtolower($this->getUnixName());
402 $address .= 'noreply';
404 $address .= '@'.forge_get_config('web_host');
409 * getDescription - the description of this ArtifactType.
411 * @return string description.
413 function getDescription() {
414 return $this->data_array['description'];
418 * getDuePeriod - how many seconds until it's considered overdue.
420 * @return int seconds.
422 function getDuePeriod() {
423 return $this->data_array['due_period'];
427 * getStatusTimeout - how many seconds until an item is stale.
429 * @return int seconds.
431 function getStatusTimeout() {
432 return $this->data_array['status_timeout'];
436 * getCustomStatusField - return the extra_field_id of the field containing the custom status.
438 * @return int extra_field_id.
440 function getCustomStatusField() {
441 return $this->data_array['custom_status_field'];
445 * setCustomStatusField - set the extra_field_id of the field containing the custom status.
447 * @param int $extra_field_id The extra field id.
448 * @return boolean success.
450 function setCustomStatusField($extra_field_id) {
451 $res = db_query_params('UPDATE artifact_group_list SET custom_status_field=$1
452 WHERE group_artifact_id=$2',
453 array ($extra_field_id,
459 * usesCustomStatuses - boolean
461 * @return boolean use_custom_statues.
463 function usesCustomStatuses() {
464 return $this->getCustomStatusField();
468 * remapStatus - pass the extra_fields array and return the status_id, either open/closed
470 * @param int $status_id The status_id
471 * @param array $extra_fields Complex array of extra_field_data
472 * @return int status_id.
474 function remapStatus($status_id, $extra_fields) {
475 if ($this->usesCustomStatuses()) {
476 //get the selected element for the extra_field_status element
477 $csfield = $this->getCustomStatusField();
478 if (array_key_exists($csfield, $extra_fields)) {
479 $element_id = $extra_fields[$csfield];
481 //convert that element_id into the status_id
482 $res = db_query_params('SELECT status_id FROM artifact_extra_field_elements WHERE element_id=$1',
485 $this->setError('Error Remapping Status: '.db_error());
488 $status_id = db_result($res, 0, 'status_id');
490 // custom status was not passed... use the first status from the database
491 $res = db_query_params('SELECT status_id FROM artifact_extra_field_elements WHERE extra_field_id=$1 ORDER BY element_id ASC LIMIT 1 OFFSET 0',
493 if (db_numrows($res) == 0) { // No values available
494 $this->setError('Error Remapping Status');
497 $status_id = db_result($res, 0, 'status_id');
500 if ($status_id < 1 || $status_id > 4) {
501 echo "INVALID STATUS REMAP: $status_id FROM SELECTED ELEMENT: $element_id";
511 * getDataType - flag that is generally unused but can mark the difference between bugs, patches, etc.
513 * @return int The type (1) bug (2) support (3) patch (4) feature (0) other.
515 function getDataType() {
516 return $this->data_array['datatype'];
520 * setMonitor - user can monitor this artifact.
522 * @return bool false - always false - always use the getErrorMessage() for feedback
524 function setMonitor($user_id = -1) {
525 if ($user_id == -1) {
526 if (!session_loggedin()) {
527 $this->setError(_('You can only monitor if you are logged in.'));
530 $user_id = user_getid();
533 $res = db_query_params('SELECT * FROM artifact_type_monitor WHERE group_artifact_id=$1 AND user_id=$2',
534 array($this->getID(),
536 if (!$res || db_numrows($res) < 1) {
538 $res = db_query_params('INSERT INTO artifact_type_monitor (group_artifact_id,user_id) VALUES ($1,$2)',
539 array($this->getID(),
542 $this->setError(db_error());
545 $this->setError(_('Monitoring Started'));
549 //already monitoring - remove their monitor
550 db_query_params('DELETE FROM artifact_type_monitor
551 WHERE group_artifact_id=$1
553 array($this->getID(),
555 $this->setError(_('Monitoring Stopped'));
560 function isMonitoring() {
561 if (!session_loggedin()) {
564 $result = db_query_params('SELECT count(*) AS count FROM artifact_type_monitor
565 WHERE user_id=$1 AND group_artifact_id=$2',
568 $row_count = db_fetch_array($result);
569 return $result && $row_count['count'] > 0;
573 * getMonitorIds - array of id of users monitoring this Artifact.
575 * @return array of id of users monitoring this Artifact.
577 function &getMonitorIds() {
578 $res = db_query_params('SELECT user_id FROM artifact_type_monitor WHERE group_artifact_id=$1',
579 array($this->getID()));
580 return util_result_column_to_array($res);
584 * getExtraFields - List of possible user built extra fields
585 * set up for this artifact type.
587 * @param array $types
588 * @return array arrays of data;
590 function getExtraFields($types = array()) {
592 $filter = implode(',', $types);
593 $types = explode(',', $filter);
597 if (!isset($this->extra_fields[$filter])) {
598 $this->extra_fields[$filter] = array();
600 $res = db_query_params('SELECT *
601 FROM artifact_extra_field_list
602 WHERE group_artifact_id=$1
603 AND field_type = ANY ($2)
604 ORDER BY field_type ASC',
605 array($this->getID(),
606 db_int_array_to_any_clause($types)));
608 $res = db_query_params('SELECT *
609 FROM artifact_extra_field_list
610 WHERE group_artifact_id=$1
611 ORDER BY field_type ASC',
612 array($this->getID()));
614 while ($arr = db_fetch_array($res)) {
615 $this->extra_fields[$filter][$arr['extra_field_id']] = $arr;
619 return $this->extra_fields[$filter];
623 * cloneFieldsFrom - clone all the fields and elements from another tracker
625 * @param int $clone_tracker_id
626 * @return boolean true/false on success
628 function cloneFieldsFrom($clone_tracker_id) {
630 $g = group_get_object(forge_get_config('template_group'));
631 if (!$g || !is_object($g)) {
632 $this->setError('Could Not Get Template Group');
634 } elseif ($g->isError()) {
635 $this->setError('Template Group Error '.$g->getErrorMessage());
638 $at = new ArtifactType($g,$clone_tracker_id);
639 if (!$at || !is_object($at)) {
640 $this->setError('Could Not Get Tracker To Clone');
642 } elseif ($at->isError()) {
643 $this->setError('Clone Tracker Error '.$at->getErrorMessage());
646 $efs = $at->getExtraFields();
649 // Iterate list of extra fields
652 foreach ($efs as $ef) {
653 //new field in this tracker
654 $nef = new ArtifactExtraField($this);
655 if (!$nef->create(util_unconvert_htmlspecialchars($ef['field_name']), $ef['field_type'], $ef['attribute1'], $ef['attribute2'], $ef['is_required'], $ef['alias'])) {
656 $this->setError('Error Creating New Extra Field: '.$nef->getErrorMessage());
661 // Iterate the elements
663 $resel = db_query_params('SELECT * FROM artifact_extra_field_elements WHERE extra_field_id=$1',
664 array($ef['extra_field_id']));
665 while ($el = db_fetch_array($resel)) {
667 $nel = new ArtifactExtraFieldElement($nef);
668 if (!$nel->create(util_unconvert_htmlspecialchars($el['element_name']), $el['status_id'])) {
670 $this->setError('Error Creating New Extra Field Element: '.$nel->getErrorMessage());
681 * getExtraFieldName - Get a box name using the box ID
683 * @param int $extra_field_id id of an extra field.
684 * @return string name of extra field.
686 function getExtraFieldName($extra_field_id) {
687 $arr = $this->getExtraFields();
688 return $arr[$extra_field_id]['field_name'];
692 * getExtraFieldElements - List of possible admin configured
693 * extra field elements. This function is used to
694 * present the boxes and choices on the main Add/Update page.
696 * @param int $id id of the extra field
697 * @return array of elements for this extra field.
699 function getExtraFieldElements($id) {
704 if (!isset($this->extra_field[$id])) {
705 $this->extra_field[$id] = array();
706 $res = db_query_params('SELECT element_id, element_name, status_id
707 FROM artifact_extra_field_elements
708 WHERE extra_field_id = $1
709 ORDER BY element_pos ASC, element_id ASC',
712 while ($arr = db_fetch_array($res)) {
713 $this->extra_field[$id][$i++] = $arr;
715 // if (count($this->extra_field[$id]) == 0) {
720 return $this->extra_field[$id];
724 * getElementName - get the name of a particular element.
727 * @return string The name.
729 function getElementName($choice_id) {
733 if (is_array($choice_id)) {
734 $choice_id = implode(',', array_map('intval', $choice_id));
736 $choice_id = intval($choice_id);
738 if ($choice_id == 100) {
741 if (!isset($this->element_name[$choice_id])) {
742 $res = db_query_params('SELECT element_id,extra_field_id,element_name
743 FROM artifact_extra_field_elements
744 WHERE element_id = ANY ($1)',
745 array(db_int_array_to_any_clause(explode(',', $choice_id))));
746 if (db_numrows($res) > 1) {
747 $arr = util_result_column_to_array($res, 2);
748 $this->element_name[$choice_id] = implode(',', $arr);
750 $this->element_name[$choice_id] = db_result($res, 0, 'element_name');
753 return $this->element_name[$choice_id];
757 * getElementStatusID - get the status of a particular element.
759 * @param int|array $choice_id
760 * @return int The status
762 function getElementStatusID($choice_id) {
766 if (is_array($choice_id)) {
767 $choice_id = implode(',',$choice_id);
769 if ($choice_id == 100) {
772 if (!$this->element_status[$choice_id]) {
773 $res = db_query_params('SELECT element_id,extra_field_id,status_id
774 FROM artifact_extra_field_elements
775 WHERE element_id = ANY ($1)',
776 array(db_int_array_to_any_clause(explode(',', $choice_id))));
777 if (db_numrows($res) > 1) {
778 $arr = util_result_column_to_array($res, 2);
779 $this->element_status[$choice_id] = implode(',', $arr);
781 $this->element_status[$choice_id] = db_result($res, 0, 'status_id');
784 return $this->element_status[$choice_id];
788 * delete - delete this tracker and all its related data.
790 * @param bool $sure I'm Sure.
791 * @param bool $really_sure I'm REALLY sure.
792 * @return bool true/false;
794 function delete($sure, $really_sure) {
795 if (!$sure || !$really_sure) {
796 $this->setMissingParamsError(_('Please tick all checkboxes.'));
799 if (!forge_check_perm ('tracker_admin', $this->Group->getID())) {
800 $this->setPermissionDeniedError();
804 db_query_params('DELETE FROM artifact_extra_field_data
805 WHERE EXISTS (SELECT artifact_id FROM artifact
806 WHERE group_artifact_id=$1
807 AND artifact.artifact_id=artifact_extra_field_data.artifact_id)',
808 array($this->getID()));
809 //echo '0.1'.db_error();
810 db_query_params('DELETE FROM artifact_extra_field_elements
811 WHERE EXISTS (SELECT extra_field_id FROM artifact_extra_field_list
812 WHERE group_artifact_id=$1
813 AND artifact_extra_field_list.extra_field_id = artifact_extra_field_elements.extra_field_id)',
814 array ($this->getID()));
815 //echo '0.2'.db_error();
816 db_query_params('DELETE FROM artifact_extra_field_list
817 WHERE group_artifact_id=$1',
818 array ($this->getID()));
819 //echo '0.3'.db_error();
820 db_query_params('DELETE FROM artifact_canned_responses
821 WHERE group_artifact_id=$1',
822 array ($this->getID()));
823 //echo '1'.db_error();
824 db_query_params('DELETE FROM artifact_counts_agg
825 WHERE group_artifact_id=$1',
826 array ($this->getID()));
827 //echo '5'.db_error();
829 ArtifactStorage::instance()->deleteFromQuery('SELECT id FROM artifact_file
830 WHERE EXISTS (SELECT artifact_id FROM artifact
831 WHERE group_artifact_id=$1
832 AND artifact.artifact_id=artifact_file.artifact_id)',
833 array($this->getID()));
835 db_query_params('DELETE FROM artifact_file
836 WHERE EXISTS (SELECT artifact_id FROM artifact
837 WHERE group_artifact_id=$1
838 AND artifact.artifact_id=artifact_file.artifact_id)',
839 array($this->getID()));
840 //echo '6'.db_error();
841 db_query_params('DELETE FROM artifact_message
842 WHERE EXISTS (SELECT artifact_id FROM artifact
843 WHERE group_artifact_id=$1
844 AND artifact.artifact_id=artifact_message.artifact_id)',
845 array($this->getID()));
846 //echo '7'.db_error();
847 db_query_params('DELETE FROM artifact_history
848 WHERE EXISTS (SELECT artifact_id FROM artifact
849 WHERE group_artifact_id=$1
850 AND artifact.artifact_id=artifact_history.artifact_id)',
851 array($this->getID()));
852 //echo '8'.db_error();
853 db_query_params('DELETE FROM artifact_monitor
854 WHERE EXISTS (SELECT artifact_id FROM artifact
855 WHERE group_artifact_id=$1
856 AND artifact.artifact_id=artifact_monitor.artifact_id)',
857 array($this->getID()));
858 //echo '9'.db_error();
859 db_query_params('DELETE FROM artifact
860 WHERE group_artifact_id=$1',
861 array($this->getID()));
862 //echo '4'.db_error();
863 db_query_params('DELETE FROM artifact_group_list
864 WHERE group_artifact_id=$1',
865 array($this->getID()));
866 //echo '11'.db_error();
869 ArtifactStorage::instance()->commit();
871 $this->Group->normalizeAllRoles();
877 * getSubmitters - returns a result set of submitters.
879 * @return resource database result set.
881 function getSubmitters() {
882 if (!isset($this->submitters_res)) {
883 $this->submitters_res = db_query_params('SELECT DISTINCT submitted_by, submitted_realname
885 WHERE group_artifact_id=$1
886 ORDER BY submitted_realname',
887 array($this->getID()));
889 return $this->submitters_res;
893 * getCannedResponses - returns a result set of canned responses.
895 * @return resource database result set.
897 function getCannedResponses() {
898 if (!isset($this->cannedresponses_res)) {
899 $this->cannedresponses_res = db_query_params('SELECT id,title
900 FROM artifact_canned_responses
901 WHERE group_artifact_id=$1',
902 array($this->getID()));
904 return $this->cannedresponses_res;
908 * getStatuses - returns a result set of statuses.
910 * These statuses are either the default open/closed or any number of
911 * custom statuses that are stored in the extra fields. On insert/update
912 * to an artifact the status_id is remapped from the extra_field_element_id to
913 * the standard open/closed id.
915 * @return resource database result set.
917 function getStatuses() {
918 if (!isset($this->status_res)) {
919 $this->status_res = db_query_params('SELECT * FROM artifact_status', array());
921 return $this->status_res;
925 * getStatusName - returns the name of this status.
927 * @param int $id The status ID.
928 * @return string name.
930 function getStatusName($id) {
931 $result = db_query_params('select status_name from artifact_status WHERE id=$1',
933 if ($result && db_numrows($result) > 0) {
934 return db_result($result, 0, 'status_name');
936 return 'Error: Not Found';
941 * update - use this to update this ArtifactType in the database.
943 * @param string $name The item name.
944 * @param string $description The item description.
945 * @param bool $email_all (1) true (0) false - whether to email on all updates.
946 * @param string $email_address The address to send new entries and updates to.
947 * @param int $due_period Days before this item is considered overdue.
948 * @param int $status_timeout Days before stale items time out.
949 * @param bool $use_resolution (1) true (0) false - whether the resolution box should be shown.
950 * @param string $submit_instructions Free-form string that project admins can place on the submit page.
951 * @param string $browse_instructions Free-form string that project admins can place on the browse page.
952 * @return bool true on success, false on failure.
954 function update($name, $description, $email_all, $email_address,
955 $due_period, $status_timeout, $use_resolution, $submit_instructions, $browse_instructions) {
957 if (!forge_check_perm ('tracker_admin', $this->Group->getID())) {
958 $this->setPermissionDeniedError();
962 if ($this->getDataType()) {
963 $name=$this->getName();
964 $description=$this->getDescription();
967 if (!$name || !$description || !$due_period || !$status_timeout) {
968 $this->setError(_('ArtifactType: Name, Description, Due Period, and Status Timeout are required'));
972 $result = db_query_params('SELECT count(*) AS count FROM artifact_group_list WHERE group_id=$1 AND name=$2 AND group_artifact_id!=$3',
973 array($this->Group->getID(), $name, $this->getID()));
975 $this->setError('ArtifactType::Update(): '.db_error());
978 if (db_result($result, 0, 'count')) {
979 $this->setError(_('Tracker name already used'));
983 if ($email_address) {
984 $invalid_emails = validate_emails($email_address);
985 if (count($invalid_emails) > 0) {
986 $this->SetError(_('E-mail address(es) appeared invalid').': '.implode(',', $invalid_emails));
991 $email_all = ((!$email_all) ? 0 : $email_all);
992 $use_resolution = ((!$use_resolution) ? 0 : $use_resolution);
994 $res = db_query_params('UPDATE artifact_group_list SET
997 email_all_updates=$3,
1001 submit_instructions=$7,
1002 browse_instructions=$8
1003 WHERE group_artifact_id=$9 AND group_id=$10',
1005 htmlspecialchars($name),
1006 htmlspecialchars($description),
1009 $due_period * (60*60*24),
1010 $status_timeout * (60*60*24),
1011 htmlspecialchars($submit_instructions),
1012 htmlspecialchars($browse_instructions),
1014 $this->Group->getID()));
1016 if (!$res || db_affected_rows($res) < 1) {
1017 $this->setError('ArtifactType::Update(): '.db_error());
1020 $this->fetchData($this->getID());
1026 * getBrowseList - get the free-form string strings.
1028 * @return string instructions.
1030 function getBrowseList() {
1031 $list = $this->data_array['browse_list'];
1033 // remove status_id in the browse list if a custom status exists
1034 if (count($this->getExtraFields(array(ARTIFACT_EXTRAFIELDTYPE_STATUS))) > 0) {
1035 $arr = explode(',', $list);
1036 $idx = array_search('status_id', $arr);
1037 if ($idx !== False) {
1038 array_splice($arr, $idx, 1);
1040 return join(',', $arr);
1047 * setCustomStatusField - set the extra_field_id of the field containing the custom status.
1049 * @param int $list The extra field id.
1050 * @return boolean success.
1052 function setBrowseList($list) {
1053 $res = db_query_params('UPDATE artifact_group_list
1055 WHERE group_artifact_id=$2',
1058 $this->fetchData($this->getID());
1066 // c-file-style: "bsd"