5 * Copyright 1999-2001, VA Linux Systems, Inc.
6 * Copyright 2009-2010, Roland Mas
7 * Copyright 2010-2011, Franck Villaume - Capgemini
8 * Copyright 2010-2011, Alain Peyrat - Alcatel-Lucent
9 * http://fusionforge.org
11 * This file is part of FusionForge.
13 * FusionForge is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published
15 * by the Free Software Foundation; either version 2 of the License,
16 * or (at your option) any later version.
18 * FusionForge is distributed in the hope that it will be useful, but
19 * WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21 * General Public License for more details.
23 * You should have received a copy of the GNU General Public License
24 * along with FusionForge; if not, write to the Free Software
25 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
29 require_once $gfcommon.'tracker/ArtifactTypes.class.php';
30 require_once $gfcommon.'tracker/ArtifactTypeFactory.class.php';
31 require_once $gfcommon.'forum/Forum.class.php';
32 require_once $gfcommon.'forum/ForumFactory.class.php';
33 require_once $gfcommon.'pm/ProjectGroup.class.php';
34 require_once $gfcommon.'pm/ProjectGroupFactory.class.php';
35 require_once $gfcommon.'include/Role.class.php';
36 require_once $gfcommon.'frs/FRSPackage.class.php';
37 require_once $gfcommon.'docman/DocumentGroup.class.php';
38 require_once $gfcommon.'docman/DocumentGroupFactory.class.php';
39 require_once $gfcommon.'mail/MailingList.class.php';
40 require_once $gfcommon.'mail/MailingListFactory.class.php';
41 require_once $gfcommon.'survey/SurveyFactory.class.php';
42 require_once $gfcommon.'survey/SurveyQuestionFactory.class.php';
43 require_once $gfcommon.'include/gettext.php';
44 require_once $gfcommon.'include/GroupJoinRequest.class.php';
49 * group_get_object() - Get the group object.
51 * group_get_object() is useful so you can pool group objects/save database queries
52 * You should always use this instead of instantiating the object directly.
54 * You can now optionally pass in a db result handle. If you do, it re-uses that query
55 * to instantiate the objects.
57 * IMPORTANT! That db result must contain all fields
58 * from groups table or you will have problems
61 * @param int Result set handle ("SELECT * FROM groups WHERE group_id=xx")
62 * @return object a group object or false on failure
64 function &group_get_object($group_id, $res = false) {
65 //create a common set of group objects
66 //saves a little wear on the database
68 //automatically checks group_type and
69 //returns appropriate object
72 if (!isset($GROUP_OBJ["_".$group_id."_"])) {
74 //the db result handle was passed in
76 $res = db_query_params('SELECT * FROM groups WHERE group_id=$1', array($group_id)) ;
78 if (!$res || db_numrows($res) < 1) {
79 $GROUP_OBJ["_".$group_id."_"]=false;
82 check group type and set up object
84 if (db_result($res,0,'type_id') == 1) {
86 $GROUP_OBJ["_".$group_id."_"] = new Group($group_id, $res);
89 $GROUP_OBJ["_".$group_id."_"] = false;
93 return $GROUP_OBJ["_".$group_id."_"];
96 function &group_get_objects($id_arr) {
99 // Note: if we don't do this, the result may be corrupted
103 foreach ($id_arr as $id) {
105 // See if this ID already has been fetched in the cache
107 if (!isset($GROUP_OBJ["_".$id."_"])) {
111 if (count($fetch) > 0) {
112 $res=db_query_params('SELECT * FROM groups WHERE group_id = ANY ($1)',
113 array(db_int_array_to_any_clause($fetch)));
114 while ($arr = db_fetch_array($res)) {
115 $GROUP_OBJ["_".$arr['group_id']."_"] = new Group($arr['group_id'],$arr);
118 foreach ($id_arr as $id) {
119 $return[] =& $GROUP_OBJ["_".$id."_"];
124 function &group_get_active_projects() {
125 $res = db_query_params('SELECT group_id FROM groups WHERE status=$1',
127 return group_get_objects(util_result_column_to_array($res,0));
130 function &group_get_template_projects() {
131 $res=db_query_params ('SELECT group_id FROM groups WHERE is_template=1 AND status != $1',
133 return group_get_objects (util_result_column_to_array($res,0)) ;
136 function &group_get_object_by_name($groupname) {
137 $res = db_query_params('SELECT * FROM groups WHERE unix_group_name=$1', array($groupname));
138 return group_get_object(db_result($res, 0, 'group_id'), $res);
141 function &group_get_objects_by_name($groupname_arr) {
142 $res = db_query_params('SELECT group_id FROM groups WHERE unix_group_name = ANY ($1)',
143 array(db_string_array_to_any_clause($groupname_arr)));
144 $arr =& util_result_column_to_array($res,0);
145 return group_get_objects($arr);
148 function &group_get_object_by_publicname($groupname) {
149 $res = db_query_params('SELECT * FROM groups WHERE lower(group_name) LIKE $1',
150 array(htmlspecialchars(strtolower($groupname))));
151 return group_get_object(db_result($res, 0, 'group_id'), $res);
154 class Group extends Error {
156 * Associative array of data from db.
158 * @var array $data_array.
163 * array of User objects.
165 * @var array $membersArr.
170 * Whether the use is an admin/super user of this project.
172 * @var bool $is_admin.
177 * Artifact types result handle.
179 * @var int $types_res.
184 * Associative array of data for plugins.
186 * @var array $plugins_data.
192 * Associative array of data for the group menu.
194 * @var array $menu_data.
199 * Group - Group object constructor - use group_get_object() to instantiate.
201 * @param int Required - group_id of the group you want to instantiate.
202 * @param int Database result from select query OR associative array of all columns.
203 * @return boolean success or not
205 function Group($id = false, $res = false) {
208 //setting up an empty object
209 //probably going to call create()
213 if (!$this->fetchData($id)) {
218 // Assoc array was passed in
220 if (is_array($res)) {
221 $this->data_array =& $res;
223 if (db_numrows($res) < 1) {
224 //function in class we extended
225 $this->setError(_('Group Not Found'));
226 $this->data_array=array();
229 //set up an associative array for use by other functions
230 $this->data_array = db_fetch_array_by_row($res, 0);
238 * fetchData - May need to refresh database fields if an update occurred.
240 * @param int The group_id.
241 * @return boolean success or not
243 function fetchData($group_id) {
244 $res = db_query_params ('SELECT * FROM groups WHERE group_id=$1',
246 if (!$res || db_numrows($res) < 1) {
247 $this->setError(sprintf(_('fetchData():: %s'),db_error()));
250 $this->data_array = db_fetch_array($res);
255 * create - Create new group.
257 * This method should be called on empty Group object.
259 * @param object The User object.
260 * @param string The full name of the user.
261 * @param string The Unix name of the user.
262 * @param string The new group description.
263 * @param string The purpose of the group.
264 * @param boolean Whether to send an email or not
265 * @param int The id of the project this new project is based on
266 * @return boolean success or not
268 function create(&$user, $group_name, $unix_name, $description, $purpose, $unix_box = 'shell1',
269 $scm_box = 'cvs1', $is_public = 1, $send_mail = true, $built_from_template = 0) {
270 // $user is ignored - anyone can create pending group
273 if ($this->getID()!=0) {
274 $this->setError(_('Group::create: Group object already exists'));
276 } else if (!$this->validateGroupName($group_name)) {
278 } else if (!account_groupnamevalid($unix_name)) {
279 $this->setError(_('Invalid Unix name'));
281 } else if (!$SYS->sysUseUnixName($unix_name)) {
282 $this->setError(_('Unix name already taken'));
284 } else if (db_numrows(db_query_params('SELECT group_id FROM groups WHERE unix_group_name=$1',
285 array($unix_name))) > 0) {
286 $this->setError(_('Unix name already taken'));
288 } else if (strlen($purpose)<10) {
289 $this->setError(_('Please describe your Registration Purpose in a more comprehensive manner'));
291 } else if (strlen($purpose)>1500) {
292 $this->setError(_('The Registration Purpose text is too long. Please make it smaller than 1500 bytes.'));
294 } else if (strlen($description)<10) {
295 $this->setError(_('Describe in a more comprehensive manner your project.'));
297 } else if (strlen($description)>255) {
298 $this->setError(_('Your project description is too long. Please make it smaller than 256 bytes.'));
303 $res = db_query_params('
320 VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14)',
321 array (htmlspecialchars ($group_name),
324 htmlspecialchars($description),
325 $unix_name.".".forge_get_config('web_host'),
326 $unix_name.".".forge_get_config('web_host'),
330 htmlspecialchars($purpose),
333 md5(util_randbytes()),
334 $built_from_template));
335 if (!$res || db_affected_rows($res) < 1) {
336 $this->setError(sprintf(_('ERROR: Could not create group: %s'),db_error()));
341 $id = db_insertid($res, 'groups', 'group_id');
343 $this->setError(sprintf(_('ERROR: Could not get group id: %s'),db_error()));
348 if (!$this->fetchData($id)) {
354 $gjr = new GroupJoinRequest($this);
355 $gjr->create($user->getID(),
356 'Fake GroupJoinRequest to store the creator of a project',
360 // Now, make the user an admin
362 $res=db_query_params('INSERT INTO user_group (user_id, group_id, admin_flags,
363 cvs_flags, artifact_flags, forum_flags, role_id)
364 VALUES ($1, $2, $3, $4, $5, $6, $7)',
365 array($user->getID(),
372 if (!$res || db_affected_rows($res) < 1) {
373 $this->setError(sprintf(_('ERROR: Could not add admin to newly created group: %s'),db_error()));
379 $hook_params = array();
380 $hook_params['group'] = $this;
381 $hook_params['group_id'] = $this->getID();
382 $hook_params['group_name'] = $group_name;
383 $hook_params['unix_group_name'] = $unix_name;
384 plugin_hook("group_create", $hook_params);
388 $this->sendNewProjectNotificationEmail();
396 * updateAdmin - Update core properties of group object.
398 * This function require site admin privilege.
400 * @param object User requesting operation (for access control).
401 * @param boolean Whether group is publicly accessible (0/1).
402 * @param int Group type (1-project, 2-foundry).
403 * @param string Machine on which group's home directory located.
404 * @param string Domain which serves group's WWW.
408 function updateAdmin(&$user, $is_public, $type_id, $unix_box, $http_domain) {
409 $perm =& $this->getPermission();
411 if (!$perm || !is_object($perm)) {
412 $this->setError(_('Could not get permission.'));
416 if (!$perm->isSuperUser()) {
417 $this->setError(_('Permission denied.'));
423 $res = db_query_params('
425 SET is_public=$1, type_id=$2,
426 unix_box=$3, http_domain=$4
434 if (!$res || db_affected_rows($res) < 1) {
435 $this->setError(_('ERROR: DB: Could not change group properties: %s'),db_error());
440 // Log the audit trail
441 if ($is_public != $this->isPublic()) {
442 $this->addHistory('is_public', $this->isPublic());
444 if ($type_id != $this->data_array['type_id']) {
445 $this->addHistory('type_id', $this->data_array['type_id']);
447 if ($unix_box != $this->data_array['unix_box']) {
448 $this->addHistory('unix_box', $this->data_array['unix_box']);
450 if ($http_domain != $this->data_array['http_domain']) {
451 $this->addHistory('http_domain', $this->data_array['http_domain']);
454 if (!$this->fetchData($this->getID())) {
463 * update - Update number of common properties.
465 * Unlike updateAdmin(), this function accessible to project admin.
467 * @param object User requesting operation (for access control).
468 * @param boolean Whether group is publicly accessible (0/1).
469 * @param string Project's license (string ident).
470 * @param int Group type (1-project, 2-foundry).
471 * @param string Machine on which group's home directory located.
472 * @param string Domain which serves group's WWW.
473 * @return int status.
476 function update(&$user, $group_name, $homepage, $short_description, $use_mail, $use_survey, $use_forum,
477 $use_pm, $use_pm_depend_box, $use_scm, $use_news, $use_docman,
478 $new_doc_address, $send_all_docs, $logo_image_id,
479 $use_ftp, $use_tracker, $use_frs, $use_stats, $tags, $is_public) {
481 $perm =& $this->getPermission();
483 if (!$perm || !is_object($perm)) {
484 $this->setError(_('Could not get permission.'));
488 if (!$perm->isAdmin()) {
489 $this->setError(_('Permission denied.'));
493 // Validate some values
494 if ($this->getPublicName() != $group_name) {
495 if (!$this->validateGroupName($group_name)) {
500 if ($new_doc_address) {
501 $invalid_mails = validate_emails($new_doc_address);
502 if (count($invalid_mails) > 0) {
503 $this->setError(sprintf(ngettext('New Doc Address Appeared Invalid: %s', 'New Doc Addresses Appeared Invalid: %s', count($invalid_mails)),implode(',',$invalid_mails)));
508 // in the database, these all default to '1',
509 // so we have to explicity set 0
522 if (!$use_pm_depend_box) {
523 $use_pm_depend_box = 0;
546 if (!$send_all_docs) {
550 $homepage = ltrim($homepage);
552 $homepage = util_make_url('/projects/' . $this->getUnixName() . '/');
555 if (strlen(htmlspecialchars($short_description))>255) {
556 $this->setError(_('Error updating project information: Maximum length for Project Description is 255 chars.'));
562 //XXX not yet actived logo_image_id='$logo_image_id',
563 $res = db_query_params('UPDATE groups
566 short_description=$3,
571 use_pm_depend_box=$8,
582 array(htmlspecialchars($group_name),
584 htmlspecialchars($short_description),
602 $this->setError(sprintf(_('Error updating project information: %s'), db_error()));
607 if (!$this->setUseDocman($use_docman)) {
608 $this->setError(sprintf(_('Error updating project information: use_docman %s'), db_error()));
613 if ($this->setTags($tags) === false) {
618 $hook_params = array();
619 $hook_params['group'] = $this;
620 $hook_params['group_id'] = $this->getID();
621 $hook_params['group_homepage'] = $homepage;
622 $hook_params['group_name'] = htmlspecialchars($group_name);
623 $hook_params['group_description'] = htmlspecialchars($short_description);
624 $hook_params['group_ispublic'] = $is_public;
625 if (!plugin_hook("group_update", $hook_params)) {
626 if (!$this->isError()) {
627 $this->setError(_('Error updating project information in plugin_hook group_update'));
633 // Log the audit trail
634 $this->addHistory('Changed Public Info', '');
636 if (!$this->fetchData($this->getID())) {
645 * getID - Simply return the group_id for this object.
647 * @return int group_id.
650 return $this->data_array['group_id'];
654 * getType() - Foundry, project, etc.
656 * @return int The type flag from the database.
659 return $this->data_array['type_id'];
664 * getStatus - the status code.
666 * Statuses char include I,H,A,D.
668 function getStatus() {
669 return $this->data_array['status'];
673 * setStatus - set the status code.
675 * Statuses include I,H,A,D.
677 * @param object User requesting operation (for access control).
678 * @param string Status value.
679 * @return boolean success.
682 function setStatus(&$user, $status) {
685 if (!forge_check_global_perm('approve_projects')) {
686 $this->setPermissionDeniedError();
690 // Projects in 'A' status can only go to 'H' or 'D'
691 // Projects in 'D' status can only go to 'A'
692 // Projects in 'P' status can only go to 'A' OR 'D'
693 // Projects in 'I' status can only go to 'P'
694 // Projects in 'H' status can only go to 'A' OR 'D'
695 $allowed_status_changes = array(
696 'AH'=>1,'AD'=>1,'DA'=>1,'PA'=>1,'PD'=>1,
697 'IP'=>1,'HA'=>1,'HD'=>1
700 // Check that status transition is valid
701 if ($this->getStatus() != $status
702 && !$allowed_status_changes[$this->getStatus().$status]) {
703 $this->setError(_('Invalid Status Change'));
709 $res = db_query_params('UPDATE groups
711 WHERE group_id=$2', array($status, $this->getID()));
713 if (!$res || db_affected_rows($res) < 1) {
714 $this->setError(sprintf(_('ERROR: DB: Could not change group status: %s'),db_error()));
720 // Activate system group, if not yet
721 if (!$SYS->sysCheckGroup($this->getID())) {
722 if (!$SYS->sysCreateGroup($this->getID())) {
723 $this->setError($SYS->getErrorMessage());
728 if (!$this->activateUsers()) {
733 /* Otherwise, the group is not active, and make sure that
734 System group is not active either */
735 } else if ($SYS->sysCheckGroup($this->getID())) {
736 if (!$SYS->sysRemoveGroup($this->getID())) {
737 $this->setError($SYS->getErrorMessage());
743 $hook_params = array();
744 $hook_params['group'] = $this;
745 $hook_params['group_id'] = $this->getID();
746 $hook_params['status'] = $status;
747 plugin_hook("group_setstatus", $hook_params);
751 // Log the audit trail
752 if ($status != $this->getStatus()) {
753 $this->addHistory('Status', $this->getStatus());
756 $this->data_array['status'] = $status;
761 * isProject - Simple boolean test to see if it's a project or not.
763 * @return boolean is_project.
765 function isProject() {
766 if ($this->getType()==1) {
774 * isPublic - Simply returns the is_public flag from the database.
776 * @return boolean is_public.
778 function isPublic() {
779 return $this->data_array['is_public'];
783 * isActive - Database field status of 'A' returns true.
785 * @return boolean is_active.
787 function isActive() {
788 if ($this->getStatus()=='A') {
796 * isTemplate - Simply returns the is_template flag from the database.
798 * @return boolean is_template.
800 function isTemplate() {
801 return $this->data_array['is_template'];
805 * setAsTemplate - Set the template status of a project
807 * @param boolean is_template.
809 function setAsTemplate($booleanparam) {
811 $booleanparam = $booleanparam ? 1 : 0;
812 $res = db_query_params('UPDATE groups SET is_template=$1 WHERE group_id=$2',
813 array($booleanparam, $this->getID()));
815 $this->data_array['is_template']=$booleanparam;
825 * getTemplateProject - Return the project template this project is built from
827 * @return object The template project
829 function getTemplateProject() {
830 return group_get_object($this->data_array['built_from_template']);
834 * getUnixName - the unix_name
836 * @return string unix_name.
838 function getUnixName() {
839 return strtolower($this->data_array['unix_group_name']);
843 * getPublicName - the full-length public name.
845 * @return string The group_name.
847 function getPublicName() {
848 return $this->data_array['group_name'];
852 * getRegisterPurpose - the text description of the purpose of this project.
854 * @return string The description.
856 function getRegisterPurpose() {
857 return $this->data_array['register_purpose'];
861 * getDescription - the text description of this project.
863 * @return string The description.
865 function getDescription() {
866 return $this->data_array['short_description'];
870 * getStartDate - the unix time this project was registered.
872 * @return int (unix time) of registration.
874 function getStartDate() {
875 return $this->data_array['register_time'];
879 * getLogoImageID - the id of the logo in the database for this project.
881 * @return int The ID of logo image in db_images table (or 100 if none).
883 function getLogoImageID() {
884 return $this->data_array['logo_image_id'];
888 * getUnixBox - the hostname of the unix box where this project is located.
890 * @return string The name of the unix machine for the group.
892 function getUnixBox() {
893 return $this->data_array['unix_box'];
897 * getSCMBox - the hostname of the scm box where this project is located.
899 * @return string The name of the unix machine for the group.
901 function getSCMBox() {
902 return $this->data_array['scm_box'];
905 * setSCMBox - the hostname of the scm box where this project is located.
907 * @param string The name of the new SCM_BOX
909 function setSCMBox($scm_box) {
911 if ($scm_box == $this->data_array['scm_box']) {
916 $res = db_query_params('UPDATE groups SET scm_box=$1 WHERE group_id=$2', array($scm_box, $this->getID ()));
918 $this->addHistory('scm_box', $this->data_array['scm_box']);
919 $this->data_array['scm_box'] = $scm_box;
924 $this->setError(_("Couldn't insert SCM_BOX to database"));
928 $this->setError(_("SCM Box can't be empty"));
934 * getDomain - the hostname.domain where their web page is located.
936 * @return string The name of the group [web] domain.
938 function getDomain() {
939 return $this->data_array['http_domain'];
943 * getRegistrationPurpose - the text description of the purpose of this project.
945 * @return string The application for project hosting.
947 function getRegistrationPurpose() {
948 return $this->data_array['register_purpose'];
953 * getAdmins() - Get array of Admin user objects.
955 * @return array Array of User objects.
957 function &getAdmins() {
958 $roles = RBACEngine::getInstance()->getRolesByAllowedAction ('project_admin', $this->getID());
962 foreach ($roles as $role) {
963 if (! ($role instanceof RoleExplicit)) {
966 if ($role->getHomeProject() == NULL
967 || $role->getHomeProject()->getID() != $this->getID()) {
971 foreach ($role->getUsers() as $u) {
972 $user_ids[] = $u->getID();
975 return user_get_objects(array_unique($user_ids));
979 Common Group preferences for tools
983 * enableAnonSCM - whether or not this group has opted to enable Anonymous SCM.
985 * @return boolean enable_scm.
987 function enableAnonSCM() {
989 $r = RoleAnonymous::getInstance();
990 return $r->hasPermission('scm', $this->getID(), 'read');
992 if ($this->isPublic() && $this->usesSCM()) {
993 return $this->data_array['enable_anonscm'];
1000 function SetUsesAnonSCM($booleanparam) {
1002 $booleanparam = $booleanparam ? 1 : 0;
1004 $r = RoleAnonymous::getInstance();
1005 $r->setSetting('scm', $this->getID(), $booleanparam);
1008 $res = db_query_params('UPDATE groups SET enable_anonscm=$1 WHERE group_id=$2',
1009 array($booleanparam, $this->getID()));
1011 $this->data_array['enable_anonscm'] = $booleanparam;
1021 * enablePserver - whether or not this group has opted to enable Pserver.
1023 * @return boolean enable_pserver.
1025 function enablePserver() {
1026 if ($this->usesSCM()) {
1027 return $this->data_array['enable_pserver'];
1033 function SetUsesPserver($booleanparam) {
1035 $booleanparam = $booleanparam ? 1 : 0;
1036 $res = db_query_params('UPDATE groups SET enable_pserver=$1 WHERE group_id=$2',
1037 array($booleanparam, $this->getID()));
1039 $this->data_array['enable_pserver'] = $booleanparam;
1048 * usesSCM - whether or not this group has opted to use SCM.
1050 * @return boolean uses_scm.
1052 function usesSCM() {
1053 if (forge_get_config('use_scm')) {
1054 return $this->data_array['use_scm'];
1061 * setUseSCM - Set the SCM usage
1063 * @param boolean enabled/disabled
1065 function setUseSCM($booleanparam) {
1067 $booleanparam = $booleanparam ? 1 : 0 ;
1068 $res = db_query_params('UPDATE groups SET use_scm=$1 WHERE group_id=$2',
1069 array($booleanparam, $this->getID()));
1071 $this->data_array['use_scm']=$booleanparam;
1081 * usesMail - whether or not this group has opted to use mailing lists.
1083 * @return boolean uses_mail.
1085 function usesMail() {
1086 if (forge_get_config('use_mail')) {
1087 return $this->data_array['use_mail'];
1094 * setUseMail - Set the mailing-list usage
1096 * @param boolean enabled/disabled
1098 function setUseMail($booleanparam) {
1100 $booleanparam = $booleanparam ? 1 : 0 ;
1101 $res = db_query_params('UPDATE groups SET use_mail=$1 WHERE group_id=$2',
1102 array($booleanparam, $this->getID()));
1104 $this->data_array['use_mail']=$booleanparam;
1114 * usesNews - whether or not this group has opted to use news.
1116 * @return boolean uses_news.
1118 function usesNews() {
1119 if (forge_get_config('use_news')) {
1120 return $this->data_array['use_news'];
1127 * usesForum - whether or not this group has opted to use discussion forums.
1129 * @return boolean uses_forum.
1131 function usesForum() {
1132 if (forge_get_config('use_forum')) {
1133 return $this->data_array['use_forum'];
1140 * setUseForum - Set the forum usage
1142 * @param boolean enabled/disabled
1144 function setUseForum($booleanparam) {
1146 $booleanparam = $booleanparam ? 1 : 0;
1147 $res = db_query_params('UPDATE groups SET use_forum=$1 WHERE group_id=$2',
1148 array($booleanparam, $this->getID()));
1150 $this->data_array['use_forum']=$booleanparam;
1160 * usesStats - whether or not this group has opted to use stats.
1162 * @return boolean uses_stats.
1164 function usesStats() {
1165 return $this->data_array['use_stats'];
1169 * usesFRS - whether or not this group has opted to use file release system.
1171 * @return boolean uses_frs.
1173 function usesFRS() {
1174 if (forge_get_config('use_frs')) {
1175 return $this->data_array['use_frs'];
1182 * setUseFRS - Set the FRS usage
1184 * @param boolean enabled/disabled
1186 function setUseFRS($booleanparam) {
1188 $booleanparam = $booleanparam ? 1 : 0;
1189 $res = db_query_params('UPDATE groups SET use_frs=$1 WHERE group_id=$2',
1190 array ($booleanparam, $this->getID()));
1192 $this->data_array['use_frs']=$booleanparam;
1202 * usesTracker - whether or not this group has opted to use tracker.
1204 * @return boolean uses_tracker.
1206 function usesTracker() {
1207 if (forge_get_config('use_tracker')) {
1208 return $this->data_array['use_tracker'];
1215 * setUseTracker - Set the tracker usage
1217 * @param boolean enabled/disabled
1219 function setUseTracker ($booleanparam) {
1221 $booleanparam = $booleanparam ? 1 : 0 ;
1222 $res = db_query_params ('UPDATE groups SET use_tracker=$1 WHERE group_id=$2',
1223 array ($booleanparam, $this->getID()));
1225 $this->data_array['use_tracker']=$booleanparam;
1235 * useCreateOnline - whether or not this group has opted to use create online documents option.
1237 * @return boolean use_docman_create_online.
1239 function useCreateOnline() {
1240 if (forge_get_config('use_docman')) {
1241 return $this->data_array['use_docman_create_online'];
1248 * usesDocman - whether or not this group has opted to use docman.
1250 * @return boolean use_docman.
1252 function usesDocman() {
1253 if (forge_get_config('use_docman')) {
1254 return $this->data_array['use_docman'];
1261 * setUseDocman - Set the docman usage
1263 * @param boolean enabled/disabled
1265 function setUseDocman($booleanparam) {
1267 $booleanparam = $booleanparam ? 1 : 0;
1268 $res = db_query_params('UPDATE groups SET use_docman = $1 WHERE group_id = $2',
1269 array($booleanparam, $this->getID()));
1271 // check if / doc_group exists, if not create it
1272 $trashdir = db_query_params('select groupname from doc_groups where groupname = $1 and group_id = $2',
1273 array('.trash', $this->getID()));
1274 if ($trashdir && db_numrows($trashdir) == 0) {
1275 $resinsert = db_query_params('insert into doc_groups (groupname, group_id, stateid) values ($1, $2, $3)',
1276 array('.trash', $this->getID(), '2'));
1282 $this->data_array['use_docman'] = $booleanparam;
1292 * useDocmanSearch - whether or not this group has opted to use docman search engine.
1294 * @return boolean use_docman_search.
1296 function useDocmanSearch() {
1297 if (forge_get_config('use_docman')) {
1298 return $this->data_array['use_docman_search'];
1305 * useWebdav - whether or not this group has opted to use webdav interface.
1307 * @return boolean use_docman_search.
1309 function useWebdav() {
1310 if (forge_get_config('use_webdav')) {
1311 return $this->data_array['use_webdav'];
1318 * usesFTP - whether or not this group has opted to use FTP.
1320 * @return boolean uses_ftp.
1322 function usesFTP() {
1323 if (forge_get_config('use_ftp')) {
1324 return $this->data_array['use_ftp'];
1331 * usesSurvey - whether or not this group has opted to use surveys.
1333 * @return boolean uses_survey.
1335 function usesSurvey() {
1336 if (forge_get_config('use_survey')) {
1337 return $this->data_array['use_survey'];
1344 * usesPM - whether or not this group has opted to Project Manager.
1346 * @return boolean uses_projman.
1349 if (forge_get_config('use_pm')) {
1350 return $this->data_array['use_pm'];
1357 * setUsePM - Set the PM usage
1359 * @param boolean enabled/disabled
1361 function setUsePM($booleanparam) {
1363 $booleanparam = $booleanparam ? 1 : 0;
1364 $res = db_query_params('UPDATE groups SET use_pm=$1 WHERE group_id=$2',
1365 array($booleanparam, $this->getID()));
1367 $this->data_array['use_pm']=$booleanparam;
1377 * getPlugins - get a list of all available group plugins
1379 * @return array array containing plugin_id => plugin_name
1381 function getPlugins() {
1382 if (!isset($this->plugins_data)) {
1383 $this->plugins_data = array();
1384 $res = db_query_params('SELECT group_plugin.plugin_id, plugins.plugin_name
1385 FROM group_plugin, plugins
1386 WHERE group_plugin.group_id=$1
1387 AND group_plugin.plugin_id=plugins.plugin_id', array($this->getID()));
1388 $rows = db_numrows($res);
1390 for ($i=0; $i<$rows; $i++) {
1391 $plugin_id = db_result($res, $i, 'plugin_id');
1392 $this->plugins_data[$plugin_id] = db_result($res, $i, 'plugin_name');
1395 return $this->plugins_data;
1399 * usesPlugin - returns true if the group uses a particular plugin
1401 * @param string name of the plugin
1402 * @return boolean whether plugin is being used or not
1404 function usesPlugin($pluginname) {
1405 $plugins_data = $this->getPlugins();
1406 foreach ($plugins_data as $p_id => $p_name) {
1407 if ($p_name == $pluginname) {
1415 * added for Codendi compatibility
1416 * usesServices - returns true if the group uses a particular plugin or feature
1418 * @param string name of the plugin
1419 * @return boolean whether plugin is being used or not
1421 function usesService($feature) {
1422 $plugins_data = $this->getPlugins();
1423 $pm = plugin_manager_get_object();
1424 foreach ($plugins_data as $p_id => $p_name) {
1425 if ($p_name == $feature) {
1428 if ($pm->getPluginByName($p_name)->provide($feature)) {
1436 * setPluginUse - enables/disables plugins for the group
1438 * @param string name of the plugin
1439 * @param boolean the new state
1440 * @return string database result
1442 function setPluginUse($pluginname, $val=true) {
1443 if ($val == $this->usesPlugin($pluginname)) {
1444 // State is already good, returning
1447 $res = db_query_params('SELECT plugin_id FROM plugins WHERE plugin_name=$1',
1448 array($pluginname));
1449 $rows = db_numrows($res);
1451 // Error: no plugin by that name
1454 $plugin_id = db_result($res,0,'plugin_id');
1456 unset($this->plugins_data);
1458 $res = db_query_params('INSERT INTO group_plugin (group_id, plugin_id) VALUES ($1, $2)',
1459 array($this->getID(),
1463 $res = db_query_params('DELETE FROM group_plugin WHERE group_id=$1 AND plugin_id=$2',
1464 array($this->getID(),
1471 * getDocEmailAddress - get email address(es) to send doc notifications to.
1473 * @return string email address.
1475 function getDocEmailAddress() {
1476 return $this->data_array['new_doc_address'];
1480 * DocEmailAll - whether or not this group has opted to use receive notices on all doc updates.
1482 * @return boolean email_on_all_doc_updates.
1484 function docEmailAll() {
1485 return $this->data_array['send_all_docs'];
1490 * getHomePage - The URL for this project's home page.
1492 * @return string homepage URL.
1494 function getHomePage() {
1495 return $this->data_array['homepage'];
1499 * getTags - Tags of this project.
1501 * @return string List of tags. Comma separated
1503 function getTags() {
1504 $sql = 'SELECT name FROM project_tags WHERE group_id = $1';
1505 $res = db_query_params($sql, array($this->getID()));
1506 return join(', ', util_result_column_to_array($res));
1510 * setTags - Set tags of this project.
1512 * @return string database result.
1514 function setTags($tags) {
1516 $sql = 'DELETE FROM project_tags WHERE group_id=$1';
1517 $res = db_query_params($sql, array($this->getID()));
1519 $this->setError('Deleting old tags: '.db_error());
1523 $inserted = array();
1524 $tags_array = preg_split('/[;,]/', $tags);
1525 foreach ($tags_array as $tag) {
1526 $tag = preg_replace('/[\t\r\n]/', ' ', $tag);
1527 // Allowed caracteres: [A-Z][a-z][0-9] -_&'#+.
1528 if (preg_match('/[^[:alnum:]| |\-|_|\&|\'|#|\+|\.]/', $tag)) {
1529 $this->setError(_('Bad tag name, you only can use the following characters: [A-Z][a-z][0-9]-_&\'#+. and space'));
1534 if ($tag == '' || array_search($tag, $inserted) !== false) continue;
1535 $sql = 'INSERT INTO project_tags (group_id,name) VALUES ($1, $2)';
1536 $res = db_query_params($sql, array($this->getID(), $tag));
1538 $this->setError(_('Setting tags: ').db_error());
1549 * getPermission - Return a Permission for this Group
1551 * @return object The Permission.
1553 function &getPermission() {
1554 return permission_get_object($this);
1558 function delete($sure, $really_sure, $really_really_sure) {
1559 if (!$sure || !$really_sure || !$really_really_sure) {
1560 $this->setMissingParamsError(_('Please tick all checkboxes.'));
1563 if ($this->getID() == forge_get_config('news_group') ||
1564 $this->getID() == 1 ||
1565 $this->getID() == forge_get_config('stats_group') ||
1566 $this->getID() == forge_get_config('peer_rating_group')) {
1567 $this->setError(_('Cannot Delete System Group'));
1570 $perm =& $this->getPermission();
1571 if (!$perm || !is_object($perm)) {
1572 $this->setPermissionDeniedError();
1574 } elseif ($perm->isError()) {
1575 $this->setPermissionDeniedError();
1577 } elseif (!$perm->isSuperUser()) {
1578 $this->setPermissionDeniedError();
1584 // Remove all the members
1586 $members =& $this->getMembers();
1587 foreach ($members as $i) {
1588 if(!$this->removeUser($i->getID())) {
1589 $this->setError(_('Could not properly remove member:').' '.$i->getID());
1593 // Failsafe until user_group table is gone
1594 $res = db_query_params('DELETE FROM user_group WHERE group_id=$1',
1595 array($this->getID()));
1597 // unlink roles to this project
1598 if ($this->isPublic()) {
1599 $ra = RoleAnonymous::getInstance();
1600 $rl = RoleLoggedIn::getInstance();
1601 $ra->unlinkProject($this);
1602 $rl->unlinkProject($this);
1604 // @todo : unlink all the other roles created in the project...
1609 $atf = new ArtifactTypeFactory($this);
1610 $at_arr =& $atf->getArtifactTypes();
1611 foreach ($at_arr as $i) {
1612 if (!is_object($i)) {
1615 if (!$i->delete(1,1)) {
1616 $this->setError(_('Could not properly delete the tracker:').' '.$i->getErrorMessage());
1623 $ff = new ForumFactory($this);
1624 $f_arr =& $ff->getForums();
1625 foreach ($f_arr as $i) {
1626 if (!is_object($i)) {
1629 if(!$i->delete(1,1)) {
1630 $this->setError(_('Could not properly delete the forum:').' '.$i->getErrorMessage());
1635 // Delete Subprojects
1637 $pgf = new ProjectGroupFactory($this);
1638 $pg_arr =& $pgf->getProjectGroups();
1639 foreach ($pg_arr as $i) {
1640 if (!is_object($i)) {
1643 if (!$i->delete(1,1)) {
1644 $this->setError(_('Could not properly delete the ProjectGroup:').' '.$i->getErrorMessage());
1649 // Delete FRS Packages
1651 $res = db_query_params('SELECT * FROM frs_package WHERE group_id=$1',
1652 array($this->getID()));
1653 while ($arr = db_fetch_array($res)) {
1654 $frsp=new FRSPackage($this, $arr['package_id'], $arr);
1655 if (!$frsp->delete(1, 1)) {
1656 $this->setError(_('Could not properly delete the FRSPackage:').' '.$frsp->getErrorMessage());
1663 $news_group=group_get_object(forge_get_config('news_group'));
1664 $res = db_query_params('SELECT forum_id FROM news_bytes WHERE group_id=$1',
1665 array($this->getID()));
1667 $this->setError(_('Error Deleting News: ').db_error());
1672 for ($i=0; $i<db_numrows($res); $i++) {
1673 $Forum = new Forum($news_group,db_result($res,$i,'forum_id'));
1674 if (!$Forum->delete(1,1)) {
1675 $this->setError(_("Could Not Delete News Forum: %d"),$Forum->getID());
1679 $res = db_query_params('DELETE FROM news_bytes WHERE group_id=$1',
1680 array($this->getID()));
1682 $this->setError(_('Error Deleting News: ').db_error());
1690 $res = db_query_params('DELETE FROM doc_data WHERE group_id=$1',
1691 array($this->getID()));
1693 $this->setError(_('Error Deleting Documents: ').db_error());
1698 $res = db_query_params('DELETE FROM doc_groups WHERE group_id=$1',
1699 array($this->getID()));
1701 $this->setError(_('Error Deleting Documents: ').db_error());
1709 $res=db_query_params('DELETE FROM project_tags WHERE group_id=$1', array($this->getID()));
1711 $this->setError(_('Error Deleting Tags: ').db_error());
1717 // Delete group history
1719 $res = db_query_params('DELETE FROM group_history WHERE group_id=$1',
1720 array($this->getID()));
1722 $this->setError(_('Error Deleting Project History: ').db_error());
1728 // Delete group plugins
1730 $res = db_query_params('DELETE FROM group_plugin WHERE group_id=$1',
1731 array($this->getID()));
1733 $this->setError(_('Error Deleting Project Plugins: ').db_error());
1739 // Delete group cvs stats
1741 $res = db_query_params ('DELETE FROM stats_cvs_group WHERE group_id=$1',
1742 array ($this->getID())) ;
1744 $this->setError(_('Error Deleting SCM Statistics: ').db_error());
1752 $sf = new SurveyFactory($this);
1753 $s_arr =& $sf->getSurveys();
1754 foreach ($s_arr as $i) {
1755 if (!is_object($i)) {
1758 if (!$i->delete()) {
1759 $this->setError(_('Could not properly delete the survey'));
1764 // Delete SurveyQuestions
1766 $sqf = new SurveyQuestionFactory($this);
1767 $sq_arr =& $sqf->getSurveyQuestions();
1768 foreach ($sq_arr as $i) {
1769 if (!is_object($i)) {
1772 if (!$i->delete()) {
1773 $this->setError(_('Could not properly delete the survey questions'));
1778 // Delete Mailing List Factory
1780 $mlf = new MailingListFactory($this);
1781 $ml_arr =& $mlf->getMailingLists();
1782 foreach ($ml_arr as $i) {
1783 if (!is_object($i)) {
1786 if (!$i->delete(1,1)) {
1787 $this->setError(_('Could not properly delete the mailing list'));
1794 $res = db_query_params('DELETE FROM trove_group_link WHERE group_id=$1',
1795 array($this->getID()));
1797 $this->setError(_('Error Deleting Trove: ').db_error());
1802 $res = db_query_params('DELETE FROM trove_agg WHERE group_id=$1',
1803 array($this->getID()));
1805 $this->setError(_('Error Deleting Trove: ').db_error());
1813 $res = db_query_params('DELETE FROM project_sums_agg WHERE group_id=$1',
1814 array($this->getID()));
1816 $this->setError(_('Error Deleting Counters: ').db_error());
1821 $res = db_query_params('INSERT INTO deleted_groups (unix_group_name, delete_date, isdeleted) VALUES ($1, $2, $3)',
1822 array($this->getUnixName(),
1826 $this->setError(_('Error Deleting Project:').' '.db_error());
1831 $res = db_query_params('DELETE FROM groups WHERE group_id=$1',
1832 array($this->getID()));
1834 $this->setError(_('Error Deleting Project:').' '.db_error());
1841 $hook_params = array();
1842 $hook_params['group'] = $this;
1843 $hook_params['group_id'] = $this->getID();
1844 plugin_hook("group_delete", $hook_params);
1846 if (forge_get_config('upload_dir') != '' && $this->getUnixName()) {
1847 exec('/bin/rm -rf '.forge_get_config('upload_dir').'/'.$this->getUnixName().'/');
1849 if (forge_get_config('ftp_upload_dir') != '' && $this->getUnixName()) {
1850 exec('/bin/rm -rf '.forge_get_config('ftp_upload_dir').'/'.$this->getUnixName().'/');
1855 $res = db_query_params('DELETE FROM rep_group_act_monthly WHERE group_id=$1',
1856 array ($this->getID()));
1857 //echo 'rep_group_act_monthly'.db_error();
1858 $res = db_query_params('DELETE FROM rep_group_act_weekly WHERE group_id=$1',
1859 array ($this->getID()));
1860 //echo 'rep_group_act_weekly'.db_error();
1861 $res = db_query_params('DELETE FROM rep_group_act_daily WHERE group_id=$1',
1862 array ($this->getID()));
1863 //echo 'rep_group_act_daily'.db_error();
1864 unset($this->data_array);
1869 Basic functions to add/remove users to/from a group
1870 and update their permissions
1874 * addUser - controls adding a user to a group.
1876 * @param string Unix name of the user to add OR integer user_id.
1877 * @param int The role_id this user should have.
1878 * @return boolean success.
1881 function addUser($user_identifier,$role_id) {
1884 Admins can add users to groups
1887 if (!forge_check_perm ('project_admin', $this->getID())) {
1888 $this->setPermissionDeniedError();
1894 get user id for this user's unix_name
1896 if (is_int ($user_identifier)) { // user_id or user_name
1897 $res_newuser = db_query_params ('SELECT * FROM users WHERE user_id=$1', array ($user_identifier)) ;
1899 $res_newuser = db_query_params ('SELECT * FROM users WHERE user_name=$1', array ($user_identifier)) ;
1901 if (db_numrows($res_newuser) > 0) {
1903 // make sure user is active
1905 if (db_result($res_newuser,0,'status') != 'A') {
1906 $this->setError(_('User is not active. Only active users can be added.'));
1912 // user was found - set new user_id var
1914 $user_id = db_result($res_newuser,0,'user_id');
1916 $role = new Role($this,$role_id);
1917 if (!$role || !is_object($role)) {
1918 $this->setError(_('Error Getting Role Object'));
1921 } elseif ($role->isError()) {
1922 $this->setError('addUser::roleget::'.$role->getErrorMessage());
1928 $role->addUser(user_get_object ($user_id)) ;
1929 if (!$SYS->sysCheckCreateGroup($this->getID())){
1930 $this->setError($SYS->getErrorMessage());
1934 if (!$SYS->sysCheckCreateUser($user_id)) {
1935 $this->setError($SYS->getErrorMessage());
1942 // if not already a member, add them
1944 $res_member = db_query_params('SELECT user_id
1946 WHERE user_id=$1 AND group_id=$2',
1947 array($user_id, $this->getID()));
1949 if (db_numrows($res_member) < 1) {
1951 // Create this user's row in the user_group table
1953 $res = db_query_params('INSERT INTO user_group
1954 (user_id,group_id,admin_flags,forum_flags,project_flags,
1955 doc_flags,cvs_flags,member_role,release_flags,artifact_flags)
1956 VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10)',
1968 //verify the insert worked
1969 if (!$res || db_affected_rows($res) < 1) {
1970 $this->setError(sprintf(_('ERROR: Could Not Add User To Group: %s'),db_error()));
1975 // check and create if group doesn't exists
1977 //echo "<h2>Group::addUser SYS->sysCheckCreateGroup(".$this->getID().")</h2>";
1978 if (!$SYS->sysCheckCreateGroup($this->getID())){
1979 $this->setError($SYS->getErrorMessage());
1984 // check and create if user doesn't exists
1986 //echo "<h2>Group::addUser SYS->sysCheckCreateUser($user_id)</h2>";
1987 if (!$SYS->sysCheckCreateUser($user_id)) {
1988 $this->setError($SYS->getErrorMessage());
1995 //echo "<h2>Group::addUser role->setUser($user_id)</h2>";
1996 if (!$role->setUser($user_id)) {
1997 $this->setError('addUser::role::setUser'.$role->getErrorMessage());
2003 // user was already a member
2004 // make sure they are set up
2006 $user= user_get_object($user_id,$res_newuser);
2007 $user->fetchData($user->getID());
2008 $role = new Role($this,$role_id);
2009 if (!$role || !is_object($role)) {
2010 $this->setError(_('Error Getting Role Object'));
2013 } elseif ($role->isError()) {
2014 $this->setError('addUser::roleget::'.$role->getErrorMessage());
2018 //echo "<h2>Already Member Group::addUser role->setUser($user_id)</h2>";
2019 if (!$role->setUser($user_id)) {
2020 $this->setError('addUser::role::setUser'.$role->getErrorMessage());
2025 // set up their system info
2027 //echo "<h2>Already Member Group::addUser SYS->sysCheckCreateUser($user_id)</h2>";
2028 if (!$SYS->sysCheckCreateUser($user_id)) {
2029 $this->setError($SYS->getErrorMessage());
2037 // user doesn't exist
2039 $this->setError(_('ERROR: User does not exist'));
2044 $hook_params['group'] = $this;
2045 $hook_params['group_id'] = $this->getID();
2046 $hook_params['user'] = &user_get_object($user_id);
2047 $hook_params['user_id'] = $user_id;
2048 plugin_hook ("group_adduser", $hook_params);
2053 $this->addHistory('Added User',$user_identifier);
2059 * removeUser - controls removing a user from a group.
2061 * Users can remove themselves.
2063 * @param int The ID of the user to remove.
2064 * @return boolean success.
2066 function removeUser($user_id) {
2069 if ($user_id != user_getid()
2070 || !forge_check_perm('project_admin', $this->getID())) {
2071 $this->setPermissionDeniedError();
2078 $user = user_get_object($user_id);
2079 $roles = RBACEngine::getInstance()->getAvailableRolesForUser($user);
2081 foreach ($roles as $role) {
2082 if ($role->getHomeProject() && $role->getHomeProject()->getID() == $this->getID()) {
2083 $found_role = $role;
2087 if ($found_role == NULL) {
2088 $this->setError(sprintf(_('ERROR: User not removed: %s')));
2092 $found_role->removeUser($user);
2093 if (!$SYS->sysGroupCheckUser($this->getID(), $user_id)) {
2094 $this->setError($SYS->getErrorMessage());
2100 $res = db_query_params('DELETE FROM user_group WHERE group_id=$1 AND user_id=$2',
2101 array($this->getID(),
2103 if (!$res || db_affected_rows($res) < 1) {
2104 $this->setError(_('ERROR: User not removed:').' '.db_error());
2111 // reassign open artifacts to id=100
2113 $res = db_query_params('UPDATE artifact SET assigned_to=100
2114 WHERE group_artifact_id
2115 IN (SELECT group_artifact_id
2116 FROM artifact_group_list
2117 WHERE group_id=$1 AND status_id=1 AND assigned_to=$2)',
2118 array($this->getID(),
2121 $this->setError(_('ERROR: DB: artifact:').' '.db_error());
2127 // reassign open tasks to id=100
2128 // first have to purge any assignments that would cause
2129 // conflict with existing assignment to 100
2131 $res = db_query_params('DELETE FROM project_assigned_to
2132 WHERE project_task_id IN (SELECT pt.project_task_id
2133 FROM project_task pt, project_group_list pgl, project_assigned_to pat
2134 WHERE pt.group_project_id = pgl.group_project_id
2135 AND pat.project_task_id=pt.project_task_id
2136 AND pt.status_id=1 AND pgl.group_id=$1
2137 AND pat.assigned_to_id=$2)
2138 AND assigned_to_id=100',
2139 array($this->getID(),
2142 $this->setError(sprintf(_('ERROR: DB: project_assigned_to %d: %s'), 1, db_error()));
2146 $res = db_query_params('UPDATE project_assigned_to SET assigned_to_id=100
2147 WHERE project_task_id IN (SELECT pt.project_task_id
2148 FROM project_task pt, project_group_list pgl
2149 WHERE pt.group_project_id = pgl.group_project_id
2150 AND pt.status_id=1 AND pgl.group_id=$1)
2151 AND assigned_to_id=$2',
2152 array($this->getID(),
2155 $this->setError(sprintf(_('ERROR: DB: project_assigned_to %d: %s'), 2, db_error()));
2161 // Remove user from system
2163 if (!$SYS->sysGroupRemoveUser($this->getID(), $user_id)) {
2164 $this->setError($SYS->getErrorMessage());
2169 $hook_params['group'] = $this;
2170 $hook_params['group_id'] = $this->getID();
2171 $hook_params['user'] = user_get_object($user_id);
2172 $hook_params['user_id'] = $user_id;
2173 plugin_hook ("group_removeuser", $hook_params);
2176 $this->addHistory('Removed User',$user_id);
2183 * updateUser - controls updating a user's role in this group.
2185 * @param int The ID of the user.
2186 * @param int The role_id to set this user to.
2187 * @return boolean success.
2189 function updateUser($user_id,$role_id) {
2192 if (!forge_check_perm ('project_admin', $this->getID())) {
2193 $this->setPermissionDeniedError();
2198 $newrole = RBACEngine::getInstance()->getRoleById ($role_id) ;
2199 if (!$newrole || !is_object($newrole)) {
2200 $this->setError(_('Could Not Get Role'));
2202 } elseif ($newrole->isError()) {
2203 $this->setError(sprintf(_('Role: %s'),$role->getErrorMessage()));
2205 } elseif ($newrole->getHomeProject() == NULL
2206 || $newrole->getHomeProject()->getID() != $this->getID()) {
2207 $this->setError(_('Wrong destination role'));
2210 $user = user_get_object ($user_id) ;
2211 $roles = RBACEngine::getInstance()->getAvailableRolesForUser ($user) ;
2212 $found_role = NULL ;
2213 foreach ($roles as $role) {
2214 if ($role->getHomeProject() && $role->getHomeProject()->getID() == $this->getID()) {
2215 $found_role = $role ;
2219 if ($found_role == NULL) {
2220 $this->setError(sprintf(_('ERROR: User not removed: %s')));
2224 $found_role->removeUser ($user) ;
2225 $newrole->addUser ($user) ;
2227 $role = new Role($this,$role_id);
2228 if (!$role || !is_object($role)) {
2229 $this->setError(_('Could Not Get Role'));
2231 } elseif ($role->isError()) {
2232 $this->setError(sprintf(_('Role: %s'),$role->getErrorMessage()));
2235 //echo "<h3>Group::updateUser role->setUser($user_id)</h3>";
2236 if (!$role->setUser($user_id)) {
2237 $this->setError(sprintf(_('Role: %s'),$role->getErrorMessage()));
2242 $this->addHistory('Updated User',$user_id);
2247 * addHistory - Makes an audit trail entry for this project.
2249 * @param string The name of the field.
2250 * @param string The Old Value for this $field_name.
2251 * @return database result handle.
2254 function addHistory($field_name, $old_value) {
2255 return db_query_params ('INSERT INTO group_history(group_id,field_name,old_value,mod_by,adddate)
2256 VALUES ($1,$2,$3,$4,$5)',
2257 array ($this->getID(),
2265 * activateUsers - Make sure that group members have unix accounts.
2267 * Setup unix accounts for group members. Can be called even
2268 * if members are already active.
2272 function activateUsers() {
2274 Activate member(s) of the project
2278 $members = $this->getUsers (true) ;
2280 foreach ($members as $member) {
2282 foreach (RBACEngine::getInstance()->getAvailableRolesForUser ($member) as $role) {
2283 if ($role->getHomeProject() && $role->getHomeProject()->getID() == $this->getID()) {
2286 if (!$this->addUser($member->getUnixName(),$role->getID())) {
2293 $res_member = db_query_params('SELECT user_id,role_id FROM user_group WHERE group_id=$1',
2294 array ($this->getID()));
2295 while ($row_member = db_fetch_array($res_member)) {
2296 $u = user_get_object($row_member['user_id']);
2297 if (!$this->addUser($u->getUnixName(),$row_member['role_id'])) {
2307 * getMembers - returns array of User objects for this project
2309 * @return array of User objects for this group.
2311 function getMembers() {
2312 return $this->getUsers (true) ;
2316 * replaceTemplateStrings - fill-in some blanks with project name
2318 * @param string Template string
2319 * @return string String after replacements
2321 function replaceTemplateStrings($string) {
2322 $string = str_replace ('UNIXNAME', $this->getUnixName(), $string) ;
2323 $string = str_replace ('PUBLICNAME', $this->getPublicName(), $string) ;
2324 $string = str_replace ('DESCRIPTION', $this->getDescription(), $string) ;
2329 * approve - Approve pending project.
2331 * @param object The User object who is doing the updating.
2334 function approve(&$user) {
2336 require_once $gfcommon.'widget/WidgetLayoutManager.class.php';
2338 if ($this->getStatus()=='A') {
2339 $this->setError(_("Group already active"));
2345 // Step 1: Activate group and create LDAP entries
2346 if (!$this->setStatus($user, 'A')) {
2351 // Switch to system language for item creation
2352 setup_gettext_from_sys_lang();
2354 // Create default roles
2356 $idadmin_group = NULL;
2357 foreach (get_group_join_requests ($this) as $gjr) {
2358 $idadmin_group = $gjr->getUserID();
2361 if ($idadmin_group == NULL) {
2362 $idadmin_group = $user->getID();
2365 $admin_group = db_query_params('SELECT user_id FROM user_group WHERE group_id=$1 AND admin_flags=$2',
2366 array($this->getID(),
2368 if (db_numrows($admin_group) > 0) {
2369 $idadmin_group = db_result($admin_group,0,'user_id');
2371 $idadmin_group = $user->getID();
2372 db_query_params('INSERT INTO user_group (user_id, group_id, admin_flags) VALUES ($1, $2, $3)',
2373 array($idadmin_group,
2379 $template = $this->getTemplateProject();
2380 $id_mappings = array();
2381 $seen_local_roles = false;
2383 // Copy roles from template project
2384 foreach($template->getRoles() as $oldrole) {
2385 if ($oldrole->getHomeProject() != NULL) {
2386 $role = new Role($this);
2388 // Need to use a different role name so that the permissions aren't set from the hardcoded defaults
2389 $role->create('TEMPORARY ROLE NAME', $data, true);
2390 $role->setName($oldrole->getName());
2391 $seen_local_roles = true;
2394 $role->linkProject($this);
2396 $id_mappings['role'][$oldrole->getID()] = $role->getID();
2397 // Reuse the project_admin permission
2398 $role->setSetting ('project_admin', $this->getID(), $oldrole->getSetting ('project_admin', $template->getID())) ;
2402 if (!$seen_local_roles) {
2403 $role = new Role($this);
2404 $adminperms = array ('project_admin' => array ($this->getID() => 1)) ;
2405 $role_id = $role->create ('Admin', $adminperms, true) ;
2409 $roles = $this->getRoles() ;
2410 foreach ($roles as $r) {
2411 if ($r->getSetting ('project_admin', $this->getID())) {
2412 $r->addUser(user_get_object ($idadmin_group));
2417 // Temporarily switch to the submitter's identity
2418 $saved_session = session_get_user();
2419 session_set_internal($idadmin_group);
2422 if (forge_get_config('use_tracker')) {
2423 $this->setUseTracker ($template->usesTracker());
2424 if ($template->usesTracker()) {
2425 $oldatf = new ArtifactTypeFactory($template);
2426 foreach ($oldatf->getArtifactTypes() as $o) {
2427 $t = new ArtifactType ($this) ;
2428 $t->create ($this->replaceTemplateStrings($o->getName()),$this->replaceTemplateStrings($o->getDescription()),$o->isPublic(),$o->allowsAnon(),$o->emailAll(),$o->getEmailAddress(),$o->getDuePeriod()/86400,0,$o->getSubmitInstructions(),$o->getBrowseInstructions()) ;
2429 $id_mappings['tracker'][$o->getID()] = $t->getID();
2430 $t->cloneFieldsFrom ($o->getID());
2435 if (forge_get_config('use_pm')) {
2436 $this->setUsePM ($template->usesPM());
2437 if ($template->usesPM()) {
2438 $oldpgf = new ProjectGroupFactory($template);
2439 foreach ($oldpgf->getProjectGroups() as $o) {
2440 $pg = new ProjectGroup($this);
2441 $pg->create($this->replaceTemplateStrings($o->getName()),$this->replaceTemplateStrings($o->getDescription()),$o->isPublic(),$o->getSendAllPostsTo());
2442 $id_mappings['pm'][$o->getID()] = $pg->getID();
2447 if (forge_get_config('use_forum')) {
2448 $this->setUseForum($template->usesForum()) ;
2449 if ($template->usesForum()) {
2450 $oldff = new ForumFactory($template) ;
2451 foreach ($oldff->getForums() as $o) {
2452 $f = new Forum($this);
2453 $f->create($this->replaceTemplateStrings($o->getName()),$this->replaceTemplateStrings($o->getDescription()),$o->isPublic(),$o->getSendAllPostsTo(),1,$o->allowAnonymous(),$o->getModerationLevel());
2454 $id_mappings['forum'][$o->getID()] = $f->getID();
2459 if (forge_get_config('use_docman')) {
2460 $this->setUseDocman($template->usesDocman());
2461 if ($template->usesDocman()) {
2462 $olddgf = new DocumentGroupFactory($template);
2463 // First pass: create all docgroups
2464 $id_mappings['docman_docgroup'][0] = 0;
2465 foreach ($olddgf->getDocumentGroups() as $o) {
2466 $ndgf = new DocumentGroup($this);
2467 // .trash is a reserved directory
2468 if ($o->getName() != '.trash' && $o->getParentID() == 0) {
2469 $ndgf->create($this->replaceTemplateStrings($o->getName()));
2470 $id_mappings['docman_docgroup'][$o->getID()] = $ndgf->getID();
2473 // Second pass: restore hierarchy links
2474 foreach ($olddgf->getDocumentGroups() as $o) {
2475 $ndgf = new DocumentGroup($this);
2476 if ($o->getName() != '.trash' && $o->getParentID() == 0) {
2477 $ndgf->fetchData($id_mappings['docman_docgroup'][$o->getID()]);
2478 $ndgf->update($ndgf->getName(), $id_mappings['docman_docgroup'][$o->getParentID()]);
2484 if (forge_get_config('use_frs')) {
2485 $this->setUseFRS ($template->usesFRS());
2486 if ($template->usesFRS()) {
2487 foreach (get_frs_packages($template) as $o) {
2488 $newp = new FRSPackage($this);
2489 $nname = $this->replaceTemplateStrings($o->getName());
2490 $newp->create ($nname, $o->isPublic());
2495 if (forge_get_config('use_mail')) {
2496 $this->setUseMail($template->usesMail()) ;
2497 if ($template->usesMail()) {
2498 $oldmlf = new MailingListFactory($template);
2499 foreach ($oldmlf->getMailingLists() as $o) {
2500 $ml = new MailingList($this);
2501 $nname = preg_replace ('/^'.$template->getUnixName().'-/','',$o->getName()) ;
2503 $ndescription = $this->replaceTemplateStrings($o->getDescription()) ;
2504 $ml->create($nname, $ndescription, $o->isPublic());
2509 $this->setUseSCM ($template->usesSCM()) ;
2511 foreach ($template->getPlugins() as $plugin_id => $plugin_name) {
2512 $this->setPluginUse ($plugin_name) ;
2515 foreach ($template->getRoles() as $oldrole) {
2516 $newrole = RBACEngine::getInstance()->getRoleById ($id_mappings['role'][$oldrole->getID()]) ;
2517 if ($oldrole->getHomeProject() != NULL
2518 && $oldrole->getHomeProject()->getID() == $template->getID()) {
2519 $newrole->setPublic ($oldrole->isPublic()) ;
2521 $oldsettings = $oldrole->getSettingsForProject ($template) ;
2523 $sections = array ('project_read', 'project_admin', 'frs', 'scm', 'docman', 'tracker_admin', 'new_tracker', 'forum_admin', 'new_forum', 'pm_admin', 'new_pm') ;
2524 foreach ($sections as $section) {
2525 $newrole->setSetting ($section, $this->getID(), $oldsettings[$section][$template->getID()]) ;
2528 $sections = array ('tracker', 'pm', 'forum') ;
2529 foreach ($sections as $section) {
2530 if (isset ($oldsettings[$section])) {
2531 foreach ($oldsettings[$section] as $k => $v) {
2532 // Only copy perms for tools that have been copied
2533 if (isset ($id_mappings[$section][$k])) {
2534 $newrole->setSetting ($section,
2535 $id_mappings[$section][$k],
2543 $lm = new WidgetLayoutManager();
2544 $lm->createDefaultLayoutForProject ($this->getID(), $template->getID()) ;
2546 $params = array () ;
2547 $params['template'] = $template ;
2548 $params['project'] = $this ;
2549 $params['id_mappings'] = $id_mappings ;
2550 plugin_hook_by_reference ('clone_project_from_template', $params) ;
2552 // Disable everything
2553 $res = db_query_params ('UPDATE groups SET use_mail=0, use_survey=0, use_forum=0, use_pm=0, use_pm_depend_box=0, use_scm=0, use_news=0, use_docman=0, is_public=0, use_ftp=0, use_tracker=0, use_frs=0, use_stats=0 WHERE group_id=$1',
2555 array ($this->getID())) ;
2558 $this->normalizeAllRoles();
2560 // Switch back to user preference
2561 session_set_internal($saved_session->getID());
2562 setup_gettext_from_context();
2566 $this->sendApprovalEmail();
2567 $this->addHistory('Approved', 'x');
2570 // Plugin can make approve operation there
2572 $params[0] = $idadmin_group;
2573 $params[1] = $this->getID();
2574 plugin_hook('group_approved', $params);
2582 * sendApprovalEmail - Send new project email.
2584 * @return boolean success.
2587 function sendApprovalEmail() {
2588 $admins = RBACEngine::getInstance()->getUsersByAllowedAction ('project_admin', $this->getID()) ;
2590 if (count($admins) < 1) {
2591 $this->setError(_("Group does not have any administrators."));
2595 // send one email per admin
2596 foreach ($admins as $admin) {
2597 setup_gettext_for_user ($admin) ;
2599 $message=sprintf(_('Your project registration for %4$s has been approved.
2601 Project Full Name: %1$s
2602 Project Unix Name: %2$s
2604 Your DNS will take up to a day to become active on our site.
2605 Your web site is accessible through your shell account. Please read
2606 site documentation (see link below) about intended usage, available
2607 services, and directory layout of the account.
2610 own project page in %4$s while logged in, you will find
2611 additional menu functions to your left labeled \'Project Admin\'.
2613 We highly suggest that you now visit %4$s and create a public
2614 description for your project. This can be done by visiting your project
2615 page while logged in, and selecting \'Project Admin\' from the menus
2616 on the left (or by visiting %3$s
2619 Your project will also not appear in the Trove Software Map (primary
2620 list of projects hosted on %4$s which offers great flexibility in
2621 browsing and search) until you categorize it in the project administration
2622 screens. So that people can find your project, you should do this now.
2623 Visit your project while logged in, and select \'Project Admin\' from the
2626 Enjoy the system, and please tell others about %4$s. Let us know
2627 if there is anything we can do to help you.
2630 htmlspecialchars_decode($this->getPublicName()),
2631 $this->getUnixName(),
2632 util_make_url ('/project/admin/?group_id='.$this->getID()),
2633 forge_get_config ('forge_name'));
2635 util_send_message($admin->getEmail(), sprintf(_('%1$s Project Approved'), forge_get_config ('forge_name')), $message);
2637 setup_gettext_from_context();
2645 * sendRejectionEmail - Send project rejection email.
2647 * This function sends out a rejection message to a user who
2648 * registered a project.
2650 * @param int The id of the response to use.
2651 * @param string The rejection message.
2652 * @return boolean completion status.
2655 function sendRejectionEmail($response_id, $message="zxcv") {
2656 $submitters = array () ;
2658 foreach (get_group_join_requests ($this) as $gjr) {
2659 $submitters[] = user_get_object($gjr->getUserID());
2662 $res = db_query_params("SELECT u.user_id FROM users u, user_group ug WHERE ug.group_id=$1 AND u.user_id=ug.user_id",
2664 while ($arr = db_fetch_array($res)) {
2665 $submitter[] = user_get_object($arr['user_id']);
2669 if (count ($submitters) < 1) {
2670 $this->setError(_("Group does not have any administrators."));
2674 foreach ($submitters as $admin) {
2675 setup_gettext_for_user($admin);
2677 $response=sprintf(_('Your project registration for %3$s has been denied.
2679 Project Full Name: %1$s
2680 Project Unix Name: %2$s
2682 Reasons for negative decision:
2684 '), $this->getPublicName(), $this->getUnixName(), forge_get_config('forge_name'));
2686 // Check to see if they want to send a custom rejection response
2687 if ($response_id == 0) {
2688 $response .= $message;
2690 $response .= db_result(
2691 db_query_params('SELECT response_text FROM canned_responses WHERE response_id=$1', array ($response_id)),
2696 util_send_message($admin->getEmail(), sprintf(_('%1$s Project Denied'), forge_get_config ('forge_name')), $response);
2697 setup_gettext_from_context();
2704 * sendNewProjectNotificationEmail - Send new project notification email.
2706 * This function sends out a notification email to the
2707 * SourceForge admin user when a new project is
2710 * @return boolean success.
2713 function sendNewProjectNotificationEmail() {
2714 // Get the user who wants to register the project
2715 $submitters = array();
2717 foreach (get_group_join_requests ($this) as $gjr) {
2718 $submitters[] = user_get_object($gjr->getUserID());
2721 $res = db_query_params("SELECT u.user_id FROM users u, user_group ug WHERE ug.group_id=$1 AND u.user_id=ug.user_id",
2723 while ($arr = db_fetch_array ($res)) {
2724 $submitter[] = user_get_object($arr['user_id']);
2727 if (count ($submitters) < 1) {
2728 $this->setError(_("Could not find user who has submitted the project."));
2732 $admins = RBACEngine::getInstance()->getUsersByAllowedAction ('approve_projects', -1) ;
2734 if (count($admins) < 1) {
2735 $this->setError(_("There is no administrator to send the mail to."));
2739 foreach ($admins as $admin) {
2740 $admin_email = $admin->getEmail () ;
2741 setup_gettext_for_user ($admin) ;
2743 foreach ($submitters as $u) {
2744 $submitter_names[] = $u->getRealName() ;
2747 $message = sprintf(_('New %1$s Project Submitted
2749 Project Full Name: %2$s
2750 Submitted Description: %3$s
2752 forge_get_config ('forge_name'),
2753 htmlspecialchars_decode($this->getPublicName()),
2754 htmlspecialchars_decode($this->getRegistrationPurpose()));
2756 foreach ($submitters as $submitter) {
2757 $message .= sprintf(_('Submitter: %1$s (%2$s)
2759 $submitter->getRealName(),
2760 $submitter->getUnixName());
2763 $message .= sprintf (_('
2764 Please visit the following URL to approve or reject this project:
2766 util_make_url ('/admin/approve-pending.php')) ;
2767 util_send_message($admin_email, sprintf(_('New %1$s Project Submitted'), forge_get_config ('forge_name')), $message);
2768 setup_gettext_from_context();
2772 $email = $submitter->getEmail() ;
2773 setup_gettext_for_user ($submitter) ;
2775 $message=sprintf(_('New %1$s Project Submitted
2777 Project Full Name: %2$s
2778 Submitted Description: %3$s
2780 The %1$s admin team will now examine your project submission. You will be notified of their decision.'), forge_get_config ('forge_name'), $this->getPublicName(), util_unconvert_htmlspecialchars($this->getRegistrationPurpose()), forge_get_config('web_host'));
2782 util_send_message($email, sprintf(_('New %1$s Project Submitted'), forge_get_config ('forge_name')), $message);
2783 setup_gettext_from_context();
2792 * validateGroupName - Validate the group name
2794 * @param string Group name.
2796 * @return boolean an error false and set an error is the group name is invalide otherwise return true
2798 function validateGroupName($group_name) {
2799 if (strlen($group_name)<3) {
2800 $this->setError(_('Group name is too short'));
2802 } else if (strlen(htmlspecialchars($group_name))>50) {
2803 $this->setError(_('Group name is too long'));
2805 } else if ($group=group_get_object_by_publicname($group_name)) {
2806 $this->setError(_('Group name already taken'));
2814 * getRoles - Get the roles of the group.
2816 * @return array Role ids of this group.
2818 function getRolesId() {
2819 $role_ids = array();
2822 $res = db_query_params('SELECT role_id FROM pfo_role WHERE home_group_id=$1',
2823 array($this->getID()));
2824 while ($arr = db_fetch_array($res)) {
2825 $role_ids[] = $arr['role_id'];
2827 $res = db_query_params('SELECT role_id FROM role_project_refs WHERE group_id=$1',
2828 array($this->getID()));
2829 while ($arr = db_fetch_array($res)) {
2830 $role_ids[] = $arr['role_id'];
2833 $res = db_query_params('SELECT role_id FROM role WHERE group_id=$1',
2834 array($this->getID()));
2835 while ($arr = db_fetch_array($res)) {
2836 $role_ids[] = $arr['role_id'];
2840 return array_unique($role_ids);
2844 * getRoles - Get the roles of the group.
2846 * @return array Roles of this group.
2848 function getRoles() {
2851 $roles = $this->getRolesId();
2853 $engine = RBACEngine::getInstance();
2854 foreach ($roles as $role_id) {
2855 $result[] = $engine->getRoleById ($role_id);
2858 foreach ($roles as $role_id) {
2859 $result[] = new Role ($this, $role_id);
2866 function normalizeAllRoles() {
2867 $roles = $this->getRoles();
2869 foreach ($roles as $r) {
2870 $r->normalizeData();
2875 * getUnixStatus - Status of activation of unix account.
2877 * @return char (N)one, (A)ctive, (S)uspended or (D)eleted
2879 function getUnixStatus() {
2880 return $this->data_array['unix_status'];
2884 * setUnixStatus - Sets status of activation of unix account.
2886 * @param string The unix status.
2892 * @return boolean success.
2894 function setUnixStatus($status) {
2897 $res = db_query_params ('UPDATE groups SET unix_status=$1 WHERE group_id=$2',
2902 $this->setError(sprintf(_('ERROR - Could Not Update Group Unix Status: %s'),db_error()));
2906 if ($status == 'A') {
2907 if (!$SYS->sysCheckCreateGroup($this->getID())) {
2908 $this->setError($SYS->getErrorMessage());
2913 if ($SYS->sysCheckGroup($this->getID())) {
2914 if (!$SYS->sysRemoveGroup($this->getID())) {
2915 $this->setError($SYS->getErrorMessage());
2922 $this->data_array['unix_status']=$status;
2929 * getUsers - Get the users of a group
2931 * @return array of user's objects.
2933 function getUsers($onlylocal = true) {
2934 if (!isset($this->membersArr)) {
2935 $this->membersArr = array () ;
2939 foreach ($this->getRoles() as $role) {
2941 && ($role->getHomeProject() == NULL || $role->getHomeProject()->getID() != $this->getID())) {
2944 foreach ($role->getUsers() as $user) {
2945 $ids[] = $user->getID() ;
2948 $ids = array_unique ($ids) ;
2949 foreach ($ids as $id) {
2950 $u = user_get_object ($id) ;
2951 if ($u->isActive()) {
2952 $this->membersArr[] = $u ;
2957 $users_group_res = db_query_params ('SELECT u.user_id FROM users u, user_group ug WHERE ug.group_id=$1 AND ug.user_id=u.user_id AND u.status=$2',
2958 array ($this->getID(),
2960 if (!$users_group_res) {
2961 $this->setError(_('Error: Enable to get users from group'). ' ' . $this->getID() . ' ' .db_error());
2965 for ($i=0; $i<db_numrows($users_group_res); $i++) {
2966 $this->membersArr[$i] = new GFUser(db_result($users_group_res,$i,'user_id'),false);
2971 return $this->membersArr;
2974 function setDocmanCreateOnlineStatus($status) {
2976 /* if we activate search engine, we probably want to reindex */
2977 $res = db_query_params('UPDATE groups SET use_docman_create_online=$1 WHERE group_id=$2',
2978 array($status, $this->getID()));
2981 $this->setError(sprintf(_('ERROR - Could Not Update Group DocmanCreateOnline Status: %s'),db_error()));
2985 $this->data_array['use_docman_create_online']=$status;
2991 function setDocmanWebdav($status) {
2993 /* if we activate search engine, we probably want to reindex */
2994 $res = db_query_params('UPDATE groups SET use_webdav=$1 WHERE group_id=$2',
2999 $this->setError(sprintf(_('ERROR - Could Not Update Group UseWebdab Status: %s'),db_error()));
3003 $this->data_array['use_webdav']=$status;
3009 function setDocmanSearchStatus($status) {
3011 /* if we activate search engine, we probably want to reindex */
3012 $res = db_query_params('UPDATE groups SET use_docman_search=$1, force_docman_reindex=$1 WHERE group_id=$2',
3017 $this->setError(sprintf(_('ERROR - Could Not Update Group UseDocmanSearch Status: %s'),db_error()));
3021 $this->data_array['use_docman_search']=$status;
3027 function setDocmanForceReindexSearch($status) {
3029 /* if we activate search engine, we probably want to reindex */
3030 $res = db_query_params('UPDATE groups SET force_docman_reindex=$1 WHERE group_id=$2',
3035 $this->setError(sprintf(_('ERROR - Could Not Update Group force_docman_reindex %s'),db_error()));
3039 $this->data_array['force_docman_reindex']=$status;
3045 function setStorageAPI($type) {
3049 function getStorageAPI() {
3055 * group_getname() - get the group name
3057 * @param int The group ID
3061 function group_getname ($group_id = 0) {
3062 $grp = group_get_object($group_id);
3064 return $grp->getPublicName();
3071 * group_getunixname() - get the unixname for a group
3073 * @param int The group ID
3077 function group_getunixname ($group_id) {
3078 $grp = group_get_object($group_id);
3080 return $grp->getUnixName();
3087 * group_get_result() - Get the group object result ID.
3089 * @param int The group ID
3093 function &group_get_result($group_id=0) {
3094 $grp = group_get_object($group_id);
3096 return $grp->getData();
3102 function getAllProjectTags($onlyvisible = true) {
3103 $res = db_query_params('SELECT project_tags.name, groups.group_id FROM groups, project_tags WHERE groups.group_id = project_tags.group_id AND groups.status = $1 ORDER BY project_tags.name, groups.group_id',
3106 if (!$res || db_numrows($res) == 0) {
3112 while ($arr = db_fetch_array($res)) {
3114 $group_id = $arr[1];
3115 if (!isset($result[$tag])) {
3116 $result[$tag] = array();
3119 if (!$onlyvisible || forge_check_perm('project_read', $group_id)) {
3120 $p = group_get_object($group_id);
3121 $result[$tag][] = array('unix_group_name' => $p->getUnixName(),
3122 'group_id' => $group_id);
3129 class ProjectComparator {
3130 var $criterion = 'name' ;
3132 function Compare ($a, $b) {
3133 switch ($this->criterion) {
3136 $namecmp = strcoll ($a->getPublicName(), $b->getPublicName()) ;
3137 if ($namecmp != 0) {
3140 /* If several projects share a same public name */
3141 return strcoll ($a->getUnixName(), $b->getUnixName()) ;
3144 return strcmp ($a->getUnixName(), $b->getUnixName()) ;
3147 $aid = $a->getID() ;
3148 $bid = $b->getID() ;
3152 return ($a < $b) ? -1 : 1;
3158 function sortProjectList (&$list, $criterion='name') {
3159 $cmp = new ProjectComparator () ;
3160 $cmp->criterion = $criterion ;
3162 return usort ($list, array ($cmp, 'Compare')) ;
3167 // c-file-style: "bsd"