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. FusionForge is free software;
12 * you can redistribute it and/or modify it under the terms of the
13 * GNU General Public License as published by the Free Software
14 * Foundation; either version 2 of the Licence, or (at your option)
17 * FusionForge is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
22 * You should have received a copy of the GNU General Public License along
23 * with FusionForge; if not, write to the Free Software Foundation, Inc.,
24 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
27 require_once $gfcommon.'tracker/ArtifactTypes.class.php';
28 require_once $gfcommon.'tracker/ArtifactTypeFactory.class.php';
29 require_once $gfcommon.'forum/Forum.class.php';
30 require_once $gfcommon.'forum/ForumFactory.class.php';
31 require_once $gfcommon.'pm/ProjectGroup.class.php';
32 require_once $gfcommon.'pm/ProjectGroupFactory.class.php';
33 require_once $gfcommon.'include/Role.class.php';
34 require_once $gfcommon.'frs/FRSPackage.class.php';
35 require_once $gfcommon.'docman/DocumentGroup.class.php';
36 require_once $gfcommon.'docman/DocumentGroupFactory.class.php';
37 require_once $gfcommon.'mail/MailingList.class.php';
38 require_once $gfcommon.'mail/MailingListFactory.class.php';
39 require_once $gfcommon.'survey/SurveyFactory.class.php';
40 require_once $gfcommon.'survey/SurveyQuestionFactory.class.php';
41 require_once $gfcommon.'include/gettext.php';
42 require_once $gfcommon.'include/GroupJoinRequest.class.php';
47 * group_get_object() - Get the group object.
49 * group_get_object() is useful so you can pool group objects/save database queries
50 * You should always use this instead of instantiating the object directly.
52 * You can now optionally pass in a db result handle. If you do, it re-uses that query
53 * to instantiate the objects.
55 * IMPORTANT! That db result must contain all fields
56 * from groups table or you will have problems
59 * @param int Result set handle ("SELECT * FROM groups WHERE group_id=xx")
60 * @return object a group object or false on failure
62 function &group_get_object($group_id, $res = false) {
63 //create a common set of group objects
64 //saves a little wear on the database
66 //automatically checks group_type and
67 //returns appropriate object
70 if (!isset($GROUP_OBJ["_".$group_id."_"])) {
72 //the db result handle was passed in
74 $res = db_query_params('SELECT * FROM groups WHERE group_id=$1', array($group_id)) ;
76 if (!$res || db_numrows($res) < 1) {
77 $GROUP_OBJ["_".$group_id."_"]=false;
80 check group type and set up object
82 if (db_result($res,0,'type_id') == 1) {
84 $GROUP_OBJ["_".$group_id."_"] = new Group($group_id, $res);
87 $GROUP_OBJ["_".$group_id."_"] = false;
91 return $GROUP_OBJ["_".$group_id."_"];
94 function &group_get_objects($id_arr) {
97 // Note: if we don't do this, the result may be corrupted
101 foreach ($id_arr as $id) {
103 // See if this ID already has been fetched in the cache
105 if (!isset($GROUP_OBJ["_".$id."_"])) {
109 if (count($fetch) > 0) {
110 $res=db_query_params('SELECT * FROM groups WHERE group_id = ANY ($1)',
111 array(db_int_array_to_any_clause($fetch)));
112 while ($arr = db_fetch_array($res)) {
113 $GROUP_OBJ["_".$arr['group_id']."_"] = new Group($arr['group_id'],$arr);
116 foreach ($id_arr as $id) {
117 $return[] =& $GROUP_OBJ["_".$id."_"];
122 function &group_get_active_projects() {
123 $res = db_query_params('SELECT group_id FROM groups WHERE status=$1',
125 return group_get_objects(util_result_column_to_array($res,0));
128 function &group_get_template_projects() {
129 $res=db_query_params ('SELECT group_id FROM groups WHERE is_template=1 AND status != $1',
131 return group_get_objects (util_result_column_to_array($res,0)) ;
134 function &group_get_object_by_name($groupname) {
135 $res = db_query_params('SELECT * FROM groups WHERE unix_group_name=$1', array($groupname));
136 return group_get_object(db_result($res, 0, 'group_id'), $res);
139 function &group_get_objects_by_name($groupname_arr) {
140 $res = db_query_params('SELECT group_id FROM groups WHERE unix_group_name = ANY ($1)',
141 array(db_string_array_to_any_clause($groupname_arr)));
142 $arr =& util_result_column_to_array($res,0);
143 return group_get_objects($arr);
146 function &group_get_object_by_publicname($groupname) {
147 $res = db_query_params('SELECT * FROM groups WHERE lower(group_name) LIKE $1',
148 array(htmlspecialchars(strtolower($groupname))));
149 return group_get_object(db_result($res, 0, 'group_id'), $res);
152 class Group extends Error {
154 * Associative array of data from db.
156 * @var array $data_array.
161 * array of User objects.
163 * @var array $membersArr.
168 * Whether the use is an admin/super user of this project.
170 * @var bool $is_admin.
175 * Artifact types result handle.
177 * @var int $types_res.
182 * Associative array of data for plugins.
184 * @var array $plugins_data.
190 * Associative array of data for the group menu.
192 * @var array $menu_data.
197 * Group - Group object constructor - use group_get_object() to instantiate.
199 * @param int Required - group_id of the group you want to instantiate.
200 * @param int Database result from select query OR associative array of all columns.
201 * @return boolean success or not
203 function Group($id = false, $res = false) {
206 //setting up an empty object
207 //probably going to call create()
211 if (!$this->fetchData($id)) {
216 // Assoc array was passed in
218 if (is_array($res)) {
219 $this->data_array =& $res;
221 if (db_numrows($res) < 1) {
222 //function in class we extended
223 $this->setError(_('Group Not Found'));
224 $this->data_array=array();
227 //set up an associative array for use by other functions
228 $this->data_array = db_fetch_array_by_row($res, 0);
236 * fetchData - May need to refresh database fields if an update occurred.
238 * @param int The group_id.
239 * @return boolean success or not
241 function fetchData($group_id) {
242 $res = db_query_params ('SELECT * FROM groups WHERE group_id=$1',
244 if (!$res || db_numrows($res) < 1) {
245 $this->setError(sprintf(_('fetchData():: %s'),db_error()));
248 $this->data_array = db_fetch_array($res);
253 * create - Create new group.
255 * This method should be called on empty Group object.
256 * It will add an entry for a pending group/project (status 'P')
258 * @param object The User object.
259 * @param string The full name of the user.
260 * @param string The Unix name of the user.
261 * @param string The new group description.
262 * @param string The purpose of the group.
263 * @param boolean Whether to send an email or not
264 * @param int The id of the project this new project is based on
265 * @return boolean success or not
267 function create(&$user, $group_name, $unix_name, $description, $purpose, $unix_box = 'shell1',
268 $scm_box = 'cvs1', $is_public = 1, $send_mail = true, $built_from_template = 0) {
269 // $user is ignored - anyone can create pending group
272 if ($this->getID()!=0) {
273 $this->setError(_('Group::create: Group object already exists'));
275 } else if (!$this->validateGroupName($group_name)) {
277 } else if (!account_groupnamevalid($unix_name)) {
278 $this->setError(_('Invalid Unix name'));
280 } else if (!$SYS->sysUseUnixName($unix_name)) {
281 $this->setError(_('Unix name already taken'));
283 } else if (db_numrows(db_query_params('SELECT group_id FROM groups WHERE unix_group_name=$1',
284 array($unix_name))) > 0) {
285 $this->setError(_('Unix name already taken'));
287 } else if (strlen($purpose)<10) {
288 $this->setError(_('Please describe your Registration Purpose in a more comprehensive manner'));
290 } else if (strlen($purpose)>1500) {
291 $this->setError(_('The Registration Purpose text is too long. Please make it smaller than 1500 bytes.'));
293 } else if (strlen($description)<10) {
294 $this->setError(_('Describe in a more comprehensive manner your project.'));
296 } else if (strlen($description)>255) {
297 $this->setError(_('Your project description is too long. Please make it smaller than 256 bytes.'));
302 $res = db_query_params('
318 VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13)',
319 array (htmlspecialchars ($group_name),
321 htmlspecialchars($description),
322 $unix_name.".".forge_get_config('web_host'),
323 $unix_name.".".forge_get_config('web_host'),
327 htmlspecialchars($purpose),
330 md5(util_randbytes()),
331 $built_from_template));
332 if (!$res || db_affected_rows($res) < 1) {
333 $this->setError(sprintf(_('ERROR: Could not create group: %s'),db_error()));
338 $id = db_insertid($res, 'groups', 'group_id');
340 $this->setError(sprintf(_('ERROR: Could not get group id: %s'),db_error()));
345 if (!$this->fetchData($id)) {
351 $gjr = new GroupJoinRequest($this);
352 $gjr->create($user->getID(),
353 'Fake GroupJoinRequest to store the creator of a project',
357 // Now, make the user an admin
359 $res=db_query_params('INSERT INTO user_group (user_id, group_id, admin_flags,
360 cvs_flags, artifact_flags, forum_flags, role_id)
361 VALUES ($1, $2, $3, $4, $5, $6, $7)',
362 array($user->getID(),
369 if (!$res || db_affected_rows($res) < 1) {
370 $this->setError(sprintf(_('ERROR: Could not add admin to newly created group: %s'),db_error()));
376 $hook_params = array();
377 $hook_params['group'] = $this;
378 $hook_params['group_id'] = $this->getID();
379 $hook_params['group_name'] = $group_name;
380 $hook_params['unix_group_name'] = $unix_name;
381 plugin_hook("group_create", $hook_params);
385 $this->sendNewProjectNotificationEmail();
393 * updateAdmin - Update core properties of group object.
395 * This function require site admin privilege.
397 * @param object User requesting operation (for access control).
398 * @param boolean Whether group is publicly accessible (0/1).
399 * @param int Group type (1-project, 2-foundry).
400 * @param string Machine on which group's home directory located.
401 * @param string Domain which serves group's WWW.
405 function updateAdmin(&$user, $is_public, $type_id, $unix_box, $http_domain) {
406 $perm =& $this->getPermission();
408 if (!$perm || !is_object($perm)) {
409 $this->setError(_('Could not get permission.'));
413 if (!$perm->isSuperUser()) {
414 $this->setError(_('Permission denied.'));
420 $res = db_query_params('
422 SET type_id=$1, unix_box=$2, http_domain=$3
429 if (!$res || db_affected_rows($res) < 1) {
430 $this->setError(_('ERROR: DB: Could not change group properties: %s'),db_error());
435 // Log the audit trail
436 if ($type_id != $this->data_array['type_id']) {
437 $this->addHistory('type_id', $this->data_array['type_id']);
439 if ($unix_box != $this->data_array['unix_box']) {
440 $this->addHistory('unix_box', $this->data_array['unix_box']);
442 if ($http_domain != $this->data_array['http_domain']) {
443 $this->addHistory('http_domain', $this->data_array['http_domain']);
446 if (!$this->fetchData($this->getID())) {
455 * update - Update number of common properties.
457 * Unlike updateAdmin(), this function accessible to project admin.
459 * @param object User requesting operation (for access control).
460 * @param boolean Whether group is publicly accessible (0/1).
461 * @param string Project's license (string ident).
462 * @param int Group type (1-project, 2-foundry).
463 * @param string Machine on which group's home directory located.
464 * @param string Domain which serves group's WWW.
465 * @return int status.
468 function update(&$user, $group_name, $homepage, $short_description, $use_mail, $use_survey, $use_forum,
469 $use_pm, $use_pm_depend_box, $use_scm, $use_news, $use_docman,
470 $new_doc_address, $send_all_docs, $logo_image_id,
471 $use_ftp, $use_tracker, $use_frs, $use_stats, $tags, $is_public) {
473 $perm =& $this->getPermission();
475 if (!$perm || !is_object($perm)) {
476 $this->setError(_('Could not get permission.'));
480 if (!$perm->isAdmin()) {
481 $this->setError(_('Permission denied.'));
485 // Validate some values
486 if ($this->getPublicName() != $group_name) {
487 if (!$this->validateGroupName($group_name)) {
492 if ($new_doc_address) {
493 $invalid_mails = validate_emails($new_doc_address);
494 if (count($invalid_mails) > 0) {
495 $this->setError(sprintf(ngettext('New Doc Address Appeared Invalid: %s', 'New Doc Addresses Appeared Invalid: %s', count($invalid_mails)),implode(',',$invalid_mails)));
500 // in the database, these all default to '1',
501 // so we have to explicity set 0
514 if (!$use_pm_depend_box) {
515 $use_pm_depend_box = 0;
538 if (!$send_all_docs) {
542 $homepage = ltrim($homepage);
544 $homepage = util_make_url('/projects/' . $this->getUnixName() . '/');
547 if (strlen(htmlspecialchars($short_description))>255) {
548 $this->setError(_('Error updating project information: Maximum length for Project Description is 255 chars.'));
554 //XXX not yet actived logo_image_id='$logo_image_id',
555 $res = db_query_params('UPDATE groups
558 short_description=$3,
563 use_pm_depend_box=$8,
573 array(htmlspecialchars($group_name),
575 htmlspecialchars($short_description),
592 $this->setError(sprintf(_('Error updating project information: %s'), db_error()));
597 if (!$this->setUseDocman($use_docman)) {
598 $this->setError(sprintf(_('Error updating project information: use_docman %s'), db_error()));
603 if ($this->setTags($tags) === false) {
608 $hook_params = array();
609 $hook_params['group'] = $this;
610 $hook_params['group_id'] = $this->getID();
611 $hook_params['group_homepage'] = $homepage;
612 $hook_params['group_name'] = htmlspecialchars($group_name);
613 $hook_params['group_description'] = htmlspecialchars($short_description);
614 $hook_params['group_ispublic'] = $is_public;
615 if (!plugin_hook("group_update", $hook_params)) {
616 if (!$this->isError()) {
617 $this->setError(_('Error updating project information in plugin_hook group_update'));
623 // Log the audit trail
624 $this->addHistory('Changed Public Info', '');
626 if (!$this->fetchData($this->getID())) {
635 * getID - Simply return the group_id for this object.
637 * @return int group_id.
640 return $this->data_array['group_id'];
644 * getType() - Foundry, project, etc.
646 * @return int The type flag from the database.
649 return $this->data_array['type_id'];
654 * getStatus - the status code.
656 * Statuses char include I,H,A,D,P.
657 * TODO : document what these mean :
664 function getStatus() {
665 return $this->data_array['status'];
669 * setStatus - set the status code.
671 * Statuses include I,H,A,D,P.
672 * TODO : document what these mean :
679 * @param object User requesting operation (for access control).
680 * @param string Status value.
681 * @return boolean success.
684 function setStatus(&$user, $status) {
687 if (!forge_check_global_perm('approve_projects')) {
688 $this->setPermissionDeniedError();
692 // Projects in 'A' status can only go to 'H' or 'D'
693 // Projects in 'D' status can only go to 'A'
694 // Projects in 'P' status can only go to 'A' OR 'D'
695 // Projects in 'I' status can only go to 'P'
696 // Projects in 'H' status can only go to 'A' OR 'D'
697 $allowed_status_changes = array(
698 'AH'=>1,'AD'=>1,'DA'=>1,'PA'=>1,'PD'=>1,
699 'IP'=>1,'HA'=>1,'HD'=>1
702 // Check that status transition is valid
703 if ($this->getStatus() != $status
704 && !$allowed_status_changes[$this->getStatus().$status]) {
705 $this->setError(_('Invalid Status Change'));
711 $res = db_query_params('UPDATE groups
713 WHERE group_id=$2', array($status, $this->getID()));
715 if (!$res || db_affected_rows($res) < 1) {
716 $this->setError(sprintf(_('ERROR: DB: Could not change group status: %s'),db_error()));
722 // Activate system group, if not yet
723 if (!$SYS->sysCheckGroup($this->getID())) {
724 if (!$SYS->sysCreateGroup($this->getID())) {
725 $this->setError($SYS->getErrorMessage());
730 if (!$this->activateUsers()) {
735 /* Otherwise, the group is not active, and make sure that
736 System group is not active either */
737 } else if ($SYS->sysCheckGroup($this->getID())) {
738 if (!$SYS->sysRemoveGroup($this->getID())) {
739 $this->setError($SYS->getErrorMessage());
745 $hook_params = array();
746 $hook_params['group'] = $this;
747 $hook_params['group_id'] = $this->getID();
748 $hook_params['status'] = $status;
749 plugin_hook("group_setstatus", $hook_params);
753 // Log the audit trail
754 if ($status != $this->getStatus()) {
755 $this->addHistory('Status', $this->getStatus());
758 $this->data_array['status'] = $status;
763 * isProject - Simple boolean test to see if it's a project or not.
765 * @return boolean is_project.
767 function isProject() {
768 if ($this->getType()==1) {
776 * isPublic - Wrapper around RBAC to check if a project is anonymously readable
778 * @return boolean is_public.
780 function isPublic() {
781 $ra = RoleAnonymous::getInstance() ;
782 return $ra->hasPermission('project_read', $this->getID());
786 * isActive - Database field status of 'A' returns true.
788 * @return boolean is_active.
790 function isActive() {
791 if ($this->getStatus()=='A') {
799 * isTemplate - Simply returns the is_template flag from the database.
801 * @return boolean is_template.
803 function isTemplate() {
804 return $this->data_array['is_template'];
808 * setAsTemplate - Set the template status of a project
810 * @param boolean is_template.
812 function setAsTemplate($booleanparam) {
814 $booleanparam = $booleanparam ? 1 : 0;
815 $res = db_query_params('UPDATE groups SET is_template=$1 WHERE group_id=$2',
816 array($booleanparam, $this->getID()));
818 $this->data_array['is_template']=$booleanparam;
828 * getTemplateProject - Return the project template this project is built from
830 * @return object The template project
832 function getTemplateProject() {
833 return group_get_object($this->data_array['built_from_template']);
837 * getUnixName - the unix_name
839 * @return string unix_name.
841 function getUnixName() {
842 return strtolower($this->data_array['unix_group_name']);
846 * getPublicName - the full-length public name.
848 * @return string The group_name.
850 function getPublicName() {
851 return $this->data_array['group_name'];
855 * getRegisterPurpose - the text description of the purpose of this project.
857 * @return string The description.
859 function getRegisterPurpose() {
860 return $this->data_array['register_purpose'];
864 * getDescription - the text description of this project.
866 * @return string The description.
868 function getDescription() {
869 return $this->data_array['short_description'];
873 * getStartDate - the unix time this project was registered.
875 * @return int (unix time) of registration.
877 function getStartDate() {
878 return $this->data_array['register_time'];
882 * getLogoImageID - the id of the logo in the database for this project.
884 * @return int The ID of logo image in db_images table (or 100 if none).
886 function getLogoImageID() {
887 return $this->data_array['logo_image_id'];
891 * getUnixBox - the hostname of the unix box where this project is located.
893 * @return string The name of the unix machine for the group.
895 function getUnixBox() {
896 return $this->data_array['unix_box'];
900 * getSCMBox - the hostname of the scm box where this project is located.
902 * @return string The name of the unix machine for the group.
904 function getSCMBox() {
905 return $this->data_array['scm_box'];
908 * setSCMBox - the hostname of the scm box where this project is located.
910 * @param string The name of the new SCM_BOX
912 function setSCMBox($scm_box) {
914 if ($scm_box == $this->data_array['scm_box']) {
919 $res = db_query_params('UPDATE groups SET scm_box=$1 WHERE group_id=$2', array($scm_box, $this->getID ()));
921 $this->addHistory('scm_box', $this->data_array['scm_box']);
922 $this->data_array['scm_box'] = $scm_box;
927 $this->setError(_("Couldn't insert SCM_BOX to database"));
931 $this->setError(_("SCM Box can't be empty"));
937 * getDomain - the hostname.domain where their web page is located.
939 * @return string The name of the group [web] domain.
941 function getDomain() {
942 return $this->data_array['http_domain'];
946 * getRegistrationPurpose - the text description of the purpose of this project.
948 * @return string The application for project hosting.
950 function getRegistrationPurpose() {
951 return $this->data_array['register_purpose'];
956 * getAdmins() - Get array of Admin user objects.
958 * @return array Array of User objects.
960 function &getAdmins() {
961 $roles = RBACEngine::getInstance()->getRolesByAllowedAction ('project_admin', $this->getID());
965 foreach ($roles as $role) {
966 if (! ($role instanceof RoleExplicit)) {
969 if ($role->getHomeProject() == NULL
970 || $role->getHomeProject()->getID() != $this->getID()) {
974 foreach ($role->getUsers() as $u) {
975 $user_ids[] = $u->getID();
978 return user_get_objects(array_unique($user_ids));
982 Common Group preferences for tools
986 * enableAnonSCM - whether or not this group has opted to enable Anonymous SCM.
988 * @return boolean enable_scm.
990 function enableAnonSCM() {
992 $r = RoleAnonymous::getInstance();
993 return $r->hasPermission('scm', $this->getID(), 'read');
995 if ($this->isPublic() && $this->usesSCM()) {
996 return $this->data_array['enable_anonscm'];
1003 function SetUsesAnonSCM($booleanparam) {
1005 $booleanparam = $booleanparam ? 1 : 0;
1007 $r = RoleAnonymous::getInstance();
1008 $r->setSetting('scm', $this->getID(), $booleanparam);
1011 $res = db_query_params('UPDATE groups SET enable_anonscm=$1 WHERE group_id=$2',
1012 array($booleanparam, $this->getID()));
1014 $this->data_array['enable_anonscm'] = $booleanparam;
1024 * enablePserver - whether or not this group has opted to enable Pserver.
1026 * @return boolean enable_pserver.
1028 function enablePserver() {
1029 if ($this->usesSCM()) {
1030 return $this->data_array['enable_pserver'];
1036 function SetUsesPserver($booleanparam) {
1038 $booleanparam = $booleanparam ? 1 : 0;
1039 $res = db_query_params('UPDATE groups SET enable_pserver=$1 WHERE group_id=$2',
1040 array($booleanparam, $this->getID()));
1042 $this->data_array['enable_pserver'] = $booleanparam;
1051 * usesSCM - whether or not this group has opted to use SCM.
1053 * @return boolean uses_scm.
1055 function usesSCM() {
1056 if (forge_get_config('use_scm')) {
1057 return $this->data_array['use_scm'];
1064 * setUseSCM - Set the SCM usage
1066 * @param boolean enabled/disabled
1068 function setUseSCM($booleanparam) {
1070 $booleanparam = $booleanparam ? 1 : 0 ;
1071 $res = db_query_params('UPDATE groups SET use_scm=$1 WHERE group_id=$2',
1072 array($booleanparam, $this->getID()));
1074 $this->data_array['use_scm']=$booleanparam;
1084 * usesMail - whether or not this group has opted to use mailing lists.
1086 * @return boolean uses_mail.
1088 function usesMail() {
1089 if (forge_get_config('use_mail')) {
1090 return $this->data_array['use_mail'];
1097 * setUseMail - Set the mailing-list usage
1099 * @param boolean enabled/disabled
1101 function setUseMail($booleanparam) {
1103 $booleanparam = $booleanparam ? 1 : 0 ;
1104 $res = db_query_params('UPDATE groups SET use_mail=$1 WHERE group_id=$2',
1105 array($booleanparam, $this->getID()));
1107 $this->data_array['use_mail']=$booleanparam;
1117 * usesNews - whether or not this group has opted to use news.
1119 * @return boolean uses_news.
1121 function usesNews() {
1122 if (forge_get_config('use_news')) {
1123 return $this->data_array['use_news'];
1130 * usesForum - whether or not this group has opted to use discussion forums.
1132 * @return boolean uses_forum.
1134 function usesForum() {
1135 if (forge_get_config('use_forum')) {
1136 return $this->data_array['use_forum'];
1143 * setUseForum - Set the forum usage
1145 * @param boolean enabled/disabled
1147 function setUseForum($booleanparam) {
1149 $booleanparam = $booleanparam ? 1 : 0;
1150 $res = db_query_params('UPDATE groups SET use_forum=$1 WHERE group_id=$2',
1151 array($booleanparam, $this->getID()));
1153 $this->data_array['use_forum']=$booleanparam;
1163 * usesStats - whether or not this group has opted to use stats.
1165 * @return boolean uses_stats.
1167 function usesStats() {
1168 return $this->data_array['use_stats'];
1172 * usesFRS - whether or not this group has opted to use file release system.
1174 * @return boolean uses_frs.
1176 function usesFRS() {
1177 if (forge_get_config('use_frs')) {
1178 return $this->data_array['use_frs'];
1185 * setUseFRS - Set the FRS usage
1187 * @param boolean enabled/disabled
1189 function setUseFRS($booleanparam) {
1191 $booleanparam = $booleanparam ? 1 : 0;
1192 $res = db_query_params('UPDATE groups SET use_frs=$1 WHERE group_id=$2',
1193 array ($booleanparam, $this->getID()));
1195 $this->data_array['use_frs']=$booleanparam;
1205 * usesTracker - whether or not this group has opted to use tracker.
1207 * @return boolean uses_tracker.
1209 function usesTracker() {
1210 if (forge_get_config('use_tracker')) {
1211 return $this->data_array['use_tracker'];
1218 * setUseTracker - Set the tracker usage
1220 * @param boolean enabled/disabled
1222 function setUseTracker ($booleanparam) {
1224 $booleanparam = $booleanparam ? 1 : 0 ;
1225 $res = db_query_params ('UPDATE groups SET use_tracker=$1 WHERE group_id=$2',
1226 array ($booleanparam, $this->getID()));
1228 $this->data_array['use_tracker']=$booleanparam;
1238 * useCreateOnline - whether or not this group has opted to use create online documents option.
1240 * @return boolean use_docman_create_online.
1242 function useCreateOnline() {
1243 if (forge_get_config('use_docman')) {
1244 return $this->data_array['use_docman_create_online'];
1251 * usesDocman - whether or not this group has opted to use docman.
1253 * @return boolean use_docman.
1255 function usesDocman() {
1256 if (forge_get_config('use_docman')) {
1257 return $this->data_array['use_docman'];
1264 * setUseDocman - Set the docman usage
1266 * @param boolean enabled/disabled
1268 function setUseDocman($booleanparam) {
1270 $booleanparam = $booleanparam ? 1 : 0;
1271 $res = db_query_params('UPDATE groups SET use_docman = $1 WHERE group_id = $2',
1272 array($booleanparam, $this->getID()));
1274 // check if / doc_group exists, if not create it
1275 $trashdir = db_query_params('select groupname from doc_groups where groupname = $1 and group_id = $2',
1276 array('.trash', $this->getID()));
1277 if ($trashdir && db_numrows($trashdir) == 0) {
1278 $resinsert = db_query_params('insert into doc_groups (groupname, group_id, stateid) values ($1, $2, $3)',
1279 array('.trash', $this->getID(), '2'));
1285 $this->data_array['use_docman'] = $booleanparam;
1295 * useDocmanSearch - whether or not this group has opted to use docman search engine.
1297 * @return boolean use_docman_search.
1299 function useDocmanSearch() {
1300 if (forge_get_config('use_docman')) {
1301 return $this->data_array['use_docman_search'];
1308 * useWebdav - whether or not this group has opted to use webdav interface.
1310 * @return boolean use_docman_search.
1312 function useWebdav() {
1313 if (forge_get_config('use_webdav')) {
1314 return $this->data_array['use_webdav'];
1321 * usesFTP - whether or not this group has opted to use FTP.
1323 * @return boolean uses_ftp.
1325 function usesFTP() {
1326 if (forge_get_config('use_ftp')) {
1327 return $this->data_array['use_ftp'];
1334 * usesSurvey - whether or not this group has opted to use surveys.
1336 * @return boolean uses_survey.
1338 function usesSurvey() {
1339 if (forge_get_config('use_survey')) {
1340 return $this->data_array['use_survey'];
1347 * usesPM - whether or not this group has opted to Project Manager.
1349 * @return boolean uses_projman.
1352 if (forge_get_config('use_pm')) {
1353 return $this->data_array['use_pm'];
1360 * setUsePM - Set the PM usage
1362 * @param boolean enabled/disabled
1364 function setUsePM($booleanparam) {
1366 $booleanparam = $booleanparam ? 1 : 0;
1367 $res = db_query_params('UPDATE groups SET use_pm=$1 WHERE group_id=$2',
1368 array($booleanparam, $this->getID()));
1370 $this->data_array['use_pm']=$booleanparam;
1380 * getPlugins - get a list of all available group plugins
1382 * @return array array containing plugin_id => plugin_name
1384 function getPlugins() {
1385 if (!isset($this->plugins_data)) {
1386 $this->plugins_data = array();
1387 $res = db_query_params('SELECT group_plugin.plugin_id, plugins.plugin_name
1388 FROM group_plugin, plugins
1389 WHERE group_plugin.group_id=$1
1390 AND group_plugin.plugin_id=plugins.plugin_id', array($this->getID()));
1391 $rows = db_numrows($res);
1393 for ($i=0; $i<$rows; $i++) {
1394 $plugin_id = db_result($res, $i, 'plugin_id');
1395 $this->plugins_data[$plugin_id] = db_result($res, $i, 'plugin_name');
1398 return $this->plugins_data;
1402 * usesPlugin - returns true if the group uses a particular plugin
1404 * @param string name of the plugin
1405 * @return boolean whether plugin is being used or not
1407 function usesPlugin($pluginname) {
1408 $plugins_data = $this->getPlugins();
1409 foreach ($plugins_data as $p_id => $p_name) {
1410 if ($p_name == $pluginname) {
1418 * added for Codendi compatibility
1419 * usesServices - returns true if the group uses a particular plugin or feature
1421 * @param string name of the plugin
1422 * @return boolean whether plugin is being used or not
1424 function usesService($feature) {
1425 $plugins_data = $this->getPlugins();
1426 $pm = plugin_manager_get_object();
1427 foreach ($plugins_data as $p_id => $p_name) {
1428 if ($p_name == $feature) {
1431 if ($pm->getPluginByName($p_name)->provide($feature)) {
1439 * setPluginUse - enables/disables plugins for the group
1441 * @param string name of the plugin
1442 * @param boolean the new state
1443 * @return string database result
1445 function setPluginUse($pluginname, $val=true) {
1446 if ($val == $this->usesPlugin($pluginname)) {
1447 // State is already good, returning
1450 $res = db_query_params('SELECT plugin_id FROM plugins WHERE plugin_name=$1',
1451 array($pluginname));
1452 $rows = db_numrows($res);
1454 // Error: no plugin by that name
1457 $plugin_id = db_result($res,0,'plugin_id');
1459 unset($this->plugins_data);
1461 $res = db_query_params('INSERT INTO group_plugin (group_id, plugin_id) VALUES ($1, $2)',
1462 array($this->getID(),
1466 $res = db_query_params('DELETE FROM group_plugin WHERE group_id=$1 AND plugin_id=$2',
1467 array($this->getID(),
1474 * getDocEmailAddress - get email address(es) to send doc notifications to.
1476 * @return string email address.
1478 function getDocEmailAddress() {
1479 return $this->data_array['new_doc_address'];
1483 * DocEmailAll - whether or not this group has opted to use receive notices on all doc updates.
1485 * @return boolean email_on_all_doc_updates.
1487 function docEmailAll() {
1488 return $this->data_array['send_all_docs'];
1493 * getHomePage - The URL for this project's home page.
1495 * @return string homepage URL.
1497 function getHomePage() {
1498 return $this->data_array['homepage'];
1502 * getTags - Tags of this project.
1504 * @return string List of tags. Comma separated
1506 function getTags() {
1507 $sql = 'SELECT name FROM project_tags WHERE group_id = $1';
1508 $res = db_query_params($sql, array($this->getID()));
1509 return join(', ', util_result_column_to_array($res));
1513 * setTags - Set tags of this project.
1515 * @return string database result.
1517 function setTags($tags) {
1519 $sql = 'DELETE FROM project_tags WHERE group_id=$1';
1520 $res = db_query_params($sql, array($this->getID()));
1522 $this->setError('Deleting old tags: '.db_error());
1526 $inserted = array();
1527 $tags_array = preg_split('/[;,]/', $tags);
1528 foreach ($tags_array as $tag) {
1529 $tag = preg_replace('/[\t\r\n]/', ' ', $tag);
1530 // Allowed caracteres: [A-Z][a-z][0-9] -_&'#+.
1531 if (preg_match('/[^[:alnum:]| |\-|_|\&|\'|#|\+|\.]/', $tag)) {
1532 $this->setError(_('Bad tag name, you only can use the following characters: [A-Z][a-z][0-9]-_&\'#+. and space'));
1537 if ($tag == '' || array_search($tag, $inserted) !== false) continue;
1538 $sql = 'INSERT INTO project_tags (group_id,name) VALUES ($1, $2)';
1539 $res = db_query_params($sql, array($this->getID(), $tag));
1541 $this->setError(_('Setting tags: ').db_error());
1552 * getPermission - Return a Permission for this Group
1554 * @return object The Permission.
1556 function &getPermission() {
1557 return permission_get_object($this);
1561 function delete($sure, $really_sure, $really_really_sure) {
1562 if (!$sure || !$really_sure || !$really_really_sure) {
1563 $this->setMissingParamsError(_('Please tick all checkboxes.'));
1566 if ($this->getID() == forge_get_config('news_group') ||
1567 $this->getID() == 1 ||
1568 $this->getID() == forge_get_config('stats_group') ||
1569 $this->getID() == forge_get_config('peer_rating_group')) {
1570 $this->setError(_('Cannot Delete System Group'));
1573 $perm =& $this->getPermission();
1574 if (!$perm || !is_object($perm)) {
1575 $this->setPermissionDeniedError();
1577 } elseif ($perm->isError()) {
1578 $this->setPermissionDeniedError();
1580 } elseif (!$perm->isSuperUser()) {
1581 $this->setPermissionDeniedError();
1587 // Remove all the members
1589 $members =& $this->getMembers();
1590 foreach ($members as $i) {
1591 if(!$this->removeUser($i->getID())) {
1592 $this->setError(_('Could not properly remove member:').' '.$i->getID());
1596 // Failsafe until user_group table is gone
1597 $res = db_query_params('DELETE FROM user_group WHERE group_id=$1',
1598 array($this->getID()));
1600 // unlink roles from this project
1601 $ra = RoleAnonymous::getInstance();
1602 $rl = RoleLoggedIn::getInstance();
1603 $ra->unlinkProject($this);
1604 $rl->unlinkProject($this);
1605 // @todo : unlink all the other roles created in the project...
1610 $atf = new ArtifactTypeFactory($this);
1611 $at_arr =& $atf->getArtifactTypes();
1612 foreach ($at_arr as $i) {
1613 if (!is_object($i)) {
1616 if (!$i->delete(1,1)) {
1617 $this->setError(_('Could not properly delete the tracker:').' '.$i->getErrorMessage());
1624 $ff = new ForumFactory($this);
1625 $f_arr =& $ff->getForums();
1626 foreach ($f_arr as $i) {
1627 if (!is_object($i)) {
1630 if(!$i->delete(1,1)) {
1631 $this->setError(_('Could not properly delete the forum:').' '.$i->getErrorMessage());
1636 // Delete Subprojects
1638 $pgf = new ProjectGroupFactory($this);
1639 $pg_arr =& $pgf->getProjectGroups();
1640 foreach ($pg_arr as $i) {
1641 if (!is_object($i)) {
1644 if (!$i->delete(1,1)) {
1645 $this->setError(_('Could not properly delete the ProjectGroup:').' '.$i->getErrorMessage());
1650 // Delete FRS Packages
1652 $res = db_query_params('SELECT * FROM frs_package WHERE group_id=$1',
1653 array($this->getID()));
1654 while ($arr = db_fetch_array($res)) {
1655 $frsp=new FRSPackage($this, $arr['package_id'], $arr);
1656 if (!$frsp->delete(1, 1)) {
1657 $this->setError(_('Could not properly delete the FRSPackage:').' '.$frsp->getErrorMessage());
1664 $news_group=group_get_object(forge_get_config('news_group'));
1665 $res = db_query_params('SELECT forum_id FROM news_bytes WHERE group_id=$1',
1666 array($this->getID()));
1668 $this->setError(_('Error Deleting News: ').db_error());
1673 for ($i=0; $i<db_numrows($res); $i++) {
1674 $Forum = new Forum($news_group,db_result($res,$i,'forum_id'));
1675 if (!$Forum->delete(1,1)) {
1676 $this->setError(_("Could Not Delete News Forum: %d"),$Forum->getID());
1680 $res = db_query_params('DELETE FROM news_bytes WHERE group_id=$1',
1681 array($this->getID()));
1683 $this->setError(_('Error Deleting News: ').db_error());
1691 $res = db_query_params('DELETE FROM doc_data WHERE group_id=$1',
1692 array($this->getID()));
1694 $this->setError(_('Error Deleting Documents: ').db_error());
1699 $res = db_query_params('DELETE FROM doc_groups WHERE group_id=$1',
1700 array($this->getID()));
1702 $this->setError(_('Error Deleting Documents: ').db_error());
1710 $res=db_query_params('DELETE FROM project_tags WHERE group_id=$1', array($this->getID()));
1712 $this->setError(_('Error Deleting Tags: ').db_error());
1718 // Delete group history
1720 $res = db_query_params('DELETE FROM group_history WHERE group_id=$1',
1721 array($this->getID()));
1723 $this->setError(_('Error Deleting Project History: ').db_error());
1729 // Delete group plugins
1731 $res = db_query_params('DELETE FROM group_plugin WHERE group_id=$1',
1732 array($this->getID()));
1734 $this->setError(_('Error Deleting Project Plugins: ').db_error());
1740 // Delete group cvs stats
1742 $res = db_query_params ('DELETE FROM stats_cvs_group WHERE group_id=$1',
1743 array ($this->getID())) ;
1745 $this->setError(_('Error Deleting SCM Statistics: ').db_error());
1753 $sf = new SurveyFactory($this);
1754 $s_arr =& $sf->getSurveys();
1755 foreach ($s_arr as $i) {
1756 if (!is_object($i)) {
1759 if (!$i->delete()) {
1760 $this->setError(_('Could not properly delete the survey'));
1765 // Delete SurveyQuestions
1767 $sqf = new SurveyQuestionFactory($this);
1768 $sq_arr =& $sqf->getSurveyQuestions();
1769 foreach ($sq_arr as $i) {
1770 if (!is_object($i)) {
1773 if (!$i->delete()) {
1774 $this->setError(_('Could not properly delete the survey questions'));
1779 // Delete Mailing List Factory
1781 $mlf = new MailingListFactory($this);
1782 $ml_arr = $mlf->getMailingLists();
1783 foreach ($ml_arr as $i) {
1784 if (!is_object($i)) {
1787 if (!$i->delete(1,1)) {
1788 $this->setError(_('Could not properly delete the mailing list'));
1795 $res = db_query_params('DELETE FROM trove_group_link WHERE group_id=$1',
1796 array($this->getID()));
1798 $this->setError(_('Error Deleting Trove: ').db_error());
1803 $res = db_query_params('DELETE FROM trove_agg WHERE group_id=$1',
1804 array($this->getID()));
1806 $this->setError(_('Error Deleting Trove: ').db_error());
1814 $res = db_query_params('DELETE FROM project_sums_agg WHERE group_id=$1',
1815 array($this->getID()));
1817 $this->setError(_('Error Deleting Counters: ').db_error());
1822 $res = db_query_params('INSERT INTO deleted_groups (unix_group_name, delete_date, isdeleted) VALUES ($1, $2, $3)',
1823 array($this->getUnixName(),
1827 $this->setError(_('Error Deleting Project:').' '.db_error());
1832 $res = db_query_params('DELETE FROM groups WHERE group_id=$1',
1833 array($this->getID()));
1835 $this->setError(_('Error Deleting Project:').' '.db_error());
1842 $hook_params = array();
1843 $hook_params['group'] = $this;
1844 $hook_params['group_id'] = $this->getID();
1845 plugin_hook("group_delete", $hook_params);
1847 if (forge_get_config('upload_dir') != '' && $this->getUnixName()) {
1848 exec('/bin/rm -rf '.forge_get_config('upload_dir').'/'.$this->getUnixName().'/');
1850 if (forge_get_config('ftp_upload_dir') != '' && $this->getUnixName()) {
1851 exec('/bin/rm -rf '.forge_get_config('ftp_upload_dir').'/'.$this->getUnixName().'/');
1856 $res = db_query_params('DELETE FROM rep_group_act_monthly WHERE group_id=$1',
1857 array ($this->getID()));
1858 //echo 'rep_group_act_monthly'.db_error();
1859 $res = db_query_params('DELETE FROM rep_group_act_weekly WHERE group_id=$1',
1860 array ($this->getID()));
1861 //echo 'rep_group_act_weekly'.db_error();
1862 $res = db_query_params('DELETE FROM rep_group_act_daily WHERE group_id=$1',
1863 array ($this->getID()));
1864 //echo 'rep_group_act_daily'.db_error();
1865 unset($this->data_array);
1870 Basic functions to add/remove users to/from a group
1871 and update their permissions
1875 * addUser - controls adding a user to a group.
1877 * @param string Unix name of the user to add OR integer user_id.
1878 * @param int The role_id this user should have.
1879 * @return boolean success.
1882 function addUser($user_identifier,$role_id) {
1885 Admins can add users to groups
1888 if (!forge_check_perm ('project_admin', $this->getID())) {
1889 $this->setPermissionDeniedError();
1895 get user id for this user's unix_name
1897 if (is_int ($user_identifier)) { // user_id or user_name
1898 $res_newuser = db_query_params ('SELECT * FROM users WHERE user_id=$1', array ($user_identifier)) ;
1900 $res_newuser = db_query_params ('SELECT * FROM users WHERE user_name=$1', array ($user_identifier)) ;
1902 if (db_numrows($res_newuser) > 0) {
1904 // make sure user is active
1906 if (db_result($res_newuser,0,'status') != 'A') {
1907 $this->setError(_('User is not active. Only active users can be added.'));
1913 // user was found - set new user_id var
1915 $user_id = db_result($res_newuser,0,'user_id');
1917 $role = new Role($this, $role_id);
1918 if (!$role || !is_object($role)) {
1919 $this->setError(_('Error Getting Role Object'));
1922 } elseif ($role->isError()) {
1923 $this->setError('addUser::roleget::'.$role->getErrorMessage());
1929 $role->addUser(user_get_object($user_id)) ;
1930 if (!$SYS->sysCheckCreateGroup($this->getID())){
1931 $this->setError($SYS->getErrorMessage());
1935 if (!$SYS->sysCheckCreateUser($user_id)) {
1936 $this->setError($SYS->getErrorMessage());
1940 if (!$SYS->sysGroupCheckUser($this->getID(),$user_id)) {
1941 $this->setError($SYS->getErrorMessage());
1945 } else { // NOT USE_PFO_RBAC
1948 // if not already a member, add them
1950 $res_member = db_query_params('SELECT user_id
1952 WHERE user_id=$1 AND group_id=$2',
1953 array($user_id, $this->getID()));
1955 if (db_numrows($res_member) < 1) {
1957 // Create this user's row in the user_group table
1959 $res = db_query_params('INSERT INTO user_group
1960 (user_id,group_id,admin_flags,forum_flags,project_flags,
1961 doc_flags,cvs_flags,member_role,release_flags,artifact_flags)
1962 VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10)',
1974 //verify the insert worked
1975 if (!$res || db_affected_rows($res) < 1) {
1976 $this->setError(sprintf(_('ERROR: Could Not Add User To Group: %s'),db_error()));
1981 // check and create if group doesn't exists
1983 //echo "<h2>Group::addUser SYS->sysCheckCreateGroup(".$this->getID().")</h2>";
1984 if (!$SYS->sysCheckCreateGroup($this->getID())){
1985 $this->setError($SYS->getErrorMessage());
1990 // check and create if user doesn't exists
1992 //echo "<h2>Group::addUser SYS->sysCheckCreateUser($user_id)</h2>";
1993 if (!$SYS->sysCheckCreateUser($user_id)) {
1994 $this->setError($SYS->getErrorMessage());
2001 //echo "<h2>Group::addUser role->setUser($user_id)</h2>";
2002 if (!$role->setUser($user_id)) {
2003 $this->setError('addUser::role::setUser'.$role->getErrorMessage());
2009 // user was already a member
2010 // make sure they are set up
2012 $user= user_get_object($user_id,$res_newuser);
2013 $user->fetchData($user->getID());
2014 $role = new Role($this,$role_id);
2015 if (!$role || !is_object($role)) {
2016 $this->setError(_('Error Getting Role Object'));
2019 } elseif ($role->isError()) {
2020 $this->setError('addUser::roleget::'.$role->getErrorMessage());
2024 //echo "<h2>Already Member Group::addUser role->setUser($user_id)</h2>";
2025 if (!$role->setUser($user_id)) {
2026 $this->setError('addUser::role::setUser'.$role->getErrorMessage());
2031 // set up their system info
2033 //echo "<h2>Already Member Group::addUser SYS->sysCheckCreateUser($user_id)</h2>";
2034 if (!$SYS->sysCheckCreateUser($user_id)) {
2035 $this->setError($SYS->getErrorMessage());
2043 // user doesn't exist
2045 $this->setError(_('ERROR: User does not exist'));
2050 $hook_params['group'] = $this;
2051 $hook_params['group_id'] = $this->getID();
2052 $hook_params['user'] = &user_get_object($user_id);
2053 $hook_params['user_id'] = $user_id;
2054 plugin_hook ("group_adduser", $hook_params);
2059 $this->addHistory('Added User',$user_identifier);
2065 * removeUser - controls removing a user from a group.
2067 * Users can remove themselves.
2069 * @param int The ID of the user to remove.
2070 * @return boolean success.
2072 function removeUser($user_id) {
2075 if ($user_id != user_getid()
2076 || !forge_check_perm('project_admin', $this->getID())) {
2077 $this->setPermissionDeniedError();
2084 $user = user_get_object($user_id);
2085 $roles = RBACEngine::getInstance()->getAvailableRolesForUser($user);
2087 foreach ($roles as $role) {
2088 if ($role->getHomeProject() && $role->getHomeProject()->getID() == $this->getID()) {
2089 $found_role = $role;
2093 if ($found_role == NULL) {
2094 $this->setError(sprintf(_('ERROR: User not removed: %s')));
2098 $found_role->removeUser($user);
2099 if (!$SYS->sysGroupCheckUser($this->getID(), $user_id)) {
2100 $this->setError($SYS->getErrorMessage());
2106 $res = db_query_params('DELETE FROM user_group WHERE group_id=$1 AND user_id=$2',
2107 array($this->getID(),
2109 if (!$res || db_affected_rows($res) < 1) {
2110 $this->setError(_('ERROR: User not removed:').' '.db_error());
2117 // reassign open artifacts to id=100
2119 $res = db_query_params('UPDATE artifact SET assigned_to=100
2120 WHERE group_artifact_id
2121 IN (SELECT group_artifact_id
2122 FROM artifact_group_list
2123 WHERE group_id=$1 AND status_id=1 AND assigned_to=$2)',
2124 array($this->getID(),
2127 $this->setError(_('ERROR: DB: artifact:').' '.db_error());
2133 // reassign open tasks to id=100
2134 // first have to purge any assignments that would cause
2135 // conflict with existing assignment to 100
2137 $res = db_query_params('DELETE FROM project_assigned_to
2138 WHERE project_task_id IN (SELECT pt.project_task_id
2139 FROM project_task pt, project_group_list pgl, project_assigned_to pat
2140 WHERE pt.group_project_id = pgl.group_project_id
2141 AND pat.project_task_id=pt.project_task_id
2142 AND pt.status_id=1 AND pgl.group_id=$1
2143 AND pat.assigned_to_id=$2)
2144 AND assigned_to_id=100',
2145 array($this->getID(),
2148 $this->setError(sprintf(_('ERROR: DB: project_assigned_to %d: %s'), 1, db_error()));
2152 $res = db_query_params('UPDATE project_assigned_to SET assigned_to_id=100
2153 WHERE project_task_id IN (SELECT pt.project_task_id
2154 FROM project_task pt, project_group_list pgl
2155 WHERE pt.group_project_id = pgl.group_project_id
2156 AND pt.status_id=1 AND pgl.group_id=$1)
2157 AND assigned_to_id=$2',
2158 array($this->getID(),
2161 $this->setError(sprintf(_('ERROR: DB: project_assigned_to %d: %s'), 2, db_error()));
2167 // Remove user from system
2169 if (!$SYS->sysGroupRemoveUser($this->getID(), $user_id)) {
2170 $this->setError($SYS->getErrorMessage());
2175 $hook_params['group'] = $this;
2176 $hook_params['group_id'] = $this->getID();
2177 $hook_params['user'] = user_get_object($user_id);
2178 $hook_params['user_id'] = $user_id;
2179 plugin_hook ("group_removeuser", $hook_params);
2182 $this->addHistory('Removed User',$user_id);
2189 * updateUser - controls updating a user's role in this group.
2191 * @param int The ID of the user.
2192 * @param int The role_id to set this user to.
2193 * @return boolean success.
2195 function updateUser($user_id,$role_id) {
2198 if (!forge_check_perm ('project_admin', $this->getID())) {
2199 $this->setPermissionDeniedError();
2204 $newrole = RBACEngine::getInstance()->getRoleById ($role_id) ;
2205 if (!$newrole || !is_object($newrole)) {
2206 $this->setError(_('Could Not Get Role'));
2208 } elseif ($newrole->isError()) {
2209 $this->setError(sprintf(_('Role: %s'),$role->getErrorMessage()));
2211 } elseif ($newrole->getHomeProject() == NULL
2212 || $newrole->getHomeProject()->getID() != $this->getID()) {
2213 $this->setError(_('Wrong destination role'));
2216 $user = user_get_object ($user_id) ;
2217 $roles = RBACEngine::getInstance()->getAvailableRolesForUser ($user) ;
2218 $found_role = NULL ;
2219 foreach ($roles as $role) {
2220 if ($role->getHomeProject() && $role->getHomeProject()->getID() == $this->getID()) {
2221 $found_role = $role ;
2225 if ($found_role == NULL) {
2226 $this->setError(sprintf(_('ERROR: User not removed: %s')));
2230 $found_role->removeUser ($user) ;
2231 $newrole->addUser ($user) ;
2233 $role = new Role($this,$role_id);
2234 if (!$role || !is_object($role)) {
2235 $this->setError(_('Could Not Get Role'));
2237 } elseif ($role->isError()) {
2238 $this->setError(sprintf(_('Role: %s'),$role->getErrorMessage()));
2241 //echo "<h3>Group::updateUser role->setUser($user_id)</h3>";
2242 if (!$role->setUser($user_id)) {
2243 $this->setError(sprintf(_('Role: %s'),$role->getErrorMessage()));
2248 $this->addHistory('Updated User',$user_id);
2253 * addHistory - Makes an audit trail entry for this project.
2255 * @param string The name of the field.
2256 * @param string The Old Value for this $field_name.
2257 * @return database result handle.
2260 function addHistory($field_name, $old_value) {
2261 return db_query_params ('INSERT INTO group_history(group_id,field_name,old_value,mod_by,adddate)
2262 VALUES ($1,$2,$3,$4,$5)',
2263 array ($this->getID(),
2271 * activateUsers - Make sure that group members have unix accounts.
2273 * Setup unix accounts for group members. Can be called even
2274 * if members are already active.
2278 function activateUsers() {
2280 Activate member(s) of the project
2284 $members = $this->getUsers (true) ;
2286 foreach ($members as $member) {
2288 foreach (RBACEngine::getInstance()->getAvailableRolesForUser ($member) as $role) {
2289 if ($role->getHomeProject() && $role->getHomeProject()->getID() == $this->getID()) {
2292 if (!$this->addUser($member->getUnixName(),$role->getID())) {
2299 $res_member = db_query_params('SELECT user_id,role_id FROM user_group WHERE group_id=$1',
2300 array ($this->getID()));
2301 while ($row_member = db_fetch_array($res_member)) {
2302 $u = user_get_object($row_member['user_id']);
2303 if (!$this->addUser($u->getUnixName(),$row_member['role_id'])) {
2313 * getMembers - returns array of User objects for this project
2315 * @return array of User objects for this group.
2317 function getMembers() {
2318 return $this->getUsers (true) ;
2322 * replaceTemplateStrings - fill-in some blanks with project name
2324 * @param string Template string
2325 * @return string String after replacements
2327 function replaceTemplateStrings($string) {
2328 $string = str_replace ('UNIXNAME', $this->getUnixName(), $string) ;
2329 $string = str_replace ('PUBLICNAME', $this->getPublicName(), $string) ;
2330 $string = str_replace ('DESCRIPTION', $this->getDescription(), $string) ;
2335 * approve - Approve pending project.
2337 * @param object The User object who is doing the updating.
2340 function approve(&$user) {
2342 require_once $gfcommon.'widget/WidgetLayoutManager.class.php';
2344 if ($this->getStatus()=='A') {
2345 $this->setError(_("Group already active"));
2351 // Step 1: Activate group and create LDAP entries
2352 if (!$this->setStatus($user, 'A')) {
2357 // Switch to system language for item creation
2358 setup_gettext_from_sys_lang();
2360 // Create default roles
2362 $idadmin_group = NULL;
2363 foreach (get_group_join_requests ($this) as $gjr) {
2364 $idadmin_group = $gjr->getUserID();
2367 if ($idadmin_group == NULL) {
2368 $idadmin_group = $user->getID();
2371 $admin_group = db_query_params('SELECT user_id FROM user_group WHERE group_id=$1 AND admin_flags=$2',
2372 array($this->getID(),
2374 if (db_numrows($admin_group) > 0) {
2375 $idadmin_group = db_result($admin_group,0,'user_id');
2377 $idadmin_group = $user->getID();
2378 db_query_params('INSERT INTO user_group (user_id, group_id, admin_flags) VALUES ($1, $2, $3)',
2379 array($idadmin_group,
2385 $template = $this->getTemplateProject();
2386 $id_mappings = array();
2387 $seen_local_roles = false;
2389 // Copy roles from template project
2390 foreach($template->getRoles() as $oldrole) {
2391 if ($oldrole->getHomeProject() != NULL) {
2392 $role = new Role($this);
2394 // Need to use a different role name so that the permissions aren't set from the hardcoded defaults
2395 $role->create('TEMPORARY ROLE NAME', $data, true);
2396 $role->setName($oldrole->getName());
2397 $seen_local_roles = true;
2400 $role->linkProject($this);
2402 $id_mappings['role'][$oldrole->getID()] = $role->getID();
2403 // Reuse the project_admin permission
2404 $role->setSetting ('project_admin', $this->getID(), $oldrole->getSetting ('project_admin', $template->getID())) ;
2408 if (!$seen_local_roles) {
2409 $role = new Role($this);
2410 $adminperms = array ('project_admin' => array ($this->getID() => 1)) ;
2411 $role_id = $role->create ('Admin', $adminperms, true) ;
2415 $roles = $this->getRoles() ;
2416 foreach ($roles as $r) {
2417 if ($r->getSetting ('project_admin', $this->getID())) {
2418 $r->addUser(user_get_object ($idadmin_group));
2423 // Temporarily switch to the submitter's identity
2424 $saved_session = session_get_user();
2425 session_set_internal($idadmin_group);
2428 if (forge_get_config('use_tracker')) {
2429 $this->setUseTracker ($template->usesTracker());
2430 if ($template->usesTracker()) {
2431 $oldatf = new ArtifactTypeFactory($template);
2432 foreach ($oldatf->getArtifactTypes() as $o) {
2433 $t = new ArtifactType ($this) ;
2434 $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()) ;
2435 $id_mappings['tracker'][$o->getID()] = $t->getID();
2436 $t->cloneFieldsFrom ($o->getID());
2441 if (forge_get_config('use_pm')) {
2442 $this->setUsePM ($template->usesPM());
2443 if ($template->usesPM()) {
2444 $oldpgf = new ProjectGroupFactory($template);
2445 foreach ($oldpgf->getProjectGroups() as $o) {
2446 $pg = new ProjectGroup($this);
2447 $pg->create($this->replaceTemplateStrings($o->getName()),$this->replaceTemplateStrings($o->getDescription()),$o->isPublic(),$o->getSendAllPostsTo());
2448 $id_mappings['pm'][$o->getID()] = $pg->getID();
2453 if (forge_get_config('use_forum')) {
2454 $this->setUseForum($template->usesForum()) ;
2455 if ($template->usesForum()) {
2456 $oldff = new ForumFactory($template) ;
2457 foreach ($oldff->getForums() as $o) {
2458 $f = new Forum($this);
2459 $f->create($this->replaceTemplateStrings($o->getName()),$this->replaceTemplateStrings($o->getDescription()),$o->isPublic(),$o->getSendAllPostsTo(),1,$o->allowAnonymous(),$o->getModerationLevel());
2460 $id_mappings['forum'][$o->getID()] = $f->getID();
2465 if (forge_get_config('use_docman')) {
2466 $this->setUseDocman($template->usesDocman());
2467 if ($template->usesDocman()) {
2468 $olddgf = new DocumentGroupFactory($template);
2469 // First pass: create all docgroups
2470 $id_mappings['docman_docgroup'][0] = 0;
2471 foreach ($olddgf->getDocumentGroups() as $o) {
2472 $ndgf = new DocumentGroup($this);
2473 // .trash is a reserved directory
2474 if ($o->getName() != '.trash' && $o->getParentID() == 0) {
2475 $ndgf->create($this->replaceTemplateStrings($o->getName()));
2476 $id_mappings['docman_docgroup'][$o->getID()] = $ndgf->getID();
2479 // Second pass: restore hierarchy links
2480 foreach ($olddgf->getDocumentGroups() as $o) {
2481 $ndgf = new DocumentGroup($this);
2482 if ($o->getName() != '.trash' && $o->getParentID() == 0) {
2483 $ndgf->fetchData($id_mappings['docman_docgroup'][$o->getID()]);
2484 $ndgf->update($ndgf->getName(), $id_mappings['docman_docgroup'][$o->getParentID()]);
2490 if (forge_get_config('use_frs')) {
2491 $this->setUseFRS ($template->usesFRS());
2492 if ($template->usesFRS()) {
2493 foreach (get_frs_packages($template) as $o) {
2494 $newp = new FRSPackage($this);
2495 $nname = $this->replaceTemplateStrings($o->getName());
2496 $newp->create ($nname, $o->isPublic());
2501 if (forge_get_config('use_mail')) {
2502 $this->setUseMail($template->usesMail()) ;
2503 if ($template->usesMail()) {
2504 $oldmlf = new MailingListFactory($template);
2505 foreach ($oldmlf->getMailingLists() as $o) {
2506 $ml = new MailingList($this);
2507 $nname = preg_replace ('/^'.$template->getUnixName().'-/','',$o->getName()) ;
2509 $ndescription = $this->replaceTemplateStrings($o->getDescription()) ;
2510 $ml->create($nname, $ndescription, $o->isPublic());
2515 $this->setUseSCM ($template->usesSCM()) ;
2517 foreach ($template->getPlugins() as $plugin_id => $plugin_name) {
2518 $this->setPluginUse ($plugin_name) ;
2521 foreach ($template->getRoles() as $oldrole) {
2522 $newrole = RBACEngine::getInstance()->getRoleById ($id_mappings['role'][$oldrole->getID()]) ;
2523 if ($oldrole->getHomeProject() != NULL
2524 && $oldrole->getHomeProject()->getID() == $template->getID()) {
2525 $newrole->setPublic ($oldrole->isPublic()) ;
2527 $oldsettings = $oldrole->getSettingsForProject ($template) ;
2529 $sections = array ('project_read', 'project_admin', 'frs', 'scm', 'docman', 'tracker_admin', 'new_tracker', 'forum_admin', 'new_forum', 'pm_admin', 'new_pm') ;
2530 foreach ($sections as $section) {
2531 $newrole->setSetting ($section, $this->getID(), $oldsettings[$section][$template->getID()]) ;
2534 $sections = array ('tracker', 'pm', 'forum') ;
2535 foreach ($sections as $section) {
2536 if (isset ($oldsettings[$section])) {
2537 foreach ($oldsettings[$section] as $k => $v) {
2538 // Only copy perms for tools that have been copied
2539 if (isset ($id_mappings[$section][$k])) {
2540 $newrole->setSetting ($section,
2541 $id_mappings[$section][$k],
2549 $lm = new WidgetLayoutManager();
2550 $lm->createDefaultLayoutForProject ($this->getID(), $template->getID()) ;
2552 $params = array () ;
2553 $params['template'] = $template ;
2554 $params['project'] = $this ;
2555 $params['id_mappings'] = $id_mappings ;
2556 plugin_hook_by_reference ('clone_project_from_template', $params) ;
2558 // Disable everything
2559 $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, use_ftp=0, use_tracker=0, use_frs=0, use_stats=0 WHERE group_id=$1',
2561 array ($this->getID())) ;
2564 $this->normalizeAllRoles();
2565 $this->activateUsers();
2567 // Switch back to user preference
2568 session_set_internal($saved_session->getID());
2569 setup_gettext_from_context();
2573 $this->sendApprovalEmail();
2574 $this->addHistory('Approved', 'x');
2577 // Plugin can make approve operation there
2579 $params[0] = $idadmin_group;
2580 $params[1] = $this->getID();
2581 plugin_hook('group_approved', $params);
2589 * sendApprovalEmail - Send new project email.
2591 * @return boolean success.
2594 function sendApprovalEmail() {
2595 $admins = RBACEngine::getInstance()->getUsersByAllowedAction ('project_admin', $this->getID()) ;
2597 if (count($admins) < 1) {
2598 $this->setError(_("Group does not have any administrators."));
2602 // send one email per admin
2603 foreach ($admins as $admin) {
2604 setup_gettext_for_user ($admin) ;
2606 $message=sprintf(_('Your project registration for %4$s has been approved.
2608 Project Full Name: %1$s
2609 Project Unix Name: %2$s
2611 Your DNS will take up to a day to become active on our site.
2612 Your web site is accessible through your shell account. Please read
2613 site documentation (see link below) about intended usage, available
2614 services, and directory layout of the account.
2617 own project page in %4$s while logged in, you will find
2618 additional menu functions to your left labeled \'Project Admin\'.
2620 We highly suggest that you now visit %4$s and create a public
2621 description for your project. This can be done by visiting your project
2622 page while logged in, and selecting \'Project Admin\' from the menus
2623 on the left (or by visiting %3$s
2626 Your project will also not appear in the Trove Software Map (primary
2627 list of projects hosted on %4$s which offers great flexibility in
2628 browsing and search) until you categorize it in the project administration
2629 screens. So that people can find your project, you should do this now.
2630 Visit your project while logged in, and select \'Project Admin\' from the
2633 Enjoy the system, and please tell others about %4$s. Let us know
2634 if there is anything we can do to help you.
2637 htmlspecialchars_decode($this->getPublicName()),
2638 $this->getUnixName(),
2639 util_make_url ('/project/admin/?group_id='.$this->getID()),
2640 forge_get_config ('forge_name'));
2642 util_send_message($admin->getEmail(), sprintf(_('%1$s Project Approved'), forge_get_config ('forge_name')), $message);
2644 setup_gettext_from_context();
2652 * sendRejectionEmail - Send project rejection email.
2654 * This function sends out a rejection message to a user who
2655 * registered a project.
2657 * @param int The id of the response to use.
2658 * @param string The rejection message.
2659 * @return boolean completion status.
2662 function sendRejectionEmail($response_id, $message="zxcv") {
2663 $submitters = array () ;
2665 foreach (get_group_join_requests ($this) as $gjr) {
2666 $submitters[] = user_get_object($gjr->getUserID());
2669 $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",
2671 while ($arr = db_fetch_array($res)) {
2672 $submitter[] = user_get_object($arr['user_id']);
2676 if (count ($submitters) < 1) {
2677 $this->setError(_("Group does not have any administrators."));
2681 foreach ($submitters as $admin) {
2682 setup_gettext_for_user($admin);
2684 $response=sprintf(_('Your project registration for %3$s has been denied.
2686 Project Full Name: %1$s
2687 Project Unix Name: %2$s
2689 Reasons for negative decision:
2691 '), $this->getPublicName(), $this->getUnixName(), forge_get_config('forge_name'));
2693 // Check to see if they want to send a custom rejection response
2694 if ($response_id == 0) {
2695 $response .= $message;
2697 $response .= db_result(
2698 db_query_params('SELECT response_text FROM canned_responses WHERE response_id=$1', array ($response_id)),
2703 util_send_message($admin->getEmail(), sprintf(_('%1$s Project Denied'), forge_get_config ('forge_name')), $response);
2704 setup_gettext_from_context();
2711 * sendNewProjectNotificationEmail - Send new project notification email.
2713 * This function sends out a notification email to the
2714 * SourceForge admin user when a new project is
2717 * @return boolean success.
2720 function sendNewProjectNotificationEmail() {
2721 // Get the user who wants to register the project
2722 $submitters = array();
2724 foreach (get_group_join_requests ($this) as $gjr) {
2725 $submitters[] = user_get_object($gjr->getUserID());
2728 $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",
2730 while ($arr = db_fetch_array ($res)) {
2731 $submitter[] = user_get_object($arr['user_id']);
2734 if (count ($submitters) < 1) {
2735 $this->setError(_("Could not find user who has submitted the project."));
2739 $admins = RBACEngine::getInstance()->getUsersByAllowedAction ('approve_projects', -1) ;
2741 if (count($admins) < 1) {
2742 $this->setError(_("There is no administrator to send the mail to."));
2746 foreach ($admins as $admin) {
2747 $admin_email = $admin->getEmail () ;
2748 setup_gettext_for_user ($admin) ;
2750 foreach ($submitters as $u) {
2751 $submitter_names[] = $u->getRealName() ;
2754 $message = sprintf(_('New %1$s Project Submitted
2756 Project Full Name: %2$s
2757 Submitted Description: %3$s
2759 forge_get_config ('forge_name'),
2760 htmlspecialchars_decode($this->getPublicName()),
2761 htmlspecialchars_decode($this->getRegistrationPurpose()));
2763 foreach ($submitters as $submitter) {
2764 $message .= sprintf(_('Submitter: %1$s (%2$s)
2766 $submitter->getRealName(),
2767 $submitter->getUnixName());
2770 $message .= sprintf (_('
2771 Please visit the following URL to approve or reject this project:
2773 util_make_url ('/admin/approve-pending.php')) ;
2774 util_send_message($admin_email, sprintf(_('New %1$s Project Submitted'), forge_get_config ('forge_name')), $message);
2775 setup_gettext_from_context();
2779 $email = $submitter->getEmail() ;
2780 setup_gettext_for_user ($submitter) ;
2782 $message=sprintf(_('New %1$s Project Submitted
2784 Project Full Name: %2$s
2785 Submitted Description: %3$s
2787 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'));
2789 util_send_message($email, sprintf(_('New %1$s Project Submitted'), forge_get_config ('forge_name')), $message);
2790 setup_gettext_from_context();
2799 * validateGroupName - Validate the group name
2801 * @param string Group name.
2803 * @return boolean an error false and set an error is the group name is invalide otherwise return true
2805 function validateGroupName($group_name) {
2806 if (strlen($group_name)<3) {
2807 $this->setError(_('Group name is too short'));
2809 } else if (strlen(htmlspecialchars($group_name))>50) {
2810 $this->setError(_('Group name is too long'));
2812 } else if ($group=group_get_object_by_publicname($group_name)) {
2813 $this->setError(_('Group name already taken'));
2821 * getRoles - Get the roles of the group.
2823 * @return array Role ids of this group.
2825 function getRolesId() {
2826 $role_ids = array();
2829 $res = db_query_params('SELECT role_id FROM pfo_role WHERE home_group_id=$1',
2830 array($this->getID()));
2831 while ($arr = db_fetch_array($res)) {
2832 $role_ids[] = $arr['role_id'];
2834 $res = db_query_params('SELECT role_id FROM role_project_refs WHERE group_id=$1',
2835 array($this->getID()));
2836 while ($arr = db_fetch_array($res)) {
2837 $role_ids[] = $arr['role_id'];
2840 $res = db_query_params('SELECT role_id FROM role WHERE group_id=$1',
2841 array($this->getID()));
2842 while ($arr = db_fetch_array($res)) {
2843 $role_ids[] = $arr['role_id'];
2847 return array_unique($role_ids);
2851 * getRoles - Get the roles of the group.
2853 * @return array Roles of this group.
2855 function getRoles() {
2858 $roles = $this->getRolesId();
2860 $engine = RBACEngine::getInstance();
2861 foreach ($roles as $role_id) {
2862 $result[] = $engine->getRoleById ($role_id);
2865 foreach ($roles as $role_id) {
2866 $result[] = new Role ($this, $role_id);
2873 function normalizeAllRoles() {
2874 $roles = $this->getRoles();
2876 foreach ($roles as $r) {
2877 $r->normalizeData();
2882 * getUnixStatus - Status of activation of unix account.
2884 * @return char (N)one, (A)ctive, (S)uspended or (D)eleted
2886 function getUnixStatus() {
2887 return $this->data_array['unix_status'];
2891 * setUnixStatus - Sets status of activation of unix account.
2893 * @param string The unix status.
2899 * @return boolean success.
2901 function setUnixStatus($status) {
2904 $res = db_query_params ('UPDATE groups SET unix_status=$1 WHERE group_id=$2',
2909 $this->setError(sprintf(_('ERROR - Could Not Update Group Unix Status: %s'),db_error()));
2913 if ($status == 'A') {
2914 if (!$SYS->sysCheckCreateGroup($this->getID())) {
2915 $this->setError($SYS->getErrorMessage());
2920 if ($SYS->sysCheckGroup($this->getID())) {
2921 if (!$SYS->sysRemoveGroup($this->getID())) {
2922 $this->setError($SYS->getErrorMessage());
2929 $this->data_array['unix_status']=$status;
2936 * getUsers - Get the users of a group
2938 * @return array of user's objects.
2940 function getUsers($onlylocal = true) {
2941 if (!isset($this->membersArr)) {
2942 $this->membersArr = array () ;
2946 foreach ($this->getRoles() as $role) {
2948 && ($role->getHomeProject() == NULL || $role->getHomeProject()->getID() != $this->getID())) {
2951 foreach ($role->getUsers() as $user) {
2952 $ids[] = $user->getID() ;
2955 $ids = array_unique ($ids) ;
2956 foreach ($ids as $id) {
2957 $u = user_get_object ($id) ;
2958 if ($u->isActive()) {
2959 $this->membersArr[] = $u ;
2964 $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',
2965 array ($this->getID(),
2967 if (!$users_group_res) {
2968 $this->setError(_('Error: Enable to get users from group'). ' ' . $this->getID() . ' ' .db_error());
2972 for ($i=0; $i<db_numrows($users_group_res); $i++) {
2973 $this->membersArr[$i] = new GFUser(db_result($users_group_res,$i,'user_id'),false);
2978 return $this->membersArr;
2981 function setDocmanCreateOnlineStatus($status) {
2983 /* if we activate search engine, we probably want to reindex */
2984 $res = db_query_params('UPDATE groups SET use_docman_create_online=$1 WHERE group_id=$2',
2985 array($status, $this->getID()));
2988 $this->setError(sprintf(_('ERROR - Could Not Update Group DocmanCreateOnline Status: %s'),db_error()));
2992 $this->data_array['use_docman_create_online']=$status;
2998 function setDocmanWebdav($status) {
3000 /* if we activate search engine, we probably want to reindex */
3001 $res = db_query_params('UPDATE groups SET use_webdav=$1 WHERE group_id=$2',
3006 $this->setError(sprintf(_('ERROR - Could Not Update Group UseWebdab Status: %s'),db_error()));
3010 $this->data_array['use_webdav']=$status;
3016 function setDocmanSearchStatus($status) {
3018 /* if we activate search engine, we probably want to reindex */
3019 $res = db_query_params('UPDATE groups SET use_docman_search=$1, force_docman_reindex=$1 WHERE group_id=$2',
3024 $this->setError(sprintf(_('ERROR - Could Not Update Group UseDocmanSearch Status: %s'),db_error()));
3028 $this->data_array['use_docman_search']=$status;
3034 function setDocmanForceReindexSearch($status) {
3036 /* if we activate search engine, we probably want to reindex */
3037 $res = db_query_params('UPDATE groups SET force_docman_reindex=$1 WHERE group_id=$2',
3042 $this->setError(sprintf(_('ERROR - Could Not Update Group force_docman_reindex %s'),db_error()));
3046 $this->data_array['force_docman_reindex']=$status;
3052 function setStorageAPI($type) {
3056 function getStorageAPI() {
3062 * group_getname() - get the group name
3064 * @param int The group ID
3068 function group_getname ($group_id = 0) {
3069 $grp = group_get_object($group_id);
3071 return $grp->getPublicName();
3078 * group_getunixname() - get the unixname for a group
3080 * @param int The group ID
3084 function group_getunixname ($group_id) {
3085 $grp = group_get_object($group_id);
3087 return $grp->getUnixName();
3094 * group_get_result() - Get the group object result ID.
3096 * @param int The group ID
3100 function &group_get_result($group_id=0) {
3101 $grp = group_get_object($group_id);
3103 return $grp->getData();
3109 function getAllProjectTags($onlyvisible = true) {
3110 $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',
3113 if (!$res || db_numrows($res) == 0) {
3119 while ($arr = db_fetch_array($res)) {
3121 $group_id = $arr[1];
3122 if (!isset($result[$tag])) {
3123 $result[$tag] = array();
3126 if (!$onlyvisible || forge_check_perm('project_read', $group_id)) {
3127 $p = group_get_object($group_id);
3128 $result[$tag][] = array('unix_group_name' => $p->getUnixName(),
3129 'group_id' => $group_id);
3137 * Utility class to compare project based in various criteria (names, unixnames, id, ...)
3140 class ProjectComparator {
3141 var $criterion = 'name' ;
3143 function Compare ($a, $b) {
3144 switch ($this->criterion) {
3147 $namecmp = strcoll ($a->getPublicName(), $b->getPublicName()) ;
3148 if ($namecmp != 0) {
3151 /* If several projects share a same public name */
3152 return strcoll ($a->getUnixName(), $b->getUnixName()) ;
3155 return strcmp ($a->getUnixName(), $b->getUnixName()) ;
3158 $aid = $a->getID() ;
3159 $bid = $b->getID() ;
3163 return ($a < $b) ? -1 : 1;
3169 function sortProjectList (&$list, $criterion='name') {
3170 $cmp = new ProjectComparator () ;
3171 $cmp->criterion = $criterion ;
3173 return usort ($list, array ($cmp, 'Compare')) ;
3178 // c-file-style: "bsd"