Complex classes like Artifact often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.
Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.
While breaking up the class, it is a good idea to analyze how other classes use Artifact, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
29 | class Artifact extends Error { |
||
30 | |||
31 | const FORMAT_TEXT = 0; |
||
32 | const FORMAT_HTML = 1; |
||
33 | |||
34 | //The diffetents mode of display |
||
35 | const OUTPUT_BROWSER = 0; |
||
36 | const OUTPUT_EXPORT = 1; |
||
37 | const OUTPUT_MAIL_TEXT = 2; |
||
38 | |||
39 | /** |
||
40 | * Artifact Type object. |
||
41 | * |
||
42 | * @var object $ArtifactType. |
||
43 | */ |
||
44 | var $ArtifactType; |
||
45 | |||
46 | /** |
||
47 | * Array of artifact data. |
||
48 | * |
||
49 | * @var array $data_array. |
||
50 | */ |
||
51 | var $data_array; |
||
52 | |||
53 | |||
54 | /** |
||
55 | * Artifact - constructor. |
||
56 | * |
||
57 | * @param object The ArtifactType object. |
||
58 | * @param integer (primary key from database OR complete assoc array) |
||
59 | * ONLY OPTIONAL WHEN YOU PLAN TO IMMEDIATELY CALL ->create() |
||
60 | * @return boolean success. |
||
61 | */ |
||
62 | function Artifact(&$ArtifactType, $data=false, $checkPerms = true) { |
||
63 | global $Language; |
||
64 | $this->Error(); |
||
65 | |||
66 | $this->ArtifactType = $ArtifactType; |
||
67 | |||
68 | //was ArtifactType legit? |
||
69 | if (!$ArtifactType || !is_object($ArtifactType)) { |
||
70 | $this->setError('Artifact: '.$Language->getText('tracker_common_canned','not_valid')); |
||
71 | return false; |
||
72 | } |
||
73 | //did ArtifactType have an error? |
||
74 | if ($ArtifactType->isError()) { |
||
75 | $this->setError('Artifact: '.$ArtifactType->getErrorMessage()); |
||
76 | return false; |
||
77 | } |
||
78 | |||
79 | // |
||
80 | // make sure this person has permission to view artifacts belonging to this tracker |
||
81 | // |
||
82 | if ($checkPerms && !$this->ArtifactType->userCanView()) { |
||
83 | $this->setError('Artifact: '.$Language->getText('tracker_common_artifact','view_private')); |
||
84 | return false; |
||
85 | } |
||
86 | |||
87 | // |
||
88 | // set up data structures |
||
89 | // |
||
90 | if ($data) { |
||
91 | if (is_array($data)) { |
||
92 | $this->data_array = $data; |
||
93 | // |
||
94 | // Should verify ArtifactType ID |
||
95 | // |
||
96 | } else { |
||
97 | if (!$this->fetchData($data)) { |
||
98 | return false; |
||
99 | } |
||
100 | } |
||
101 | // |
||
102 | // make sure this person has permission to view this artifact |
||
103 | // |
||
104 | if ($checkPerms) { |
||
105 | if (!$this->userCanView()) { |
||
106 | $this->setError('Artifact: '.$Language->getText('tracker_common_artifact','view_private_artifact')); |
||
107 | return false; |
||
108 | } |
||
109 | } |
||
110 | } |
||
111 | return true; |
||
112 | } |
||
113 | |||
114 | |||
115 | /** |
||
116 | * fetchData - re-fetch the data for this Artifact from the database. |
||
117 | * |
||
118 | * @param int The artifact ID. |
||
119 | * @return boolean success. |
||
120 | */ |
||
121 | function fetchData($artifact_id) { |
||
122 | |||
123 | global $art_field_fact,$Language; |
||
124 | if (!$art_field_fact) { |
||
125 | $art_field_fact = new ArtifactFieldFactory($this->ArtifactType); |
||
126 | } |
||
127 | |||
128 | // first fetch values of standard fields |
||
129 | $sql = "SELECT * FROM artifact WHERE artifact_id='". db_ei($artifact_id) ."' AND group_artifact_id='". db_ei($this->ArtifactType->getID()) ."'"; |
||
130 | $res=db_query($sql); |
||
131 | if (!$res || db_numrows($res) < 1) { |
||
132 | $this->setError('Artifact: '.$Language->getText('tracker_common_artifact','invalid_id')); |
||
133 | return false; |
||
134 | } |
||
135 | $this->data_array = db_fetch_array($res); |
||
136 | db_free_result($res); |
||
137 | |||
138 | |||
139 | // now get the values for generic fields if any |
||
140 | $sql = "SELECT * FROM artifact_field_value WHERE artifact_id='". db_ei($artifact_id) ."'"; |
||
141 | $res=db_query($sql); |
||
142 | if (!$res || db_numrows($res) < 1) { |
||
143 | // if no result then it is possible that there isn't any generic fields |
||
144 | return true; |
||
145 | } |
||
146 | while ($row = db_fetch_array($res)) { |
||
147 | $data_fields[$row['field_id']] = $row; |
||
148 | } |
||
149 | |||
150 | // Get the list of all fields used by this tracker and append |
||
151 | // the values for these generic fields to data_array |
||
152 | $fields = $art_field_fact->getAllUsedFields(); |
||
153 | |||
154 | while (list($key,$field) = each($fields) ) { |
||
|
|||
155 | //echo $field->getName()."-".$field->getID()."<br>"; |
||
156 | // Skip! Standard field values fectched in previous query |
||
157 | // and comment_type_id is not stored in artifact_field_value table |
||
158 | if ( $field->isStandardField() || |
||
159 | $field->getName() == "comment_type_id") { |
||
160 | continue; |
||
161 | } |
||
162 | $this->data_array[$field->getName()] = $data_fields[$field->getID()][$field->getValueFieldName()]; |
||
163 | |||
164 | } |
||
165 | |||
166 | return true; |
||
167 | } |
||
168 | |||
169 | /** |
||
170 | * getArtifactType - get the ArtifactType Object this Artifact is associated with. |
||
171 | * |
||
172 | * @return object ArtifactType. |
||
173 | */ |
||
174 | function getArtifactType() { |
||
177 | |||
178 | /** |
||
179 | * getValue - get the value for this artifact field. |
||
180 | * |
||
181 | * @param name: the field name |
||
182 | * @return value |
||
183 | */ |
||
184 | function getValue($name) { |
||
187 | |||
188 | |||
189 | /** |
||
190 | * getMultiAssignedTo - get the value for the 'multi_assigned_to' field |
||
191 | * This function is needed because getValue() won't return an array. |
||
192 | * |
||
193 | * @return array |
||
194 | */ |
||
195 | function getMultiAssignedTo() { |
||
196 | $aid=$this->getID(); |
||
197 | if (!$aid) return; |
||
198 | $sql="SELECT afv.valueInt |
||
199 | FROM artifact_field_value afv, artifact a, artifact_field af |
||
200 | WHERE a.artifact_id=". db_ei($aid) ." |
||
201 | AND afv.artifact_id=". db_ei($aid) ." |
||
202 | AND a.group_artifact_id=af.group_artifact_id |
||
203 | AND afv.field_id=af.field_id |
||
204 | AND af.field_name='multi_assigned_to'"; |
||
205 | $res=db_query($sql); |
||
206 | $i=0; |
||
207 | $return_val = array(); |
||
208 | while($resrow = db_fetch_array($res)) { |
||
209 | $return_val[$i++]=$resrow['valueInt']; |
||
210 | } |
||
211 | return $return_val; |
||
212 | } |
||
213 | |||
214 | /** |
||
215 | * getID - get this ArtifactID. |
||
216 | * |
||
217 | * @return int The artifact_id #. |
||
218 | */ |
||
219 | function getID() { |
||
222 | |||
223 | /** |
||
224 | * useArtifactPermissions |
||
225 | * @return bool true if the artifact has individual permissions set |
||
226 | */ |
||
227 | function useArtifactPermissions() { |
||
230 | |||
231 | /** |
||
232 | * getStatusID - get open/closed/deleted flag. |
||
233 | * |
||
234 | * @return int Status: (1) Open, (2) Closed, (3) Deleted. |
||
235 | */ |
||
236 | function getStatusID() { |
||
239 | |||
240 | /** |
||
241 | * getSubmittedBy - get ID of submitter. |
||
242 | * |
||
243 | * @return int user_id of submitter. |
||
244 | */ |
||
245 | function getSubmittedBy() { |
||
248 | |||
249 | /** |
||
250 | * getOpenDate - get unix time of creation. |
||
251 | * |
||
252 | * @return int unix time. |
||
253 | */ |
||
254 | function getOpenDate() { |
||
257 | |||
258 | /** |
||
259 | * getLastUpdateDate - get unix time of last artifact update. |
||
260 | * |
||
261 | * @return int unix time. |
||
262 | */ |
||
263 | function getLastUpdateDate() { |
||
266 | |||
267 | /** |
||
268 | * getCloseDate - get unix time of closure. |
||
269 | * |
||
270 | * @return int unix time. |
||
271 | */ |
||
272 | function getCloseDate() { |
||
275 | |||
276 | /** |
||
277 | * getSummary - get text summary of artifact. |
||
278 | * |
||
279 | * @return string The summary (subject). |
||
280 | */ |
||
281 | function getSummary() { |
||
284 | |||
285 | /** |
||
286 | * getDetails - get text body (message) of artifact. |
||
287 | * |
||
288 | * @return string The body (message). |
||
289 | */ |
||
290 | function getDetails() { |
||
293 | |||
294 | /** |
||
295 | * getSeverity - get the severity of this artifact |
||
296 | * |
||
297 | * @return int |
||
298 | */ |
||
299 | function getSeverity() { |
||
302 | |||
303 | /** |
||
304 | * Insert an entry into the artifact_history |
||
305 | * |
||
306 | * @param field: the field object |
||
307 | * @param old_value: the previous value of the field |
||
308 | * @param new_value: the current value of the field |
||
309 | * @param type: extra information used to store the 'comment_type_id' field value (for the follow up comments) |
||
310 | * @param email: the email is the user is not logged in |
||
311 | * |
||
312 | * @return int : the artifact_history_id |
||
313 | */ |
||
314 | function addHistory ($field,$old_value,$new_value,$type=false,$email=false,$ahid=false,$comment_format=self::FORMAT_TEXT) { |
||
315 | //MLS: add case where we add CC and file_attachment into history for task #240 |
||
316 | if (!is_object($field)) { |
||
317 | // "cc", "attachment", "comment", etc |
||
318 | $name = $field; |
||
319 | } else { |
||
320 | // If field is not to be kept in bug change history then do nothing |
||
321 | if (!$field->getGlobalKeepHistory()) { return; } |
||
322 | $name = $field->getName(); |
||
323 | } |
||
324 | |||
325 | /* |
||
326 | handle the insertion of history for these parameters |
||
327 | */ |
||
328 | if ($email) { |
||
329 | // We use the email to identify the user |
||
330 | $user=100; |
||
331 | } else { |
||
332 | if ( user_isloggedin() ) { |
||
333 | $user=user_getid(); |
||
334 | } else { |
||
335 | $user = 100; |
||
336 | } |
||
337 | $email = ""; |
||
338 | } |
||
339 | |||
340 | // If type has a value add it into the sql statement (this is only for |
||
341 | // the follow up comments (comment field)) |
||
342 | $fld_type = ''; |
||
343 | $val_type = ''; |
||
344 | if ($type) { |
||
345 | $fld_type = ',type'; $val_type = ",'". db_ei($type) ."'"; |
||
346 | } else { |
||
347 | // No comment type specified for a followup comment |
||
348 | // so force it to None (100) |
||
349 | if ($name == 'comment' || (preg_match("/^(lbl_)/",$name) && preg_match("/(_comment)$/",$name))) { |
||
350 | $fld_type = ',type'; |
||
351 | $val_type = ",'100'"; |
||
352 | } |
||
353 | } |
||
354 | |||
355 | // Follow-up comments might have a different format |
||
356 | if ($comment_format != self::FORMAT_TEXT && user_isloggedin()) { |
||
357 | $fld_type .= ',format'; |
||
358 | $val_type .= ','.db_ei($comment_format); |
||
359 | } |
||
360 | |||
361 | $sql="insert into artifact_history(artifact_id,field_name,old_value,new_value,mod_by,email,date $fld_type) ". |
||
362 | "VALUES (". db_ei($this->getID()) .",'". db_es($name) ."','". db_es($old_value) ."','". db_es($new_value) ."','". db_ei($user) ."','". db_es($email) ."','".time()."' $val_type)"; |
||
363 | //echo $sql; |
||
364 | return db_query($sql); |
||
365 | } |
||
366 | |||
367 | |||
368 | /** |
||
369 | * Create a new artifact (and its values) in the db |
||
370 | * |
||
371 | * @param array $vfl the value-field-list. Array association pair of field_name => field_value. |
||
372 | * If the function is called by the web-site submission form, the $vfl is set to false, and will be filled by the function extractFieldList function retrieving the HTTP parameters. |
||
373 | * If $vfl is not false, the fields expected in this array are *all* the fields of this tracker that are allowed to be submited by the user. |
||
374 | * @return boolean |
||
375 | */ |
||
376 | function create($vfl=false,$import=false,$row=0) { |
||
609 | |||
610 | |||
611 | |||
612 | /** |
||
613 | * Add a followup comment |
||
614 | * |
||
615 | * @param comment: the comment |
||
616 | * @param email: user email if the user is not logged in |
||
617 | * @param changes (OUT): array of changes (for notifications) |
||
618 | * |
||
619 | * @return boolean |
||
620 | */ |
||
621 | function addComment($comment,$email=false,&$changes,$comment_format=self::FORMAT_TEXT) { |
||
622 | |||
623 | global $art_field_fact,$Language; |
||
624 | |||
625 | // Add a new comment if there is one |
||
626 | if ($comment != '') { |
||
627 | |||
628 | // For none project members force the comment type to None (100) |
||
629 | if ( !user_isloggedin() ) { |
||
630 | if ( $email ) { |
||
631 | $this->addHistory('comment', "", htmlspecialchars($comment), 100, $email, null, $comment_format); |
||
632 | } else { |
||
633 | $GLOBALS['Response']->addFeedback('error', $Language->getText('tracker_common_artifact','enter_email')); |
||
634 | return false; |
||
635 | } |
||
636 | } else { |
||
637 | $this->addHistory('comment', "", htmlspecialchars($comment), 100, null, null, $comment_format); |
||
638 | } |
||
639 | $changes['comment']['add'] = stripslashes($comment); |
||
640 | $changes['comment']['type'] = $Language->getText('global','none'); |
||
641 | |||
642 | $GLOBALS['Response']->addFeedback('info', $Language->getText('tracker_common_artifact','add_comment')); |
||
643 | return true; |
||
644 | } else { |
||
645 | return false; |
||
646 | } |
||
647 | } |
||
648 | |||
649 | |||
650 | /** |
||
651 | * handle a simple follow-up comment |
||
652 | * Followup comments are added in the bug history along with the comment type. |
||
653 | * |
||
654 | * If a canned response is given it overrides anything typed in the followup |
||
655 | * comment text area |
||
656 | * |
||
657 | * @param comment (IN) : the comment that the user typed in |
||
658 | * @param canned_response (IN) : the id of the canned response |
||
659 | */ |
||
660 | function addFollowUpComment($comment,$comment_type_id,$canned_response,&$changes,$comment_format=self::FORMAT_TEXT) { |
||
661 | global $art_field_fact,$Language; |
||
662 | if ($canned_response && $canned_response != 100) { |
||
663 | |||
664 | $sql="SELECT * FROM artifact_canned_responses WHERE artifact_canned_id='". db_ei($canned_response) ."'"; |
||
665 | $res3=db_query($sql); |
||
666 | |||
667 | if ($res3 && db_numrows($res3) > 0) { |
||
668 | $comment = util_unconvert_htmlspecialchars(db_result($res3,0,'body')); |
||
669 | $GLOBALS['Response']->addFeedback('info', $Language->getText('tracker_common_artifact','canned_used')); |
||
670 | } else { |
||
671 | $GLOBALS['Response']->addFeedback('error', $Language->getText('tracker_common_artifact','unable_canned')); |
||
672 | $GLOBALS['Response']->addFeedback('error', db_error()); |
||
673 | } |
||
674 | } |
||
675 | |||
676 | if ($comment != '') { |
||
677 | $this->addHistory('comment', '', htmlspecialchars($comment), $comment_type_id, false, false, $comment_format); |
||
678 | $changes['comment']['add'] = $comment; |
||
679 | $changes['comment']['format'] = $comment_format; |
||
680 | |||
681 | $field = $art_field_fact->getFieldFromName("comment_type_id"); |
||
682 | if ( $field && isset($comment_type_id) && $comment_type_id) { |
||
683 | $changes['comment']['type'] = |
||
684 | $field->getValue($this->ArtifactType->getID(), $comment_type_id); |
||
685 | } |
||
686 | $reference_manager = $this->getReferenceManager(); |
||
687 | $reference_manager->extractCrossRef($comment,$this->getID(), ReferenceManager::REFERENCE_NATURE_ARTIFACT, $this->ArtifactType->getGroupID()); |
||
688 | |||
689 | return true; |
||
690 | } else { |
||
691 | return false; |
||
692 | } |
||
693 | } |
||
694 | |||
695 | /** |
||
696 | * Wrapper for tests |
||
697 | * |
||
698 | * @return ReferenceManager |
||
699 | */ |
||
700 | function getReferenceManager() { |
||
703 | |||
704 | /** |
||
705 | * Add a list of follow-up comments coming from the import facility |
||
706 | * |
||
707 | * @param parsed_comments (IN): an array (#detail => array2), where array2 is of the form |
||
708 | * ("date" => date, "by" => user, "type" => comment-type, "comment" => comment-string) |
||
709 | * @return boolean |
||
710 | */ |
||
711 | function addFollowUpComments($parsed_comments) { |
||
712 | global $Language; |
||
713 | |||
714 | $art_field_fact = new ArtifactFieldFactory($this->ArtifactType); |
||
715 | $artifact_import = new ArtifactImport($this->ArtifactType, $art_field_fact, $this->ArtifactType->Group); |
||
716 | |||
717 | while (list(,$arr) = each($parsed_comments)) { |
||
718 | $by = $arr['by']; |
||
719 | if ($by == "100") { |
||
720 | //this case should not exist in new trackers but |
||
721 | //can appear if we parse legacy bugs or tasks |
||
722 | $email = $Language->getText('global','none'); |
||
723 | $user_id = 100; |
||
724 | } else if (user_getname($by)) { |
||
725 | $user_id = $by; |
||
726 | $email = ""; |
||
727 | } else { |
||
728 | $email = $by; |
||
729 | $user_id = 100; |
||
730 | } |
||
731 | |||
732 | if ( ! $artifact_import->checkCommentExist($arr, $this->getID())) { |
||
733 | if (!$artifact_import->checkCommentExistInLegacyFormat($arr, $this->getID())) { |
||
734 | $comment = htmlspecialchars($arr['comment']); |
||
735 | $sql="insert into artifact_history(artifact_id,field_name,old_value,new_value,mod_by,email,date,type) ". |
||
736 | "VALUES (". db_ei($this->getID()) .",'comment','','". db_es($comment) ."','". db_ei($user_id) ."','". db_es($email) ."','". db_ei($arr['date']) ."','". db_ei($arr['type']) ."')"; |
||
737 | |||
738 | db_query($sql); |
||
739 | } |
||
740 | } |
||
741 | |||
742 | } |
||
743 | |||
744 | |||
745 | return true; |
||
746 | } |
||
747 | |||
748 | /** |
||
749 | * Update a follow-up comment |
||
750 | * |
||
751 | * @param comment_id: follow-up comment id |
||
752 | * @param comment_txt: text of the follow-up comment |
||
753 | * |
||
754 | * @return boolean |
||
755 | */ |
||
756 | function updateFollowupComment($comment_id,$comment_txt,&$changes, $comment_format=self::FORMAT_TEXT) { |
||
757 | if ($this->userCanEditFollowupComment($comment_id)) { |
||
758 | $sql = 'SELECT field_name, new_value, type FROM artifact_history' |
||
759 | .' WHERE artifact_id='. db_ei($this->getID()) |
||
760 | .' AND artifact_history_id='. db_ei($comment_id) |
||
761 | .' AND (field_name="comment" OR field_name LIKE "lbl_%_comment")'; |
||
762 | $qry = db_query($sql); |
||
763 | $new_value = db_result($qry,0,'new_value'); |
||
764 | $comment_type_id = db_result($qry,0,'type'); |
||
765 | if ($new_value == $comment_txt) { |
||
766 | //comment doesn't change |
||
767 | return false; |
||
768 | } |
||
769 | |||
770 | if ($qry) { |
||
771 | $fname = db_result($qry,0,'field_name'); |
||
772 | if (preg_match("/^(lbl_)/",$fname) && preg_match("/(_comment)$/",$fname)) { |
||
773 | $comment_lbl = $fname; |
||
774 | } else { |
||
775 | $comment_lbl = "lbl_".$comment_id."_comment"; |
||
776 | } |
||
777 | //now add new comment entry |
||
778 | $this->addHistory($comment_lbl,$new_value,htmlspecialchars($comment_txt), $comment_type_id,false,$comment_id,$comment_format); |
||
779 | $changes['comment']['del'] = $new_value; |
||
780 | $changes['comment']['add'] = $comment_txt; |
||
781 | $changes['comment']['format'] = $comment_format; |
||
782 | $reference_manager = $this->getReferenceManager(); |
||
783 | $reference_manager->extractCrossRef($comment_txt,$this->getID(),ReferenceManager::REFERENCE_NATURE_ARTIFACT,$this->ArtifactType->getGroupID()); |
||
784 | |||
785 | return true; |
||
786 | } else { |
||
787 | return false; |
||
788 | } |
||
789 | } else { |
||
790 | $this->setError($GLOBALS['Language']->getText('tracker_common_artifact','err_upd_comment', array($comment_id, $GLOBALS['Language']->getText('include_exit','perm_denied')))); |
||
791 | $GLOBALS['Response']->addFeedback('error',$GLOBALS['Language']->getText('tracker_common_artifact','err_upd_comment', array($comment_id, $GLOBALS['Language']->getText('include_exit','perm_denied')))); |
||
792 | return false; |
||
793 | } |
||
794 | |||
795 | } |
||
796 | |||
797 | /** |
||
798 | * Update an artifact. Rk: vfl is an variable list of fields, Vary from one project to another |
||
799 | * return true if artifact updated, false if nothing changed or DB update failed |
||
800 | * |
||
801 | * @param artifact_id_dependent: artifact dependencies |
||
802 | * @param canned_response: canned responses |
||
803 | * @param changes (OUT): array of changes (for notifications) |
||
804 | * |
||
805 | * @return boolean |
||
806 | */ |
||
807 | function handleUpdate ($artifact_id_dependent,$canned_response,&$changes,$masschange=false,$vfl=false,$import=false){ |
||
1109 | |||
1110 | /** |
||
1111 | * Set the permissions |
||
1112 | */ |
||
1113 | function setPermissions($use_artifact_permissions, $ugroups) { |
||
1114 | if ($this->ArtifactType->userIsAdmin()) { |
||
1115 | if ($use_artifact_permissions) { |
||
1116 | $result = permission_process_selection_form($this->ArtifactType->getGroupID(), 'TRACKER_ARTIFACT_ACCESS', $this->getId(), $ugroups); |
||
1117 | if (!$result[0]) { |
||
1118 | return $GLOBALS['Response']->addFeedback('error', $result[1]); |
||
1119 | } |
||
1120 | //If the selected ugroup corresponds to the default one (all_user), there is no need to store it |
||
1121 | if ($ugroups[0] == $GLOBALS['UGROUP_ANONYMOUS']) { |
||
1122 | $use_artifact_permissions = 0; |
||
1123 | } |
||
1124 | } |
||
1125 | $sql = "UPDATE artifact |
||
1126 | SET use_artifact_permissions = ". ($use_artifact_permissions ? 1 : 0) ." |
||
1127 | WHERE artifact_id=". db_ei($this->getID()); |
||
1128 | db_query($sql); |
||
1129 | |||
1130 | } |
||
1131 | } |
||
1132 | |||
1133 | |||
1134 | /** |
||
1135 | * Check if an email address already exists |
||
1136 | * |
||
1137 | * @param cc: the email address |
||
1138 | * |
||
1139 | * @return boolean |
||
1140 | */ |
||
1141 | function existCC($cc) { |
||
1142 | $sql = "SELECT artifact_cc_id FROM artifact_cc WHERE artifact_id=". db_ei($this->getID()) ." AND email='". db_es($cc) ."'"; |
||
1143 | $res = db_query($sql); |
||
1144 | return (db_numrows($res) >= 1); |
||
1145 | } |
||
1146 | |||
1147 | /** |
||
1148 | * Insert an email address for the CC list |
||
1149 | * |
||
1150 | * @param cc: the email address |
||
1151 | * @param added_by: user who insert this cc list |
||
1152 | * @param comment: comment for this cc list |
||
1153 | * @param date: date of creation |
||
1154 | * |
||
1155 | * @return boolean |
||
1156 | */ |
||
1157 | function insertCC($cc,$added_by,$comment,$date) { |
||
1158 | $sql = "INSERT INTO artifact_cc (artifact_id,email,added_by,comment,date) ". |
||
1159 | "VALUES (". db_ei($this->getID()) .",'". db_es($cc) ."','". db_ei($added_by) ."','". db_es($comment) ."','". db_ei($date) ."')"; |
||
1160 | $res = db_query($sql); |
||
1161 | return ($res); |
||
1162 | |||
1163 | } |
||
1164 | |||
1165 | /** |
||
1166 | * Insert email addresses for CC list |
||
1167 | * |
||
1168 | * @param email: list of email addresses |
||
1169 | * @param comment: comment for these addresses |
||
1170 | * @param changes (OUT): list of changes |
||
1171 | * @param masschange: if in a masschange, we do not wan't to get feedback when everything ok |
||
1172 | * |
||
1173 | * @return boolean |
||
1174 | */ |
||
1175 | function addCC($email,$comment,&$changes,$masschange=false) { |
||
1176 | global $Language; |
||
1177 | |||
1178 | $user_id = (user_isloggedin() ? user_getid(): 100); |
||
1179 | |||
1180 | $arr_email = util_split_emails($email); |
||
1181 | $date = time(); |
||
1182 | $ok = true; |
||
1183 | $changed = false; |
||
1184 | |||
1185 | if (! util_validateCCList($arr_email, $message)) { |
||
1186 | exit_error($Language->getText('tracker_index','cc_list_invalid'), $message); |
||
1187 | } |
||
1188 | |||
1189 | //calculate old_values to put into artifact_history |
||
1190 | $old_value=$this->getCCEmails(); |
||
1191 | reset($arr_email); |
||
1192 | while (list(,$cc) = each($arr_email)) { |
||
1193 | // Add this cc only if not there already |
||
1194 | if (!$this->existCC($cc)) { |
||
1195 | $changed = true; |
||
1196 | $res = $this->insertCC($cc,$user_id,$comment,$date); |
||
1197 | if (!$res) { $ok = false; } |
||
1198 | } |
||
1199 | } |
||
1200 | |||
1201 | if ($old_value == '') { |
||
1202 | $new_value = join(',', $arr_email); |
||
1203 | } else { |
||
1204 | $new_value = $old_value .",".join(',', $arr_email); |
||
1205 | } |
||
1206 | |||
1207 | if (!$ok) { |
||
1208 | $GLOBALS['Response']->addFeedback('error', $Language->getText('tracker_common_artifact','cc_add_fail')); |
||
1209 | } else { |
||
1210 | $this->addHistory('cc',$old_value,$new_value); |
||
1211 | $changes['CC']['add'] = join(',', $arr_email); |
||
1212 | } |
||
1213 | return $ok; |
||
1214 | } |
||
1215 | |||
1216 | /** |
||
1217 | * Delete old cc list and add new email instead |
||
1218 | * |
||
1219 | * @param email: list of email addresses |
||
1220 | * @param comment: comment for these addresses |
||
1221 | * |
||
1222 | * @return boolean |
||
1223 | */ |
||
1224 | function updateCC($email,$comment) { |
||
1225 | global $Language; |
||
1226 | |||
1227 | $user_id = (user_isloggedin() ? user_getid(): 100); |
||
1228 | |||
1229 | $arr_email = util_split_emails($email); |
||
1230 | $date = time(); |
||
1231 | $ok = true; |
||
1232 | $changed = false; |
||
1233 | |||
1234 | if (! util_validateCCList($arr_email, $message)) { |
||
1235 | exit_error($Language->getText('tracker_index','cc_list_invalid'), $message); |
||
1236 | } |
||
1237 | |||
1238 | //calculate old_values to put into artifact_history |
||
1239 | $old_value=$this->getCCEmails(); |
||
1240 | $new_value = join(',', $arr_email); |
||
1241 | |||
1242 | //look if there is really something to do or not |
||
1243 | list($deleted_values,$added_values) = util_double_diff_array(explode(",",$old_value),$arr_email); |
||
1244 | if (count($deleted_values) == 0 && count($added_values) == 0) return true; |
||
1245 | |||
1246 | if (!$this->deleteAllCC()) { |
||
1247 | $GLOBALS['Response']->addFeedback('error', $Language->getText('tracker_common_artifact','prob_cc_list',$this->getID())); |
||
1248 | $ok = false; |
||
1249 | } |
||
1250 | |||
1251 | reset($arr_email); |
||
1252 | while (list(,$cc) = each($arr_email)) { |
||
1253 | $changed = true; |
||
1254 | $res = $this->insertCC($cc,$user_id,$comment,$date); |
||
1255 | if (!$res) { $ok = false; } |
||
1256 | } |
||
1257 | |||
1258 | if (!$ok) { |
||
1259 | $GLOBALS['Response']->addFeedback('error', $Language->getText('tracker_common_artifact','cc_add_fail')); |
||
1260 | } else { |
||
1261 | $this->addHistory('cc',$old_value,$new_value); |
||
1262 | } |
||
1263 | return $ok; |
||
1264 | } |
||
1265 | |||
1266 | |||
1267 | |||
1268 | /** |
||
1269 | * Delete an email address in the CC list |
||
1270 | * |
||
1271 | * @param artifact_cc_id: cc list id |
||
1272 | * @param changes (OUT): list of changes |
||
1273 | * |
||
1274 | * @return boolean |
||
1275 | */ |
||
1276 | function deleteCC($artifact_cc_id=false,&$changes,$masschange=false) { |
||
1277 | global $Language; |
||
1278 | |||
1279 | // If both bug_id and bug_cc_id are given make sure the cc belongs |
||
1280 | // to this bug (it's a bit paranoid but...) |
||
1281 | $sql = "SELECT artifact_id,email from artifact_cc WHERE artifact_cc_id='". db_ei($artifact_cc_id) ."'"; |
||
1282 | $res1 = db_query($sql); |
||
1283 | if ((db_numrows($res1) <= 0) || (db_result($res1,0,'artifact_id') != $this->getID()) ) { |
||
1284 | $GLOBALS['Response']->addFeedback('error', $Language->getText('tracker_common_artifact','err_cc_id',$artifact_cc_id)); |
||
1285 | return false; |
||
1286 | } |
||
1287 | |||
1288 | //calculate old_values to put into artifact_history |
||
1289 | $old_value=$this->getCCEmails(); |
||
1290 | |||
1291 | // Now delete the CC address |
||
1292 | $res2 = db_query("DELETE FROM artifact_cc WHERE artifact_cc_id='". db_ei($artifact_cc_id) ."'"); |
||
1293 | if (!$res2) { |
||
1294 | $GLOBALS['Response']->addFeedback('error', $Language->getText('tracker_common_artifact','err_del_cc',array($artifact_cc_id,db_error($res2)))); |
||
1295 | return false; |
||
1296 | } else { |
||
1297 | if (!$masschange) $GLOBALS['Response']->addFeedback('info', $Language->getText('tracker_common_artifact','cc_remove')); |
||
1298 | $new_value=$this->getCCEmails(); |
||
1299 | $this->addHistory('cc',$old_value,$new_value); |
||
1300 | $changes['CC']['del'] = db_result($res1,0,'email'); |
||
1301 | return true; |
||
1302 | } |
||
1303 | } |
||
1304 | |||
1305 | /** |
||
1306 | * Check if an artifact depends already from the current one |
||
1307 | * |
||
1308 | * @param id: the artifact id |
||
1309 | * |
||
1310 | * @return boolean |
||
1311 | */ |
||
1312 | function existDependency($id) { |
||
1313 | $sql = "SELECT is_dependent_on_artifact_id FROM artifact_dependencies WHERE artifact_id=". db_ei($this->getID()) ." AND is_dependent_on_artifact_id=". db_ei($id); |
||
1314 | //echo $sql; |
||
1315 | $res = db_query($sql); |
||
1316 | return (db_numrows($res) >= 1); |
||
1317 | } |
||
1318 | |||
1319 | /** |
||
1320 | * Check if an artifact exists |
||
1321 | * |
||
1322 | * @param id: the artifact id |
||
1323 | * |
||
1324 | * @return boolean |
||
1325 | */ |
||
1326 | function validArtifact($id) { |
||
1327 | $sql = "SELECT * FROM artifact a, artifact_group_list agl WHERE ". |
||
1328 | "a.group_artifact_id = agl.group_artifact_id AND a.artifact_id=". db_ei($id) ." AND ". |
||
1329 | "agl.status = 'A'"; |
||
1330 | $res = db_query($sql); |
||
1331 | if ( db_numrows($res) >= 1 ) |
||
1332 | return true; |
||
1333 | else |
||
1334 | return false; |
||
1335 | } |
||
1336 | |||
1337 | |||
1338 | /** |
||
1339 | * Insert a artifact dependency with the current one |
||
1340 | * |
||
1341 | * @param id: the artifact id |
||
1342 | * |
||
1343 | * @return boolean |
||
1344 | */ |
||
1345 | function insertDependency($id) { |
||
1346 | $sql = "INSERT INTO artifact_dependencies (artifact_id,is_dependent_on_artifact_id) ". |
||
1347 | "VALUES (". db_ei($this->getID()) .",". db_ei($id) .")"; |
||
1348 | //echo $sql; |
||
1349 | $res = db_query($sql); |
||
1350 | return ($res); |
||
1351 | |||
1352 | } |
||
1353 | |||
1354 | |||
1355 | /** |
||
1356 | * Delete all the CC Names of this Artifact |
||
1357 | */ |
||
1358 | function deleteAllCC() { |
||
1359 | $sql = "SELECT artifact_cc_id FROM artifact_cc WHERE artifact_id=". db_ei($this->getID()) ; |
||
1360 | $res = db_query($sql); |
||
1361 | if (db_numrows($res) > 0) { |
||
1362 | for ($i=0;$i<db_numrows($res);$i++) { |
||
1363 | if ($i==0) $ccNames = db_result($res,$i,'artifact_cc_id'); |
||
1364 | else $ccNames .= ",".db_result($res,$i,'artifact_cc_id'); |
||
1365 | } |
||
1366 | $sql = "DELETE FROM artifact_cc WHERE artifact_cc_id IN (". db_es($ccNames) .") AND artifact_id=". db_ei($this->getID()) ; |
||
1367 | $res_del = db_query($sql); |
||
1368 | if (!$res_del) return false; |
||
1369 | } |
||
1370 | return true; |
||
1371 | } |
||
1372 | |||
1373 | /** |
||
1374 | * Delete all the dependencies of this Artifact |
||
1375 | */ |
||
1376 | function deleteAllDependencies() { |
||
1377 | $sql = "SELECT is_dependent_on_artifact_id FROM artifact_dependencies WHERE artifact_id=". db_ei($this->getID()) ; |
||
1378 | $res = db_query($sql); |
||
1379 | if (db_numrows($res) > 0) { |
||
1380 | for ($i=0;$i<db_numrows($res);$i++) { |
||
1381 | if ($i==0) $dependencies = db_result($res,$i,'is_dependent_on_artifact_id'); |
||
1382 | else $dependencies .= ",".db_result($res,$i,'is_dependent_on_artifact_id'); |
||
1383 | } |
||
1384 | $sql = "DELETE FROM artifact_dependencies WHERE is_dependent_on_artifact_id IN (". db_es($dependencies) .") AND artifact_id=". db_ei($this->getID()) ; |
||
1385 | $res_del = db_query($sql); |
||
1386 | if (!$res_del) return false; |
||
1387 | } |
||
1388 | return true; |
||
1389 | } |
||
1390 | |||
1391 | |||
1392 | /** |
||
1393 | * Insert artifact dependencies |
||
1394 | * |
||
1395 | * @param artifact_id_dependent: list of artifact which are depend on (comma sperator) |
||
1396 | * @param changes (OUT): list of changes |
||
1397 | * |
||
1398 | * @return boolean |
||
1399 | */ |
||
1400 | function addDependencies($artifact_id_dependent,&$changes,$masschange, $import = false) { |
||
1401 | if ( !$artifact_id_dependent ) |
||
1402 | return true; |
||
1403 | |||
1404 | $ok = true; |
||
1405 | $ids = explode(",",$artifact_id_dependent); |
||
1406 | while (list(,$id) = each($ids)) { |
||
1407 | // Add this id only if not already exist |
||
1408 | //echo "add id=".$id."<br>"; |
||
1409 | |||
1410 | // Remove potential spaces (if the list of IDs are entered like that : 171, 765, 555) |
||
1411 | $id = trim($id); |
||
1412 | |||
1413 | // Check existance |
||
1414 | if (!$this->validArtifact($id)) { |
||
1415 | |||
1416 | // at import stage, $id can have value "None" or "Aucun" |
||
1417 | if ( ! $import || $id != $GLOBALS['Language']->getText('global','none')) { |
||
1418 | $ok = false; |
||
1419 | $GLOBALS['Response']->addFeedback('error', $GLOBALS['Language']->getText('tracker_common_artifact','invalid_art',$id)); |
||
1420 | } |
||
1421 | } |
||
1422 | if ($ok && ($id != $this->getID()) && !$this->existDependency($id)) { |
||
1423 | $res = $this->insertDependency($id); |
||
1424 | if (!$res) { $ok = false; } |
||
1425 | } |
||
1426 | } |
||
1427 | |||
1428 | if (!$ok) { |
||
1429 | $GLOBALS['Response']->addFeedback('error', $GLOBALS['Language']->getText('tracker_common_artifact','depend_add_fail',$this->getID())); |
||
1430 | } else { |
||
1431 | $changes['Dependencies']['add'] = $artifact_id_dependent; |
||
1432 | } |
||
1433 | return $ok; |
||
1434 | } |
||
1435 | |||
1436 | /** |
||
1437 | * Delete an artifact id from the dependencies list |
||
1438 | * |
||
1439 | * @param dependent_on_artifact_id: artifact id which is depend on |
||
1440 | * @param changes (OUT): list of changes |
||
1441 | * |
||
1442 | * @return boolean |
||
1443 | */ |
||
1444 | function deleteDependency($dependent_on_artifact_id,&$changes) { |
||
1445 | global $Language; |
||
1446 | |||
1447 | // Delete the dependency |
||
1448 | $sql = "DELETE FROM artifact_dependencies WHERE is_dependent_on_artifact_id=". db_ei($dependent_on_artifact_id) ." AND artifact_id=". db_ei($this->getID()) ; |
||
1449 | $res2 = db_query($sql); |
||
1450 | if (!$res2) { |
||
1451 | $GLOBALS['Response']->addFeedback('error', " - Error deleting dependency $dependent_on_artifact_id: ".db_error($res2)); |
||
1452 | return false; |
||
1453 | } else { |
||
1454 | $GLOBALS['Response']->addFeedback('info', $Language->getText('tracker_common_artifact','depend_removed')); |
||
1455 | $changes['Dependencies']['del'] = $dependent_on_artifact_id; |
||
1456 | return true; |
||
1457 | } |
||
1458 | } |
||
1459 | |||
1460 | /** |
||
1461 | * Delete a followup comment from the artifact |
||
1462 | * |
||
1463 | * @param aid: the artifact id |
||
1464 | * @param comment_id: the followup comment id |
||
1465 | * |
||
1466 | * @return boolean |
||
1467 | */ |
||
1468 | function deleteFollowupComment($aid,$comment_id) { |
||
1469 | if ($this->userCanEditFollowupComment($comment_id)) { |
||
1470 | //Delete the followup comment |
||
1471 | $sel = 'SELECT field_name, new_value FROM artifact_history' |
||
1472 | .' WHERE (field_name = "comment" OR field_name LIKE "lbl_%_comment")' |
||
1473 | .' AND artifact_history_id = '. db_ei($comment_id) |
||
1474 | .' AND artifact_id = '. db_ei($aid) ; |
||
1475 | $res = db_query($sel); |
||
1476 | $new_value = db_result($res,0,'new_value'); |
||
1477 | if ($res) { |
||
1478 | $fname = db_result($res,0,'field_name'); |
||
1479 | if (preg_match("/^(lbl_)/",$fname) && preg_match("/(_comment)$/",$fname)) { |
||
1480 | $comment_lbl = $fname; |
||
1481 | } else { |
||
1482 | $comment_lbl = "lbl_".$comment_id."_comment"; |
||
1483 | } |
||
1484 | //now add a new history entry |
||
1485 | $this->addHistory($comment_lbl,$new_value,'',false,false,$comment_id); |
||
1486 | $GLOBALS['Response']->addFeedback('info',$GLOBALS['Language']->getText('tracker_common_artifact','comment_removed')); |
||
1487 | return true; |
||
1488 | } else { |
||
1489 | $GLOBALS['Response']->addFeedback('error',$GLOBALS['Language']->getText('tracker_common_artifact','err_del_comment',array($comment_id,db_error($res)))); |
||
1490 | return false; |
||
1491 | } |
||
1492 | } else { |
||
1493 | $this->setError($GLOBALS['Language']->getText('tracker_common_artifact','err_del_comment', array($comment_id, $GLOBALS['Language']->getText('include_exit','perm_denied')))); |
||
1494 | $GLOBALS['Response']->addFeedback('error',$GLOBALS['Language']->getText('tracker_common_artifact','err_del_comment', array($comment_id, $GLOBALS['Language']->getText('include_exit','perm_denied')))); |
||
1495 | return false; |
||
1496 | } |
||
1497 | |||
1498 | } |
||
1499 | |||
1500 | /** |
||
1501 | * Return if the status is closed status |
||
1502 | * |
||
1503 | * @param status: the status |
||
1504 | * |
||
1505 | * @return boolean |
||
1506 | */ |
||
1507 | function isStatusClosed($status) { |
||
1510 | |||
1511 | |||
1512 | /** |
||
1513 | * get all the field values for this artifact |
||
1514 | * |
||
1515 | * @return array |
||
1516 | */ |
||
1517 | function getFieldsValues() { |
||
1518 | |||
1519 | // get the artifact data |
||
1520 | $this->fetchData($this->getID()); |
||
1521 | return $this->data_array; |
||
1522 | } |
||
1523 | |||
1524 | /** |
||
1525 | * Return the user (user_id) that have posted follow up (comment_id) |
||
1526 | * |
||
1527 | * @return int |
||
1528 | */ |
||
1529 | function getCommenter($comment_id) { |
||
1530 | |||
1531 | $sql = 'SELECT mod_by FROM artifact_history' |
||
1532 | .' WHERE artifact_id='. db_ei($this->getID()) |
||
1533 | .' AND field_name="comment"' |
||
1534 | .' AND mod_by != 100' |
||
1535 | .' AND artifact_history_id='. db_ei($comment_id); |
||
1536 | $res = db_query($sql); |
||
1537 | return db_result($res,0,'mod_by'); |
||
1538 | |||
1539 | } |
||
1540 | |||
1541 | /** |
||
1542 | * Return the users that have posted follow ups |
||
1543 | * |
||
1544 | * @return array |
||
1545 | */ |
||
1546 | function getCommenters() { |
||
1547 | $sql="SELECT DISTINCT mod_by FROM artifact_history ". |
||
1548 | "WHERE artifact_id=". db_ei($this->getID()) ." ". |
||
1549 | "AND field_name = 'comment' AND mod_by != 100"; |
||
1550 | return db_query($sql); |
||
1551 | } |
||
1552 | |||
1553 | /** |
||
1554 | * Return the mails of anonymous users that have posted follow ups |
||
1555 | * |
||
1556 | * @return array |
||
1557 | */ |
||
1558 | function getAnonymousCommenters() { |
||
1559 | $sql="SELECT DISTINCT email FROM artifact_history ". |
||
1560 | "WHERE artifact_id=". db_ei($this->getID()) ." ". |
||
1561 | "AND field_name = 'comment' ". |
||
1562 | "AND mod_by = 100"; |
||
1563 | return db_query($sql); |
||
1564 | } |
||
1565 | |||
1566 | /** |
||
1567 | * Get follow-up comment text |
||
1568 | * |
||
1569 | * @param Integer $comment_id |
||
1570 | * |
||
1571 | * @return String |
||
1572 | */ |
||
1573 | function getFollowup($comment_id) { |
||
1577 | |||
1578 | /** |
||
1579 | * Get all details of a follow-up comment |
||
1580 | * |
||
1581 | * @param Integer $comment_id |
||
1582 | * |
||
1583 | * @return Array |
||
1584 | */ |
||
1585 | function getFollowUpDetails($comment_id) { |
||
1596 | |||
1597 | /** |
||
1598 | * Return the follow ups |
||
1599 | * |
||
1600 | * @return array |
||
1601 | */ |
||
1602 | function getFollowups () { |
||
1603 | global $art_field_fact; |
||
1604 | |||
1605 | $flup_array = array(); |
||
1606 | $qry = 'SELECT artifact_history_id, date FROM artifact_history'. |
||
1607 | ' WHERE artifact_id = '. db_ei($this->getID()) . |
||
1608 | ' AND field_name = "comment"'; |
||
1609 | $res = db_query($qry); |
||
1610 | while ($row = db_fetch_array($res)) { |
||
1611 | $ahid = $row['artifact_history_id']; |
||
1612 | $fname = "lbl_".$ahid."_comment"; |
||
1613 | $sel = 'SELECT NULL FROM artifact_history'. |
||
1614 | ' WHERE field_name = "'. db_es($fname) .'"'. |
||
1615 | ' AND artifact_id = '. db_ei($this->getID()) ; |
||
1616 | $result = db_query($sel); |
||
1617 | if (db_numrows($result) < 1) { |
||
1618 | //the followup comment was not edited/removed ==> add it to the list of comments to be displayed |
||
1619 | $flup_array[$ahid] = $row['date']; |
||
1620 | } else { |
||
1621 | //pick the latest |
||
1622 | $latest = 'SELECT artifact_history_id , new_value FROM artifact_history'. |
||
1623 | ' WHERE field_name = "'. db_es($fname) .'"'. |
||
1624 | ' AND artifact_id = '. db_ei($this->getID()) . |
||
1625 | ' AND date = (SELECT MAX(date) FROM artifact_history'. |
||
1626 | ' WHERE field_name = "'. db_es($fname) .'"'. |
||
1627 | ' AND artifact_id = '. db_ei($this->getID()) .')'; |
||
1628 | $res_latest = db_query($latest); |
||
1629 | $new_value = db_result($res_latest,0,'new_value'); |
||
1630 | if ($new_value <> '') { |
||
1631 | //if new_value eq '' ==> the followup comment was removed, don't display it |
||
1632 | $art_hist_id = db_result($res_latest,0,'artifact_history_id'); |
||
1633 | $flup_array[$art_hist_id] = $row['date']; |
||
1634 | } |
||
1635 | } |
||
1636 | } |
||
1637 | arsort($flup_array); |
||
1638 | $comment_array = array_keys($flup_array); |
||
1639 | |||
1640 | $field = $art_field_fact->getFieldFromName('comment_type_id'); |
||
1641 | if ( $field ) { |
||
1642 | // Look for project specific values first |
||
1643 | $sql="SELECT DISTINCT artifact_history.artifact_history_id, artifact_history.format, artifact_history.artifact_id,artifact_history.field_name,artifact_history.old_value,artifact_history.new_value,artifact_history.date,user.user_name,artifact_history.mod_by,artifact_history.email,artifact_history.type AS comment_type_id,artifact_field_value_list.value AS comment_type ". |
||
1644 | "FROM artifact_history,artifact_field_value_list,artifact_field,user ". |
||
1645 | "WHERE artifact_history.artifact_id=". db_ei($this->getID()) ." ". |
||
1646 | "AND (artifact_history.field_name = 'comment' OR artifact_history.field_name LIKE 'lbl_%_comment') ". |
||
1647 | "AND artifact_history.mod_by=user.user_id ". |
||
1648 | "AND artifact_history.type = artifact_field_value_list.value_id ". |
||
1649 | "AND artifact_history.artifact_history_id IN (". db_es(implode(',',$comment_array)) .") ". |
||
1650 | "AND artifact_field_value_list.field_id = artifact_field.field_id ". |
||
1651 | "AND artifact_field_value_list.group_artifact_id = artifact_field.group_artifact_id ". |
||
1652 | "AND artifact_field.group_artifact_id =". db_ei($this->ArtifactType->getID()) ." ". |
||
1653 | "AND artifact_field.field_name = 'comment_type_id' ". |
||
1654 | "ORDER BY FIELD(artifact_history_id, ". db_es(implode(',',$comment_array)) .")"; |
||
1655 | $res_value = db_query($sql); |
||
1656 | $rows=db_numrows($res_value); |
||
1657 | |||
1658 | //echo "sql=".$sql." - rows=".$rows."<br>"; |
||
1659 | } else { |
||
1660 | // Look for project specific values first |
||
1661 | $sql="SELECT DISTINCT artifact_history.artifact_history_id, artifact_history.format, artifact_history.artifact_id,artifact_history.field_name,artifact_history.old_value,artifact_history.new_value,artifact_history.date,user.user_name,artifact_history.mod_by,artifact_history.email,artifact_history.type AS comment_type_id,null AS comment_type ". |
||
1662 | "FROM artifact_history,user ". |
||
1663 | "WHERE artifact_history.artifact_id=".$this->getID()." ". |
||
1664 | "AND (artifact_history.field_name = 'comment' OR artifact_history.field_name LIKE 'lbl_%_comment') ". |
||
1665 | "AND artifact_history.mod_by=user.user_id ". |
||
1666 | "AND artifact_history.artifact_history_id IN (". db_es(implode(',',$comment_array)) .") ". |
||
1667 | "ORDER BY FIELD(artifact_history_id, ". db_es(implode(',',$comment_array)) .")"; |
||
1668 | $res_value = db_query($sql); |
||
1669 | $rows=db_numrows($res_value); |
||
1670 | |||
1671 | } |
||
1672 | return($res_value); |
||
1673 | |||
1674 | } |
||
1675 | |||
1676 | /** |
||
1677 | * Return the history events for this artifact (excluded comment events - See followups) |
||
1678 | * |
||
1679 | * @return array |
||
1680 | */ |
||
1681 | function getHistory () { |
||
1682 | |||
1683 | //Addition of new followup comments is not recorded in history (update and removal of followups is recorded) |
||
1684 | $sql="SELECT artifact_history.field_name,artifact_history.old_value,artifact_history.new_value,artifact_history.date,artifact_history.type,user.user_name ". |
||
1685 | "FROM artifact_history,user ". |
||
1686 | "WHERE artifact_history.mod_by=user.user_id ". |
||
1687 | "AND artifact_id=". db_ei($this->getID()) . |
||
1688 | " AND artifact_history.field_name <> 'comment' ". |
||
1689 | "ORDER BY artifact_history.date DESC"; |
||
1690 | return db_query($sql); |
||
1691 | } |
||
1692 | |||
1693 | /** |
||
1694 | * Return the CC list values |
||
1695 | * |
||
1696 | * @return array |
||
1697 | */ |
||
1698 | function getCCList() { |
||
1699 | |||
1700 | $sql="SELECT artifact_cc_id,artifact_cc.email,artifact_cc.added_by,artifact_cc.comment,artifact_cc.date,user.user_name ". |
||
1701 | "FROM artifact_cc,user ". |
||
1702 | "WHERE added_by=user.user_id ". |
||
1703 | "AND artifact_id=". db_ei($this->getID()) ." ORDER BY date DESC"; |
||
1704 | return db_query($sql); |
||
1705 | } |
||
1706 | |||
1707 | /** |
||
1708 | * Return the user ids of registered users in the CC list |
||
1709 | * |
||
1710 | * @return array |
||
1711 | */ |
||
1712 | function getCCIdList() { |
||
1713 | |||
1714 | $sql="SELECT u.user_id ". |
||
1715 | "FROM artifact_cc cc, user u ". |
||
1716 | "WHERE cc.email = u.user_name ". |
||
1717 | "AND cc.artifact_id=". db_ei($this->getID()) ; |
||
1718 | $res = db_query($sql); |
||
1719 | |||
1720 | return util_result_column_to_array($res); |
||
1721 | } |
||
1722 | |||
1723 | /** |
||
1724 | * Return the CC list emails only |
||
1725 | * |
||
1726 | * @return string |
||
1727 | */ |
||
1728 | function getCCEmails() { |
||
1729 | |||
1730 | $sql="SELECT email ". |
||
1731 | "FROM artifact_cc ". |
||
1732 | "WHERE artifact_id=". db_ei($this->getID()) ." ORDER BY date DESC"; |
||
1733 | $result = db_query($sql); |
||
1734 | $rows=db_numrows($result); |
||
1735 | if ($rows <= 0) { |
||
1736 | return ''; |
||
1737 | } else { |
||
1738 | $email_arr=array(); |
||
1739 | for ($i=0; $i < $rows; $i++) { |
||
1740 | $email_arr[] = db_result($result, $i, 'email'); |
||
1741 | } |
||
1742 | $old_value = join(",",$email_arr); |
||
1743 | return $old_value; |
||
1744 | } |
||
1745 | } |
||
1746 | |||
1747 | /** |
||
1748 | * Return a CC list values |
||
1749 | * |
||
1750 | * @param artifact_cc_id: the artifact cc id |
||
1751 | * |
||
1752 | * @return array |
||
1753 | */ |
||
1754 | function getCC($artifact_cc_id) { |
||
1755 | |||
1756 | $sql="SELECT artifact_cc_id,artifact_cc.email,artifact_cc.added_by,artifact_cc.comment,artifact_cc.date,user.user_name ". |
||
1757 | "FROM artifact_cc,user ". |
||
1758 | "WHERE artifact_cc_id=". db_ei($artifact_cc_id) ." ". |
||
1759 | "AND added_by=user.user_id"; |
||
1760 | $res = db_query($sql); |
||
1761 | return db_fetch_array($res); |
||
1762 | } |
||
1763 | |||
1764 | /** |
||
1765 | * Return the artifact dependencies values |
||
1766 | * |
||
1767 | * @return array |
||
1768 | */ |
||
1769 | function getDependencies() { |
||
1770 | |||
1771 | $sql="SELECT d.artifact_depend_id, d.is_dependent_on_artifact_id, d.artifact_id, a.summary, afvl.value as status, ag.group_artifact_id, ag.name, g.group_id, g.group_name ". |
||
1772 | "FROM artifact_dependencies d, artifact_group_list ag, groups g, artifact a, artifact_field_value_list afvl, artifact_field f ". |
||
1773 | "WHERE d.is_dependent_on_artifact_id = a.artifact_id AND ". |
||
1774 | "afvl.field_id = f.field_id AND ". |
||
1775 | "f.group_artifact_id = a.group_artifact_id AND ". |
||
1776 | "f.field_name = 'status_id' AND ". |
||
1777 | "afvl.value_id = a.status_id AND ". |
||
1778 | "afvl.group_artifact_id = a.group_artifact_id AND ". |
||
1779 | "a.group_artifact_id = ag.group_artifact_id AND ". |
||
1780 | "d.artifact_id = ". db_ei($this->getID()) ." AND ". |
||
1781 | "ag.group_id = g.group_id ORDER BY a.artifact_id"; |
||
1782 | //echo "sql=$sql<br>"; |
||
1783 | return db_query($sql); |
||
1784 | } |
||
1785 | |||
1786 | /** |
||
1787 | * Return the artifact inverse dependencies values |
||
1788 | * |
||
1789 | * @return array |
||
1790 | */ |
||
1791 | function getInverseDependencies() { |
||
1792 | |||
1793 | $sql="SELECT d.artifact_depend_id, d.is_dependent_on_artifact_id, d.artifact_id, a.summary, afvl.value as status, ag.group_artifact_id, ag.name, g.group_id, g.group_name ". |
||
1794 | "FROM artifact_dependencies d, artifact_group_list ag, groups g, artifact a, artifact_field_value_list afvl, artifact_field f ". |
||
1795 | "WHERE d.artifact_id = a.artifact_id AND ". |
||
1796 | "afvl.field_id = f.field_id AND ". |
||
1797 | "f.group_artifact_id = a.group_artifact_id AND ". |
||
1798 | "f.field_name = 'status_id' AND ". |
||
1799 | "afvl.value_id = a.status_id AND ". |
||
1800 | "afvl.group_artifact_id = a.group_artifact_id AND ". |
||
1801 | "a.group_artifact_id = ag.group_artifact_id AND ". |
||
1802 | "d.is_dependent_on_artifact_id = ". db_ei($this->getID()) ." AND ". |
||
1803 | "ag.group_id = g.group_id ORDER BY a.artifact_id"; |
||
1804 | //echo "sql=$sql<br>"; |
||
1805 | return db_query($sql); |
||
1806 | } |
||
1807 | |||
1808 | /** |
||
1809 | * Return the names of attached files |
||
1810 | * |
||
1811 | * @return string |
||
1812 | */ |
||
1813 | function getAttachedFileNames () { |
||
1814 | $sql="SELECT filename ". |
||
1815 | "FROM artifact_file ". |
||
1816 | "WHERE artifact_id=". db_ei($this->getID()) ." ORDER BY adddate DESC"; |
||
1817 | $result = db_query($sql); |
||
1818 | $rows=db_numrows($result); |
||
1819 | if ($rows <= 0) { |
||
1820 | return ''; |
||
1821 | } else { |
||
1822 | $name_arr=array(); |
||
1823 | for ($i=0; $i < $rows; $i++) { |
||
1824 | $name_arr[] = db_result($result, $i, 'filename'); |
||
1825 | } |
||
1826 | $old_value = join(',',$name_arr); |
||
1827 | return $old_value; |
||
1828 | } |
||
1829 | } |
||
1830 | |||
1831 | /** |
||
1832 | * Return the attached files |
||
1833 | * |
||
1834 | * @return array |
||
1835 | */ |
||
1836 | function getAttachedFiles () { |
||
1837 | $sql="SELECT id,artifact_id,filename,filesize,filetype,description,bin_data,adddate,user.user_name ". |
||
1838 | "FROM artifact_file,user ". |
||
1839 | "WHERE submitted_by=user.user_id ". |
||
1840 | "AND artifact_id=". db_ei($this->getID()) ." ORDER BY adddate DESC"; |
||
1841 | //echo "sql=$sql<br>"; |
||
1842 | return db_query($sql); |
||
1843 | } |
||
1844 | |||
1845 | /** |
||
1846 | * Return a attached file |
||
1847 | * |
||
1848 | * @param id: the file id |
||
1849 | * |
||
1850 | * @return array |
||
1851 | */ |
||
1852 | function getAttachedFile ($id) { |
||
1853 | $sql="SELECT id,filename,filesize,description,adddate,user.user_name ". |
||
1854 | "FROM artifact_file,user ". |
||
1855 | "WHERE submitted_by=user.user_id ". |
||
1856 | "AND id=". db_ei($id) ; |
||
1857 | //echo "sql=$sql<br>"; |
||
1858 | $res = db_query($sql); |
||
1859 | return db_fetch_array($res); |
||
1860 | } |
||
1861 | |||
1862 | function checkAssignees ($field_name,$result,$art_field_fact,$changes,&$user_ids) { |
||
1963 | |||
1964 | |||
1965 | |||
1966 | /** |
||
1967 | * userCanView - determine if the user can view this artifact. |
||
1968 | * |
||
1969 | * @param $my_user_id if not specified, use the current user id.. |
||
1970 | * @return boolean user_can_view. |
||
1971 | */ |
||
1972 | function userCanView($my_user_id=0) { |
||
1973 | |||
1974 | if (!$my_user_id) { |
||
1975 | $u = UserManager::instance()->getCurrentUser(); |
||
1976 | $my_user_id = $u->getId(); |
||
1977 | } else { |
||
1978 | $u = UserManager::instance()->getUserById($my_user_id); |
||
1979 | } |
||
1980 | // Super-user and Tracker admin have all rights to see even artfact that are restricted to all users |
||
1981 | if ($u->isSuperUser() || $u->isTrackerAdmin($this->ArtifactType->getGroupID(),$this->ArtifactType->getID())) { |
||
1982 | return true; |
||
1983 | } |
||
1984 | |||
1985 | |||
1986 | //Individual artifact permission |
||
1987 | $can_access = ! $this->useArtifactPermissions(); |
||
1988 | if (!$can_access) { |
||
1989 | $res=permission_db_authorized_ugroups('TRACKER_ARTIFACT_ACCESS',$this->getID()); |
||
1990 | if (db_numrows($res) > 0) { |
||
1991 | while ($row = db_fetch_array($res)) { |
||
1992 | if (ugroup_user_is_member($my_user_id, $row['ugroup_id'], $this->ArtifactType->Group->getID(), $this->ArtifactType->getID())) { |
||
1993 | $can_access = true; |
||
1994 | } |
||
1995 | } |
||
1996 | } |
||
1997 | } |
||
1998 | if ($can_access) { |
||
1999 | // Full access |
||
2000 | $res=permission_db_authorized_ugroups('TRACKER_ACCESS_FULL',$this->ArtifactType->getID()); |
||
2001 | if (db_numrows($res) > 0) { |
||
2002 | while ($row = db_fetch_array($res)) { |
||
2003 | if (ugroup_user_is_member($my_user_id, $row['ugroup_id'], $this->ArtifactType->Group->getID(), $this->ArtifactType->getID())) { |
||
2004 | return true; |
||
2005 | } |
||
2006 | } |
||
2007 | } |
||
2008 | |||
2009 | // 'submitter' access |
||
2010 | $res=permission_db_authorized_ugroups('TRACKER_ACCESS_SUBMITTER',$this->ArtifactType->getID()); |
||
2011 | if (db_numrows($res) > 0) { |
||
2012 | while ($row = db_fetch_array($res)) { |
||
2013 | if (ugroup_user_is_member($my_user_id, $row['ugroup_id'], $this->ArtifactType->Group->getID(), $this->ArtifactType->getID())) { |
||
2014 | // check that submitter is also a member |
||
2015 | if (ugroup_user_is_member($this->getSubmittedBy(), $row['ugroup_id'], $this->ArtifactType->Group->getID(), $this->ArtifactType->getID())) { |
||
2016 | return true; |
||
2017 | } |
||
2018 | } |
||
2019 | } |
||
2020 | } |
||
2021 | // 'assignee' access |
||
2022 | $res=permission_db_authorized_ugroups('TRACKER_ACCESS_ASSIGNEE',$this->ArtifactType->getID()); |
||
2023 | if (db_numrows($res) > 0) { |
||
2024 | while ($row = db_fetch_array($res)) { |
||
2025 | if (ugroup_user_is_member($my_user_id, $row['ugroup_id'], $this->ArtifactType->Group->getID(), $this->ArtifactType->getID())) { |
||
2026 | // check that one of the assignees is also a member |
||
2027 | if (ugroup_user_is_member($this->getValue('assigned_to'), $row['ugroup_id'], $this->ArtifactType->Group->getID(), $this->ArtifactType->getID())) { |
||
2028 | return true; |
||
2029 | } |
||
2030 | |||
2031 | // multi-assigned to |
||
2032 | $multi_assigned=$this->getMultiAssignedTo(); |
||
2033 | if (is_array($multi_assigned)) { |
||
2034 | foreach ($multi_assigned as $assigned) { |
||
2035 | if (ugroup_user_is_member($assigned, $row['ugroup_id'], $this->ArtifactType->Group->getID(), $this->ArtifactType->getID())) { |
||
2036 | return true; |
||
2037 | } |
||
2038 | } |
||
2039 | } |
||
2040 | } |
||
2041 | } |
||
2042 | } |
||
2043 | } |
||
2044 | return false; |
||
2045 | } |
||
2046 | |||
2047 | /** |
||
2048 | * getExtraFieldData - get an array of data for the extra fields associated with this artifact |
||
2049 | * |
||
2050 | * the array returned looks like |
||
2051 | * array( |
||
2052 | * [field_id] => fieldvalues |
||
2053 | * [field_id] => fieldvalues |
||
2054 | * ) |
||
2055 | * for multi select boxes, the values are separated by a comma |
||
2056 | * |
||
2057 | * @return array array of data |
||
2058 | */ |
||
2059 | function &getExtraFieldData() { |
||
2060 | global $art_field_fact; |
||
2061 | $extrafielddata = array(); |
||
2062 | |||
2063 | // now get the values for generic fields if any |
||
2064 | $sql = "SELECT * FROM artifact_field_value WHERE artifact_id='". db_ei($this->getID()) ."'"; |
||
2065 | $res=db_query($sql); |
||
2066 | if (!$res || db_numrows($res) < 1) { |
||
2067 | // if no result then it is possible that there isn't any generic fields |
||
2068 | return; |
||
2069 | } |
||
2070 | // Walk the database result (possible to get several values with a same field_id (multi select box)) |
||
2071 | while ($row = db_fetch_array($res)) { |
||
2072 | $data_fields[$row['field_id']][] = $row; |
||
2073 | } |
||
2074 | |||
2075 | // compute the extrafielddata array by walking the data_fields array |
||
2076 | $extrafielddata = array(); |
||
2077 | foreach ($data_fields as $field_id => $data_field) { |
||
2078 | $current_field = $art_field_fact->getFieldFromId($field_id); |
||
2079 | if (isset($current_field) && $current_field && !$current_field->isError()) { |
||
2080 | // $values contains the values of the field |
||
2081 | $values = array(); |
||
2082 | foreach ($data_field as $data_value) { |
||
2083 | $values[] = $data_value[$current_field->getValueFieldName()]; |
||
2084 | } |
||
2085 | // if there is more than one value, we separate them with a comma. |
||
2086 | // if not, implode will return the single value. |
||
2087 | $extrafielddata[$field_id] = implode(",", $values); |
||
2088 | } |
||
2089 | } |
||
2090 | return $extrafielddata; |
||
2091 | } |
||
2092 | |||
2093 | |||
2094 | /** |
||
2095 | * Build an array of user_ids using the changes array |
||
2096 | * |
||
2097 | * @param changes (IN): array of changes |
||
2098 | * |
||
2099 | * @param concerned_ids (OUT): user_ids of concerned users (attention user_ids are stored as keys) |
||
2100 | * @param concerned_addresses (OUT): email addresses of anonymous users (for instance in CC addresses) |
||
2101 | * |
||
2102 | */ |
||
2103 | function buildNotificationArrays($changes,&$concerned_ids,&$concerned_addresses) { |
||
2202 | |||
2203 | |||
2204 | |||
2205 | /** group users to be notified of artifact changes |
||
2206 | * groups are done with respect to ugroups and |
||
2207 | * their permissions on the artifact |
||
2208 | * @param user_id an array of user ids |
||
2209 | * return $user_sets array of arrays of user ids: |
||
2210 | * return $ugroup_sets array of arrays of ugroup_ids. |
||
2211 | * the $user_sets keys correspond to the $ugroup_sets keys i.e. |
||
2212 | * $ugroup_sets[x] are the ugroups that the users in $user_sets[x] |
||
2213 | * belong to |
||
2214 | */ |
||
2215 | function groupNotificationList($user_ids,&$user_sets,&$ugroup_sets) { |
||
2216 | |||
2217 | $group_id = $this->ArtifactType->getGroupID(); |
||
2218 | $group_artifact_id = $this->ArtifactType->getID(); |
||
2219 | |||
2220 | $user_sets = array(); |
||
2221 | $ugroup_sets = array(); |
||
2222 | |||
2223 | //go through user_ids array: |
||
2224 | //for each user have a look at which ugroups he belongs |
||
2225 | |||
2226 | |||
2227 | foreach ($user_ids as $user_id) { |
||
2228 | $specific_ugroups = ugroup_db_list_tracker_ugroups_for_user($group_id,$group_artifact_id,$user_id); |
||
2229 | //echo "<br>specific_ugroups for $user_id = "; print_r($specific_ugroups); |
||
2230 | $dynamic_ugroups = ugroup_db_list_dynamic_ugroups_for_user($group_id,$group_artifact_id,$user_id); |
||
2231 | //echo "<br>dynamic_ugroups for $user_id = "; print_r($dynamic_ugroups); |
||
2232 | $all_ugroups = array_merge($dynamic_ugroups, $specific_ugroups); |
||
2233 | //echo "<br>all_ugroups for $user_id = "; print_r($all_ugroups); |
||
2234 | |||
2235 | $found_gr = false; |
||
2236 | while (list($x,$ug) = each($ugroup_sets)) { |
||
2237 | $diff1 = array_diff($ug,$all_ugroups); |
||
2238 | $diff2 = array_diff($all_ugroups,$ug); |
||
2239 | if ( empty($diff1) && empty($diff2) ) { |
||
2240 | // we found the magic users that are part of exactly the same ugroups as this user |
||
2241 | $gr = $user_sets[$x]; |
||
2242 | $gr[] = $user_id; |
||
2243 | unset($user_sets[$x]); |
||
2244 | $user_sets[$x] = $gr; |
||
2245 | $found_gr = true; |
||
2246 | break; |
||
2247 | } |
||
2248 | } |
||
2249 | // if we didn't find users who have exactly the same permissions we have to add this user separately |
||
2250 | if (!$found_gr) { |
||
2251 | $user_sets[] = array($user_id); |
||
2252 | $ugroup_sets[] = $all_ugroups; |
||
2253 | } |
||
2254 | } |
||
2255 | |||
2256 | } |
||
2257 | |||
2258 | /** |
||
2259 | * Checks if a user is allowed to delete and update a follow-up comment |
||
2260 | * |
||
2261 | * @param user_id |
||
2262 | * @param comment_id |
||
2263 | * |
||
2264 | * @return boolean |
||
2265 | */ |
||
2266 | function userCanEditFollowupComment($comment_id) { |
||
2286 | |||
2287 | /** |
||
2288 | * Checks if the comment was removed |
||
2289 | * |
||
2290 | * @params int comment_id |
||
2291 | * |
||
2292 | * @return boolean |
||
2293 | */ |
||
2294 | function isFollowupCommentDeleted($comment_id) { |
||
2295 | |||
2296 | $sql = 'SELECT artifact_id, new_value |
||
2297 | FROM artifact_history |
||
2298 | WHERE artifact_history_id = '. db_ei($comment_id) ; |
||
2299 | $res = db_query($sql); |
||
2300 | if (db_result($res,0,'new_value') == "") { |
||
2301 | return true; |
||
2302 | } |
||
2303 | $lbl = "lbl_".$comment_id."_comment"; |
||
2304 | $aid = db_result($res,0,'artifact_id'); |
||
2305 | $qry = 'SELECT NULL FROM artifact_history' |
||
2306 | .' WHERE artifact_id = '. db_ei($aid) |
||
2307 | .' AND field_name = "'. db_es($lbl) .'"' |
||
2308 | .' AND new_value = ""'; |
||
2309 | $result = db_query($qry); |
||
2310 | if (db_numrows($result) > 0) { |
||
2311 | return true; |
||
2312 | } else { |
||
2313 | return false; |
||
2314 | } |
||
2315 | |||
2316 | } |
||
2317 | |||
2318 | /** |
||
2319 | * Gets the original submitter of a follow-up comment |
||
2320 | * |
||
2321 | * @param int comment_id |
||
2322 | * |
||
2323 | * @return result set |
||
2324 | */ |
||
2325 | function getOriginalCommentSubmitter($comment_id) { |
||
2326 | |||
2327 | $sql = 'SELECT field_name, mod_by, email |
||
2328 | FROM artifact_history |
||
2329 | WHERE artifact_history_id = '. db_ei($comment_id) ; |
||
2330 | $res = db_query($sql); |
||
2331 | $field_name = db_result($res,0,'field_name'); |
||
2332 | if ($field_name == "comment") { |
||
2333 | return $res; |
||
2334 | } else if (preg_match("/^(lbl_)/",$field_name) && preg_match("/(_comment)$/",$field_name)) { |
||
2335 | // extract id of the original comment |
||
2336 | $id = (int) substr($field_name,4,-8); |
||
2337 | $qry = 'SELECT mod_by, email |
||
2338 | FROM artifact_history |
||
2339 | WHERE artifact_history_id = '. db_ei($id) .' |
||
2340 | AND field_name = "comment"'; |
||
2341 | $result = db_query($qry); |
||
2342 | return $result; |
||
2343 | } |
||
2344 | |||
2345 | } |
||
2346 | |||
2347 | /** |
||
2348 | * Gets the original submission date of a follow-up comment |
||
2349 | * |
||
2350 | * @param int comment_id |
||
2351 | * |
||
2352 | * @return result set |
||
2353 | */ |
||
2354 | function getOriginalCommentDate($comment_id) { |
||
2373 | |||
2374 | /** |
||
2375 | * Send different messages to persons affected by this artifact with respect |
||
2376 | * to their different permissions |
||
2377 | * |
||
2378 | * @param more_addresses: additional addresses |
||
2379 | * @param changes: array of changes |
||
2380 | * |
||
2381 | * @return void |
||
2382 | */ |
||
2383 | function mailFollowupWithPermissions($more_addresses=false,$changes=false) { |
||
2384 | global $art_field_fact,$Language; |
||
2385 | |||
2386 | // check if notification is temporarily stopped in this tracker |
||
2387 | if (!$this->ArtifactType->getStopNotification()) { |
||
2388 | $group = $this->ArtifactType->getGroup(); |
||
2389 | $group_artifact_id = $this->ArtifactType->getID(); |
||
2390 | $group_id = $group->getGroupId(); |
||
2391 | |||
2392 | // See who is going to receive the notification. Plus append any other email |
||
2393 | // given at the end of the list. |
||
2394 | $withoutpermissions_concerned_addresses = array(); |
||
2395 | $this->buildNotificationArrays($changes, $concerned_ids, $concerned_addresses); |
||
2396 | if ($more_addresses) { |
||
2397 | foreach ($more_addresses as $address) { |
||
2398 | if ($address['address'] && $address['address'] != '') { |
||
2399 | $res_username = user_get_result_set_from_email($address['address'], false); |
||
2400 | if ($res_username && (db_numrows($res_username) == 1)) { |
||
2401 | $u_id = db_result($res_username,0,'user_id'); |
||
2402 | if (!$address['check_permissions']) { |
||
2403 | $curr_user = UserManager::instance()->getUserById($u_id); |
||
2404 | if ($curr_user->isActive() || $curr_user->isRestricted()) { |
||
2405 | $withoutpermissions_concerned_addresses[user_getemail($u_id)] = true; |
||
2406 | } |
||
2407 | unset($concerned_ids[$u_id]); |
||
2408 | } else { |
||
2409 | $concerned_ids[$u_id] = true; |
||
2410 | } |
||
2411 | } else { |
||
2412 | if (!$address['check_permissions']) { |
||
2413 | $withoutpermissions_concerned_addresses[$address['address']] = true; |
||
2414 | unset($concerned_addresses[$address['address']]); |
||
2415 | } else { |
||
2416 | $concerned_addresses[$address['address']] = true; |
||
2417 | } |
||
2418 | } |
||
2419 | } |
||
2420 | } |
||
2421 | } |
||
2422 | //concerned_ids contains users for wich we have to check permissions |
||
2423 | //concerned_addresses contains emails for which there is no existing user. Permissions will be checked (Anonymous users) |
||
2424 | //withoutpermissions_concerned_addresses contains emails for which there is no permissions check |
||
2425 | |||
2426 | //Prepare e-mail |
||
2427 | list($host,) = explode(':',$GLOBALS['sys_default_domain']); |
||
2428 | |||
2429 | |||
2430 | //treat anonymous users |
||
2431 | $text_mail = $this->createMailForUsers(array($GLOBALS['UGROUP_ANONYMOUS']),$changes,$group_id,$group_artifact_id,$ok,$subject); |
||
2432 | $html_mail = $this->createHTMLMailForUsers(array($GLOBALS['UGROUP_ANONYMOUS']),$changes,$group_id,$group_artifact_id,$ok,$subject); |
||
2433 | |||
2434 | if ($ok) { |
||
2435 | $this->sendNotification(array_keys($concerned_addresses), $subject, $text_mail, $html_mail); |
||
2436 | } |
||
2437 | |||
2438 | //treat 'without permissions' emails |
||
2439 | if (count($withoutpermissions_concerned_addresses)) { |
||
2440 | $text_mail = $this->createMailForUsers(false,$changes,$group_id,$group_artifact_id,$ok,$subject); |
||
2441 | $html_mail = $this->createHTMLMailForUsers(false,$changes,$group_id,$group_artifact_id,$ok,$subject); |
||
2442 | |||
2443 | if ($ok) { |
||
2444 | $this->sendNotification(array_keys($withoutpermissions_concerned_addresses), $subject, $text_mail, $html_mail); |
||
2445 | } |
||
2446 | |||
2447 | } |
||
2448 | |||
2449 | //now group other registered users |
||
2450 | |||
2451 | //echo "<br>concerned_ids = ".implode(',',array_keys($concerned_ids)); |
||
2452 | |||
2453 | $this->groupNotificationList(array_keys($concerned_ids),$user_sets,$ugroup_sets); |
||
2454 | |||
2455 | //echo "<br>user_sets = "; print_r($user_sets); echo ", ugroup_sets = "; print_r($ugroup_sets); |
||
2456 | reset($ugroup_sets); |
||
2457 | while (list($x,$ugroups) = each($ugroup_sets)) { |
||
2458 | unset($arr_addresses); |
||
2459 | |||
2460 | $user_ids = $user_sets[$x]; |
||
2461 | //echo "<br>---> preparing mail $x for ";print_r($user_ids); |
||
2462 | $text_mail = $this->createMailForUsers($ugroups,$changes,$group_id,$group_artifact_id,$ok,$subject); |
||
2463 | $html_mail = $this->createHTMLMailForUsers($ugroups,$changes,$group_id,$group_artifact_id,$ok,$subject); |
||
2464 | if (!$ok) continue; //don't send the mail if nothing permitted for this user group |
||
2465 | |||
2466 | foreach ($user_ids as $user_id) { |
||
2467 | $arr_addresses[] = user_getemail($user_id); |
||
2468 | } |
||
2469 | |||
2470 | if ($arr_addresses) { |
||
2471 | $this->sendNotification($arr_addresses, $subject, $text_mail, $html_mail); |
||
2472 | } |
||
2473 | } |
||
2474 | } |
||
2475 | } |
||
2476 | |||
2477 | /** |
||
2478 | * Build notification list based on user preferences |
||
2479 | * |
||
2480 | * @param Array $addresses |
||
2481 | * @param String $subject |
||
2482 | * @param Codendi_Mail_Interface $text_mail |
||
2483 | * @param Codendi_Mail_Interface $html_mail |
||
2484 | */ |
||
2485 | function sendNotification($addresses, $subject, $text_mail, $html_mail) { |
||
2486 | $html_addresses = array(); |
||
2487 | $text_addresses = array(); |
||
2488 | |||
2489 | $mailMgr = new MailManager(); |
||
2490 | $mailPrefs = $mailMgr->getMailPreferencesByEmail($addresses); |
||
2491 | foreach ($mailPrefs['html'] as $user) { |
||
2492 | $html_addresses[] = $user->getEmail(); |
||
2493 | } |
||
2494 | foreach ($mailPrefs['text'] as $user) { |
||
2495 | $text_addresses[] = $user->getEmail(); |
||
2496 | } |
||
2497 | |||
2498 | $mail = null; |
||
2499 | if ($text_mail && count($text_addresses)) { |
||
2500 | $this->sendMail($text_mail, $subject, $text_addresses); |
||
2501 | } |
||
2502 | if ($html_mail && count($html_addresses)) { |
||
2503 | if ($text_mail) { |
||
2504 | $html_mail->setBodyText($text_mail->getBody()); |
||
2505 | } |
||
2506 | $this->sendMail($html_mail, $subject, $html_addresses); |
||
2507 | } |
||
2508 | } |
||
2509 | |||
2510 | /** |
||
2511 | * Finalize & send mail to peple |
||
2512 | * |
||
2513 | * @param Codendi_Mail_Interface $mail |
||
2514 | * @param String $subject |
||
2515 | * @param Array $to |
||
2516 | */ |
||
2517 | function sendMail(Codendi_Mail_Interface $mail, $subject, array $to) { |
||
2518 | $mail->addAdditionalHeader("X-Codendi-Project", $this->ArtifactType->getGroup()->getUnixName()); |
||
2519 | $mail->addAdditionalHeader("X-Codendi-Artifact", $this->ArtifactType->getItemName()); |
||
2520 | $mail->addAdditionalHeader("X-Codendi-Artifact-ID", $this->getID()); |
||
2521 | $mail->setFrom($GLOBALS['sys_noreply']); |
||
2522 | $mail->setTo(join(',', $to)); |
||
2523 | $mail->setSubject($subject); |
||
2524 | $mail->send(); |
||
2525 | } |
||
2526 | |||
2527 | /** for a certain set of users being part of the same ugroups |
||
2528 | * create the mail body containing only fields that they have the permission to read |
||
2529 | */ |
||
2530 | function createHTMLMailForUsers($ugroups,$changes,$group_id,$group_artifact_id,&$ok,&$subject) { |
||
2673 | |||
2674 | /** |
||
2675 | * @return string html call to action button to include in an html mail |
||
2676 | */ |
||
2677 | public function fetchHtmlAnswerButton($artifact_href) { |
||
2678 | return '<p align="right" class="cta"> |
||
2679 | <a href="'. $artifact_href .'" target="_blank">' . |
||
2680 | $GLOBALS['Language']->getText('tracker_include_artifact','mail_answer_now') . |
||
2681 | '</a> |
||
2682 | </p>'; |
||
2683 | } |
||
2684 | |||
2685 | /** |
||
2686 | * return a field for the given user. |
||
2687 | * |
||
2688 | * @protected |
||
2689 | **/ |
||
2690 | function _getFieldLabelAndValueForHTMLMail($group_id, $group_artifact_id, $field, $field_perm) { |
||
2691 | $html = false; |
||
2692 | $read_only = true; |
||
2693 | $field_name = $field->getName(); |
||
2694 | if ($field_perm === false || (isset($field_perm[$field_name]) && $field_perm[$field_name] && permission_can_read_field($field_perm[$field_name]))) { |
||
2695 | |||
2696 | // For multi select box, we need to retrieve all the values |
||
2697 | if ( $field->isMultiSelectBox() ) { |
||
2698 | $field_value = $field->getValues($this->getID()); |
||
2699 | } else { |
||
2700 | $field_value = $this->getValue($field->getName()); |
||
2701 | } |
||
2702 | |||
2703 | $field_html = new ArtifactFieldHtml($field); |
||
2704 | $field_html->disableJavascript(); |
||
2705 | $label = $field_html->labelDisplay(false,false,false); |
||
2706 | |||
2707 | if ($field->getName() == 'submitted_by') { |
||
2708 | $value = util_user_link(user_getname($field_value)); |
||
2709 | } else if ($field->getName() == 'open_date') { |
||
2710 | $value = format_date($GLOBALS['Language']->getText('system', 'datefmt'),$field_value); |
||
2711 | } else if ($field->getName() == 'last_update_date') { |
||
2712 | $value = format_date($GLOBALS['Language']->getText('system', 'datefmt'),$field_value); |
||
2713 | } else { |
||
2714 | $value = $field_html->display($this->ArtifactType->getID(), $field_value, false, false, $read_only, false, false, 0, false, 0, false, 0, false); |
||
2715 | $value = util_make_links($value, $group_id, $group_artifact_id); |
||
2716 | } |
||
2717 | $html = array('label' => $label, 'value' => $value); |
||
2718 | } |
||
2719 | return $html; |
||
2720 | } |
||
2721 | |||
2722 | /** for a certain set of users being part of the same ugroups |
||
2723 | * create the mail body containing only fields that they have the permission to read |
||
2724 | */ |
||
2725 | function createMailForUsers($ugroups,$changes,$group_id,$group_artifact_id,&$ok,&$subject) { |
||
2883 | |||
2884 | /** |
||
2885 | * Check whether $field_name is readable according to $field_perm |
||
2886 | * |
||
2887 | * All permissions are granted when $field_perm is equal to false. |
||
2888 | * $field_perm is equal to false when addresses are added in tracker admin to |
||
2889 | * "Global Email Notification with "check permission" unchecked. |
||
2890 | * |
||
2891 | * @param Array $field_perm ... |
||
2892 | * |
||
2893 | * @return Boolean |
||
2894 | */ |
||
2895 | public function hasFieldPermission($field_perm, $field_name) { |
||
2896 | $hasPerm = false; |
||
2897 | if ($field_perm === false) { |
||
2898 | $hasPerm = true; |
||
2899 | } else { |
||
2900 | if (isset($field_perm[$field_name]) && $field_perm[$field_name] && permission_can_read_field($field_perm[$field_name])) { |
||
2901 | $hasPerm = true; |
||
2902 | } |
||
2903 | } |
||
2904 | return $hasPerm; |
||
2905 | } |
||
2906 | |||
2907 | /** |
||
2908 | * Format the changes |
||
2909 | * |
||
2910 | * @param changes: array of changes |
||
2911 | * @param $field_perm an array with the permission associated to each field. false to no check perms |
||
2912 | * @param $visible_change only needed when using permissions. Returns true if there is any change |
||
2913 | * that the user has permission to see |
||
2914 | * |
||
2915 | * @return string |
||
2916 | */ |
||
2917 | function formatChanges($changes,$field_perm,&$visible_change) { |
||
2918 | |||
2919 | global $art_field_fact,$Language; |
||
2920 | $visible_change = false; |
||
2921 | $out_hdr = ''; |
||
2922 | $out = ''; |
||
2923 | $out_com = ''; |
||
2924 | $out_att = ''; |
||
2925 | reset($changes); |
||
2926 | $fmt = "%20s | %-25s | %s".$GLOBALS['sys_lf']; |
||
2927 | |||
2928 | |||
2929 | if ($this->hasFieldPermission($field_perm, 'assigned_to') || |
||
2930 | $this->hasFieldPermission($field_perm, 'multi_assigned_to') || |
||
2931 | (!isset($field_perm['assigned_to']) && !isset($field_perm['multi_assigned_to']))) { |
||
2932 | if (user_isloggedin()) { |
||
2933 | $user_id = user_getid(); |
||
2934 | $out_hdr = $Language->getText('tracker_include_artifact','changes_by').' '.user_getrealname($user_id).' <'.user_getemail($user_id).">". $GLOBALS['sys_lf'] .""; |
||
2935 | $out_hdr .= $Language->getText('tracker_import_utils','date').': '.format_date($GLOBALS['Language']->getText('system', 'datefmt'),time()).' ('.user_get_timezone().')'; |
||
2936 | } else { |
||
2937 | $out_hdr = $Language->getText('tracker_include_artifact','changes_by').' '.$Language->getText('tracker_include_artifact','anon_user').' '.$Language->getText('tracker_import_utils','date').': '.format_date($GLOBALS['Language']->getText('system', 'datefmt'),time()); |
||
2938 | } |
||
2939 | } |
||
2940 | //Process special cases first: follow-up comment |
||
2941 | if (array_key_exists('comment', $changes) && $changes['comment']) { |
||
2942 | $visible_change = true; |
||
2943 | $out_com = $GLOBALS['sys_lf'] . $GLOBALS['sys_lf'] ."--------------- ".$Language->getText('tracker_include_artifact','add_flup_comment')." ----------------". $GLOBALS['sys_lf'] .""; |
||
2944 | |||
2945 | if (isset($changes['comment']['type']) && $changes['comment']['type'] != $Language->getText('global','none') && $changes['comment']['type'] != '') { |
||
2946 | $out_com .= "[".$changes['comment']['type']."]".$GLOBALS['sys_lf']; |
||
2947 | } |
||
2948 | $out_com .= $this->formatFollowUp(null, $changes['comment']['format'], $changes['comment']['add'], self::OUTPUT_MAIL_TEXT); |
||
2949 | unset($changes['comment']); |
||
2950 | } |
||
2951 | |||
2952 | //Process special cases first: file attachment |
||
2953 | if (array_key_exists('attach', $changes) && $changes['attach']) { |
||
2954 | $visible_change = true; |
||
2955 | $out_att = "". $GLOBALS['sys_lf'] . $GLOBALS['sys_lf'] ."--------------- ".$Language->getText('tracker_include_artifact','add_attachment')." -----------------". $GLOBALS['sys_lf'] .""; |
||
2956 | $out_att .= sprintf($Language->getText('tracker_include_artifact','file_name')." %-30s ".$Language->getText('tracker_include_artifact','size').":%d KB". $GLOBALS['sys_lf'] ."",$changes['attach']['name'], |
||
2957 | intval($changes['attach']['size']/1024) ); |
||
2958 | $out_att .= $changes['attach']['description'] . $GLOBALS['sys_lf'] . $changes['attach']['href']; |
||
2959 | unset($changes['attach']); |
||
2960 | } |
||
2961 | |||
2962 | // All the rest of the fields now |
||
2963 | reset($changes); |
||
2964 | |||
2965 | while ( list($field_name,$h) = each($changes)) { |
||
2966 | // If both removed and added items are empty skip - Sanity check |
||
2967 | if (((isset($h['del']) && $h['del']) || (isset($h['add']) && $h['add'])) |
||
2968 | && $this->hasFieldPermission($field_perm, $field_name)) { |
||
2969 | |||
2970 | $visible_change = true; |
||
2971 | $label = $field_name; |
||
2972 | $field = $art_field_fact->getFieldFromName($field_name); |
||
2973 | if ( $field ) { |
||
2974 | $label = $field->getLabel(); |
||
2975 | if (isset($h['del'])) { |
||
2976 | $h['del'] = SimpleSanitizer::unsanitize(util_unconvert_htmlspecialchars($h['del'])); |
||
2977 | } |
||
2978 | if (isset($h['add'])) { |
||
2979 | $h['add'] = SimpleSanitizer::unsanitize(util_unconvert_htmlspecialchars($h['add'])); |
||
2980 | } |
||
2981 | } |
||
2982 | $out .= sprintf($fmt, SimpleSanitizer::unsanitize($label), isset($h['del'])?$h['del']:"",isset($h['add'])?$h['add']:""); |
||
2983 | } |
||
2984 | } // while |
||
2985 | |||
2986 | if ($out) { |
||
2987 | $out = $GLOBALS['sys_lf'] . $GLOBALS['sys_lf'] . sprintf($fmt,$Language->getText('tracker_include_artifact','what').' ',$Language->getText('tracker_include_artifact','removed'),$Language->getText('tracker_include_artifact','added')). |
||
2988 | "------------------------------------------------------------------". $GLOBALS['sys_lf'] . $out; |
||
2989 | } |
||
2990 | |||
2991 | return($out_hdr.$out.$out_com.$out_att); |
||
2992 | } |
||
2993 | |||
2994 | /** |
||
2995 | * Format the changes |
||
2996 | * |
||
2997 | * @param changes: array of changes |
||
2998 | * @param $field_perm an array with the permission associated to each field. false to no check perms |
||
2999 | * @param string $artifact_href The direct link to the artifact |
||
3000 | * @param $visible_change only needed when using permissions. Returns true if there is any change |
||
3001 | * that the user has permission to see |
||
3002 | * |
||
3003 | * @return string |
||
3004 | */ |
||
3005 | function formatChangesHTML($changes, $field_perm, $artifact_href, &$visible_change) { |
||
3147 | |||
3148 | |||
3149 | /** |
||
3150 | * Return the string to display the follow ups comments |
||
3151 | * |
||
3152 | * @param Integer group_id: the group id |
||
3153 | * @param Integer output By default set to OUTPUT_BROWSER, the output is displayed on browser |
||
3154 | * set to OUTPUT_MAIL_TEXT, the followups will be sent in mail |
||
3155 | * else is an export csv/DB |
||
3156 | * @return string the follow-up comments to display in HTML or in ascii mode |
||
3157 | */ |
||
3158 | function showFollowUpComments($group_id, $pv, $output = self::OUTPUT_BROWSER) { |
||
3370 | |||
3371 | /** |
||
3372 | * Display the list of CC addresses |
||
3373 | * |
||
3374 | * @param group_id: the group id |
||
3375 | * @param group_artifact_id: the artifact type ID |
||
3376 | * @param ascii: ascii mode |
||
3377 | * |
||
3378 | * @return void |
||
3379 | */ |
||
3380 | function showCCList ($group_id, $group_artifact_id, $ascii=false, $pv = 0) { |
||
3381 | $hp = Codendi_HTMLPurifier::instance(); |
||
3382 | global $Language; |
||
3383 | |||
3384 | // |
||
3385 | // format the CC list for this artifact |
||
3386 | // |
||
3387 | |||
3388 | $result = $this->getCCList(); |
||
3389 | $rows = db_numrows($result); |
||
3390 | $out = ''; |
||
3391 | |||
3392 | // Nobody in the CC list -> return now |
||
3393 | if ($rows <= 0) { |
||
3394 | if ($ascii) |
||
3395 | $out = $Language->getText('tracker_include_artifact','cc_empty').$GLOBALS['sys_lf']; |
||
3396 | else |
||
3397 | $out = '<H4>'.$Language->getText('tracker_include_artifact','cc_empty').'</H4>'; |
||
3398 | return $out; |
||
3399 | } |
||
3400 | |||
3401 | // Header first an determine what the print out format is |
||
3402 | // based on output type (Ascii, HTML) |
||
3403 | if ($ascii) { |
||
3404 | $out .= $Language->getText('tracker_include_artifact','cc_list').$GLOBALS['sys_lf'].str_repeat("*",strlen($Language->getText('tracker_include_artifact','cc_list'))).$GLOBALS['sys_lf'].$GLOBALS['sys_lf']; |
||
3405 | $fmt = "%-35s | %s".$GLOBALS['sys_lf']; |
||
3406 | $out .= sprintf($fmt, $Language->getText('tracker_include_artifact','cc_address'), $Language->getText('tracker_include_artifact','fill_cc_list_cmt')); |
||
3407 | $out .= "------------------------------------------------------------------". $GLOBALS['sys_lf']; |
||
3408 | } else { |
||
3409 | |||
3410 | $title_arr=array(); |
||
3411 | $title_arr[]=$Language->getText('tracker_include_artifact','cc_address'); |
||
3412 | $title_arr[]=$Language->getText('tracker_include_artifact','fill_cc_list_cmt'); |
||
3413 | $title_arr[]=$Language->getText('tracker_include_artifact','added_by'); |
||
3414 | $title_arr[]=$Language->getText('tracker_include_artifact','posted_on'); |
||
3415 | if ($pv == 0) { |
||
3416 | $title_arr[]=$Language->getText('tracker_include_canned','delete'); |
||
3417 | } |
||
3418 | $out .= html_build_list_table_top ($title_arr); |
||
3419 | |||
3420 | $fmt = "\n".'<TR class="%s"><td>%s</td><td>%s</td><td align="center">%s</td><td align="center">%s</td>'; |
||
3421 | if ($pv == 0) { |
||
3422 | $fmt .= '<td align="center">%s</td>'; |
||
3423 | } |
||
3424 | $fmt .= '</tr>'; |
||
3425 | } |
||
3426 | |||
3427 | // Loop through the cc and format them |
||
3428 | for ($i=0; $i < $rows; $i++) { |
||
3429 | |||
3430 | $email = db_result($result, $i, 'email'); |
||
3431 | $artifact_cc_id = db_result($result, $i, 'artifact_cc_id'); |
||
3432 | |||
3433 | // if the CC is a user point to its user page else build a mailto: URL |
||
3434 | $res_username = user_get_result_set_from_unix($email); |
||
3435 | if ($res_username && (db_numrows($res_username) == 1)) |
||
3436 | $href_cc = util_user_link($email); |
||
3437 | else |
||
3438 | $href_cc = '<a href="mailto:'.util_normalize_email($email).'">'.$email.'</a>'; |
||
3439 | |||
3440 | if ($ascii) { |
||
3441 | $out .= sprintf($fmt, $email, SimpleSanitizer::unsanitize(db_result($result, $i, 'comment'))); |
||
3442 | } else { |
||
3443 | |||
3444 | // show CC delete icon if one of the condition is met: |
||
3445 | // (a) current user is a group member |
||
3446 | // (b) the CC name is the current user |
||
3447 | // (c) the CC email address matches the one of the current user |
||
3448 | // (d) the current user is the person who added a gieven name in CC list |
||
3449 | if ( user_ismember($this->ArtifactType->getGroupID()) || |
||
3450 | (user_getname(user_getid()) == $email) || |
||
3451 | (user_getemail(user_getid()) == $email) || |
||
3452 | (user_getname(user_getid()) == db_result($result, $i, 'user_name') )) { |
||
3453 | $html_delete = '<a href="?func=delete_cc&group_id='.(int)$group_id.'&aid='.(int)$this->getID().'&atid='.(int)$group_artifact_id.'&artifact_cc_id='.(int)$artifact_cc_id.'" '. |
||
3454 | ' onClick="return confirm(\''.$Language->getText('tracker_include_artifact','delete_cc').'\')">'. |
||
3455 | '<IMG SRC="'.util_get_image_theme("ic/trash.png").'" HEIGHT="16" WIDTH="16" BORDER="0" ALT="'.$Language->getText('global','btn_delete').'"></A>'; |
||
3456 | } else { |
||
3457 | $html_delete = '-'; |
||
3458 | } |
||
3459 | |||
3460 | $out .= sprintf($fmt, |
||
3461 | util_get_alt_row_color($i), |
||
3462 | $href_cc, |
||
3463 | $hp->purify(SimpleSanitizer::unsanitize(db_result($result, $i, 'comment')), CODENDI_PURIFIER_BASIC, $this->ArtifactType->getGroupId()) , |
||
3464 | util_user_link(db_result($result, $i, 'user_name')), |
||
3465 | format_date($GLOBALS['Language']->getText('system', 'datefmt'),db_result($result, $i, 'date')), |
||
3466 | $html_delete); |
||
3467 | |||
3468 | } // for |
||
3469 | } |
||
3470 | |||
3471 | // final touch... |
||
3472 | $out .= ($ascii ? $GLOBALS['sys_lf'] : "</TABLE>"); |
||
3473 | |||
3474 | return($out); |
||
3475 | |||
3476 | } |
||
3477 | |||
3478 | /** |
||
3479 | * Display the artifact dependencies list |
||
3480 | * |
||
3481 | * @param group_id: the group id |
||
3482 | * @param group_artifact_id: the artifact type ID |
||
3483 | * @param ascii: ascii mode |
||
3484 | * |
||
3485 | * @return void |
||
3486 | */ |
||
3487 | function showDependencies ($group_id, $group_artifact_id, $ascii=false, $pv = 0) { |
||
3488 | $hp = Codendi_HTMLPurifier::instance(); |
||
3489 | global $Language; |
||
3490 | |||
3491 | // |
||
3492 | // format the dependencies list for this artifact |
||
3493 | // |
||
3494 | |||
3495 | $result=$this->getDependencies(); |
||
3496 | $rows=db_numrows($result); |
||
3497 | $out = ''; |
||
3498 | // Nobody in the dependencies list -> return now |
||
3499 | if ($rows <= 0) { |
||
3500 | if ($ascii) |
||
3501 | $out = $Language->getText('tracker_include_artifact','dep_list_empty').$GLOBALS['sys_lf']; |
||
3502 | else |
||
3503 | $out = '<H4>'.$Language->getText('tracker_include_artifact','dep_list_empty').'</H4>'; |
||
3504 | return $out; |
||
3505 | } |
||
3506 | |||
3507 | // Header first an determine what the print out format is |
||
3508 | // based on output type (Ascii, HTML) |
||
3509 | if ($ascii) { |
||
3510 | $out .= $Language->getText('tracker_include_artifact','dep_list').$GLOBALS['sys_lf'].str_repeat("*",strlen($Language->getText('tracker_include_artifact','dep_list'))). $GLOBALS['sys_lf'] . $GLOBALS['sys_lf']; |
||
3511 | $fmt = "%-15s | %s (%s)". $GLOBALS['sys_lf']; |
||
3512 | $out .= sprintf($fmt, |
||
3513 | $Language->getText('tracker_include_artifact','artifact'), |
||
3514 | $Language->getText('tracker_include_artifact','summary'), |
||
3515 | $Language->getText('global','status') |
||
3516 | ); |
||
3517 | $out .= "------------------------------------------------------------------". $GLOBALS['sys_lf']; |
||
3518 | } else { |
||
3519 | |||
3520 | $title_arr=array(); |
||
3521 | $title_arr[]=$Language->getText('tracker_include_artifact','artifact'); |
||
3522 | $title_arr[]=$Language->getText('tracker_include_artifact','summary'); |
||
3523 | $title_arr[]=$Language->getText('global','status'); |
||
3524 | $title_arr[]=$Language->getText('tracker_import_admin','tracker'); |
||
3525 | $title_arr[]=$Language->getText('tracker_include_artifact','group'); |
||
3526 | if ($pv == 0) { |
||
3527 | $title_arr[]=$Language->getText('tracker_include_canned','delete'); |
||
3528 | } |
||
3529 | $out .= html_build_list_table_top ($title_arr); |
||
3530 | |||
3531 | $fmt = "\n".'<TR class="%s"><td>%s</td><td>%s</td><td align="center">%s</td><td align="center">%s</td><td align="center">%s</td>'; |
||
3532 | if ($pv == 0) { |
||
3533 | $fmt .= '<td align="center">%s</td>'; |
||
3534 | } |
||
3535 | $fmt .= '</tr>'; |
||
3536 | } |
||
3537 | |||
3538 | // Loop through the denpendencies and format them |
||
3539 | for ($i=0; $i < $rows; $i++) { |
||
3540 | |||
3541 | $dependent_on_artifact_id = db_result($result, $i, 'is_dependent_on_artifact_id'); |
||
3542 | $summary = db_result($result, $i, 'summary'); |
||
3543 | $status = db_result($result, $i, 'status'); |
||
3544 | $tracker_label = db_result($result, $i, 'name'); |
||
3545 | $group_label = db_result($result, $i, 'group_name'); |
||
3546 | |||
3547 | if ($ascii) { |
||
3548 | $out .= sprintf($fmt, $dependent_on_artifact_id, util_unconvert_htmlspecialchars($summary), $status); |
||
3549 | } else { |
||
3550 | |||
3551 | if ( user_ismember($this->ArtifactType->getGroupID()) ) { |
||
3552 | $html_delete = '<a href="?func=delete_dependent&group_id='.(int)$group_id.'&aid='.(int)$this->getID().'&atid='.(int)$group_artifact_id.'&dependent_on_artifact_id='.(int)$dependent_on_artifact_id.'" '. |
||
3553 | ' onClick="return confirm(\''.$Language->getText('tracker_include_artifact','del_dep').'\')">'. |
||
3554 | '<IMG SRC="'.util_get_image_theme("ic/trash.png").'" HEIGHT="16" WIDTH="16" BORDER="0" ALT="'.$Language->getText('global','btn_delete').'"></A>'; |
||
3555 | } else { |
||
3556 | $html_delete = '-'; |
||
3557 | } |
||
3558 | |||
3559 | $out .= sprintf($fmt, |
||
3560 | util_get_alt_row_color($i), |
||
3561 | '<a href="/tracker/?func=gotoid&group_id='.(int)$group_id.'&aid='.(int)$dependent_on_artifact_id.'">'.(int)$dependent_on_artifact_id.'</a>', |
||
3562 | $hp->purify(util_unconvert_htmlspecialchars($summary), CODENDI_PURIFIER_CONVERT_HTML) , |
||
3563 | $hp->purify($status, CODENDI_PURIFIER_CONVERT_HTML) , |
||
3564 | $hp->purify(SimpleSanitizer::unsanitize($tracker_label), CODENDI_PURIFIER_CONVERT_HTML) , |
||
3565 | $hp->purify(util_unconvert_htmlspecialchars($group_label), CODENDI_PURIFIER_CONVERT_HTML) , |
||
3566 | $html_delete); |
||
3567 | |||
3568 | } // for |
||
3569 | } |
||
3570 | |||
3571 | // final touch... |
||
3572 | $out .= ($ascii ? $GLOBALS['sys_lf'] : "</TABLE>"); |
||
3573 | |||
3574 | return($out); |
||
3575 | |||
3576 | } |
||
3577 | |||
3578 | /** |
||
3579 | * Display the list of attached files |
||
3580 | * |
||
3581 | * @param group_id: the group id |
||
3582 | * @param group_artifact_id: the artifact type ID |
||
3583 | * @param ascii: ascii mode |
||
3584 | * |
||
3585 | * @return void |
||
3586 | */ |
||
3587 | function showAttachedFiles ($group_id,$group_artifact_id,$ascii=false, $pv = 0) { |
||
3588 | |||
3589 | global $Language; |
||
3590 | $hp = $this->getHtmlPurifier(); |
||
3591 | // |
||
3592 | // show the files attached to this artifact |
||
3593 | // |
||
3594 | |||
3595 | $result=$this->getAttachedFiles(); |
||
3596 | $rows=db_numrows($result); |
||
3597 | |||
3598 | // No file attached -> return now |
||
3599 | if ($rows <= 0) { |
||
3600 | if ($ascii) |
||
3601 | $out = $Language->getText('tracker_include_artifact','no_file_attached').$GLOBALS['sys_lf']; |
||
3602 | else |
||
3603 | $out = '<H4>'.$Language->getText('tracker_include_artifact','no_file_attached').'</H4>'; |
||
3604 | return $out; |
||
3605 | } |
||
3606 | |||
3607 | // Header first |
||
3608 | if ($ascii) { |
||
3609 | $out = $Language->getText('tracker_include_artifact','file_attachment').$GLOBALS['sys_lf'].str_repeat("*",strlen($Language->getText('tracker_include_artifact','file_attachment'))); |
||
3610 | } else { |
||
3611 | |||
3612 | $title_arr=array(); |
||
3613 | $title_arr[]=$Language->getText('tracker_include_artifact','name'); |
||
3614 | $title_arr[]=$Language->getText('tracker_include_artifact','desc'); |
||
3615 | $title_arr[]=$Language->getText('tracker_include_artifact','size_kb'); |
||
3616 | $title_arr[]=$Language->getText('global','by'); |
||
3617 | $title_arr[]=$Language->getText('tracker_include_artifact','posted_on'); |
||
3618 | if ($pv == 0) { |
||
3619 | $title_arr[]=$Language->getText('tracker_include_canned','delete'); |
||
3620 | } |
||
3621 | |||
3622 | $out = html_build_list_table_top ($title_arr); |
||
3623 | } |
||
3624 | |||
3625 | // Determine what the print out format is based on output type (Ascii, HTML) |
||
3626 | if ($ascii) { |
||
3627 | $fmt = $GLOBALS['sys_lf'] . $GLOBALS['sys_lf'] ."------------------------------------------------------------------". $GLOBALS['sys_lf']. |
||
3628 | $Language->getText('tracker_import_utils','date').": %s ".$Language->getText('tracker_include_artifact','name').": %s ".$Language->getText('tracker_include_artifact','size').": %dKB ".$Language->getText('global','by').": %s". $GLOBALS['sys_lf'] ."%s". $GLOBALS['sys_lf'] ."%s"; |
||
3629 | } else { |
||
3630 | $fmt = "". $GLOBALS['sys_lf'] . '<TR class="%s"><td>%s</td><td>%s</td><td align="center">%s</td><td align="center">%s</td><td align="center">%s</td>'; |
||
3631 | if ($pv == 0) { |
||
3632 | $fmt .= '<td align="center">%s</td>'; |
||
3633 | } |
||
3634 | $fmt .= '</tr>'; |
||
3635 | } |
||
3636 | |||
3637 | // Determine which protocl to use for embedded URL in ASCII format |
||
3638 | $server=get_server_url(); |
||
3639 | |||
3640 | // Loop throuh the attached files and format them |
||
3641 | for ($i=0; $i < $rows; $i++) { |
||
3642 | |||
3643 | $artifact_file_id = db_result($result, $i, 'id'); |
||
3644 | $href = "/tracker/download.php?artifact_id=".(int)$this->getID()."&id=".(int)$artifact_file_id; |
||
3645 | |||
3646 | if ($ascii) { |
||
3647 | $out .= sprintf($fmt, |
||
3648 | format_date($GLOBALS['Language']->getText('system', 'datefmt'),db_result($result, $i, 'adddate')), |
||
3649 | db_result($result, $i, 'filename') , |
||
3650 | intval(db_result($result, $i, 'filesize')/1024), |
||
3651 | db_result($result, $i, 'user_name'), |
||
3652 | SimpleSanitizer::unsanitize(db_result($result, $i, 'description')), |
||
3653 | $server.$href); |
||
3654 | } else { |
||
3655 | // show CC delete icon if one of the condition is met: |
||
3656 | // (a) current user is group member |
||
3657 | // (b) the current user is the person who added a gieven name in CC list |
||
3658 | if ( user_ismember($this->ArtifactType->getGroupID()) || |
||
3659 | (user_getname(user_getid()) == db_result($result, $i, 'user_name') )) { |
||
3660 | $html_delete = '<a href="?func=delete_file&group_id='.(int)$group_id."&atid=".(int)$group_artifact_id."&aid=".(int)$this->getID()."&id=".(int)db_result($result, $i, 'id').'" '. |
||
3661 | ' onClick="return confirm(\''.$Language->getText('tracker_include_artifact','delete_attachment').'\')">'. |
||
3662 | '<IMG SRC="'.util_get_image_theme("ic/trash.png").'" HEIGHT="16" WIDTH="16" BORDER="0" ALT="'.$Language->getText('global','btn_delete').'"></A>'; |
||
3663 | } else { |
||
3664 | $html_delete = '-'; |
||
3665 | } |
||
3666 | $out .= sprintf($fmt, |
||
3667 | util_get_alt_row_color($i), |
||
3668 | '<a href="'.$href.'">'. $hp->purify(db_result($result, $i, 'filename'), CODENDI_PURIFIER_CONVERT_HTML) .'</a>', |
||
3669 | $hp->purify(SimpleSanitizer::unsanitize(db_result($result, $i, 'description')), CODENDI_PURIFIER_BASIC, $group_id) , |
||
3670 | intval(db_result($result, $i, 'filesize')/1024), |
||
3671 | util_user_link(db_result($result, $i, 'user_name')), |
||
3672 | format_date($GLOBALS['Language']->getText('system', 'datefmt'),db_result($result, $i, 'adddate')), |
||
3673 | $html_delete); |
||
3674 | } |
||
3675 | } // for |
||
3676 | |||
3677 | // final touch... |
||
3678 | $out .= ($ascii ? "". $GLOBALS['sys_lf'] ."" : "</TABLE>"); |
||
3679 | |||
3680 | return($out); |
||
3681 | |||
3682 | } |
||
3683 | |||
3684 | /** Update the last_update_date field in the Artifact table to 'now' |
||
3685 | */ |
||
3686 | function update_last_update_date() { |
||
3687 | $sql="UPDATE artifact SET last_update_date=".time(). |
||
3688 | " WHERE artifact_id=". db_ei($this->getID()) ; |
||
3689 | |||
3690 | return db_query($sql); |
||
3691 | } |
||
3692 | |||
3693 | /** |
||
3694 | * Returns an instance of Codendi_HTMLPurifier |
||
3695 | * |
||
3696 | * @return Codendi_HTMLPurifier |
||
3697 | */ |
||
3698 | public function getHTMLPurifier() { |
||
3701 | |||
3702 | /** |
||
3703 | * Format the comment text to a given format according to parameters |
||
3704 | * |
||
3705 | * @param Integer $groupId Project id |
||
3706 | * @param Boolean $commentFormat $value's format |
||
3707 | * @param String $value Comment content |
||
3708 | * @param Boolean $output Output format |
||
3709 | * |
||
3710 | * @return String |
||
3711 | */ |
||
3712 | public function formatFollowUp($groupId, $commentFormat, $value, $output) { |
||
3713 | $commentText = ''; |
||
3714 | if ($output == self::OUTPUT_EXPORT) { |
||
3715 | return util_unconvert_htmlspecialchars($value); |
||
3716 | } else { |
||
3717 | $hp = $this->getHTMLPurifier(); |
||
3718 | if ($output == self::OUTPUT_MAIL_TEXT) { |
||
3719 | if ($commentFormat == self::FORMAT_HTML){ |
||
3720 | $commentText = $hp->purify(util_unconvert_htmlspecialchars($value), CODENDI_PURIFIER_STRIP_HTML); |
||
3721 | } else { |
||
3722 | $commentText = $value; |
||
3723 | } |
||
3724 | $commentText = util_unconvert_htmlspecialchars($commentText); |
||
3725 | } else { |
||
3726 | if ($commentFormat == self::FORMAT_HTML) { |
||
3727 | $level = CODENDI_PURIFIER_LIGHT; |
||
3728 | } else { |
||
3729 | $level = CODENDI_PURIFIER_BASIC; |
||
3730 | } |
||
3731 | $commentText = $hp->purify(util_unconvert_htmlspecialchars($value), $level, $groupId); |
||
3732 | } |
||
3733 | return $commentText; |
||
3734 | } |
||
3735 | } |
||
3736 | |||
3737 | } |
||
3738 | |||
3739 | ?> |
||
3740 |
This checks looks for assignemnts to variables using the
list(...)
function, where not all assigned variables are subsequently used.Consider the following code example.
Only the variables
$a
and$c
are used. There was no need to assign$b
.Instead, the list call could have been.