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'));
1766 // Delete SurveyQuestions
1768 $sqf = new SurveyQuestionFactory($this);
1769 $sq_arr =& $sqf->getSurveyQuestions();
1770 foreach ($sq_arr as $i) {
1771 if (!is_object($i)) {
1774 if (!$i->delete()) {
1775 $this->setError(_('Could not properly delete the survey questions'));
1781 // Delete Mailing List Factory
1783 $mlf = new MailingListFactory($this);
1784 $ml_arr = $mlf->getMailingLists();
1785 foreach ($ml_arr as $i) {
1786 if (!is_object($i)) {
1789 if (!$i->delete(1,1)) {
1790 $this->setError(_('Could not properly delete the mailing list'));
1798 $res = db_query_params('DELETE FROM trove_group_link WHERE group_id=$1',
1799 array($this->getID()));
1801 $this->setError(_('Error Deleting Trove: ').db_error());
1806 $res = db_query_params('DELETE FROM trove_agg WHERE group_id=$1',
1807 array($this->getID()));
1809 $this->setError(_('Error Deleting Trove: ').db_error());
1817 $res = db_query_params('DELETE FROM project_sums_agg WHERE group_id=$1',
1818 array($this->getID()));
1820 $this->setError(_('Error Deleting Counters: ').db_error());
1825 $res = db_query_params('INSERT INTO deleted_groups (unix_group_name, delete_date, isdeleted) VALUES ($1, $2, $3)',
1826 array($this->getUnixName(),
1830 $this->setError(_('Error Deleting Project:').' '.db_error());
1835 $res = db_query_params('DELETE FROM groups WHERE group_id=$1',
1836 array($this->getID()));
1838 $this->setError(_('Error Deleting Project:').' '.db_error());
1845 $hook_params = array();
1846 $hook_params['group'] = $this;
1847 $hook_params['group_id'] = $this->getID();
1848 plugin_hook("group_delete", $hook_params);
1850 if (forge_get_config('upload_dir') != '' && $this->getUnixName()) {
1851 exec('/bin/rm -rf '.forge_get_config('upload_dir').'/'.$this->getUnixName().'/');
1853 if (forge_get_config('ftp_upload_dir') != '' && $this->getUnixName()) {
1854 exec('/bin/rm -rf '.forge_get_config('ftp_upload_dir').'/'.$this->getUnixName().'/');
1859 $res = db_query_params('DELETE FROM rep_group_act_monthly WHERE group_id=$1',
1860 array ($this->getID()));
1861 //echo 'rep_group_act_monthly'.db_error();
1862 $res = db_query_params('DELETE FROM rep_group_act_weekly WHERE group_id=$1',
1863 array ($this->getID()));
1864 //echo 'rep_group_act_weekly'.db_error();
1865 $res = db_query_params('DELETE FROM rep_group_act_daily WHERE group_id=$1',
1866 array ($this->getID()));
1867 //echo 'rep_group_act_daily'.db_error();
1868 unset($this->data_array);
1873 Basic functions to add/remove users to/from a group
1874 and update their permissions
1878 * addUser - controls adding a user to a group.
1880 * @param string Unix name of the user to add OR integer user_id.
1881 * @param int The role_id this user should have.
1882 * @return boolean success.
1885 function addUser($user_identifier,$role_id) {
1888 Admins can add users to groups
1891 if (!forge_check_perm ('project_admin', $this->getID())) {
1892 $this->setPermissionDeniedError();
1898 get user id for this user's unix_name
1900 if (is_int ($user_identifier)) { // user_id or user_name
1901 $res_newuser = db_query_params ('SELECT * FROM users WHERE user_id=$1', array ($user_identifier)) ;
1903 $res_newuser = db_query_params ('SELECT * FROM users WHERE user_name=$1', array ($user_identifier)) ;
1905 if (db_numrows($res_newuser) > 0) {
1907 // make sure user is active
1909 if (db_result($res_newuser,0,'status') != 'A') {
1910 $this->setError(_('User is not active. Only active users can be added.'));
1916 // user was found - set new user_id var
1918 $user_id = db_result($res_newuser,0,'user_id');
1920 $role = new Role($this, $role_id);
1921 if (!$role || !is_object($role)) {
1922 $this->setError(_('Error Getting Role Object'));
1925 } elseif ($role->isError()) {
1926 $this->setError('addUser::roleget::'.$role->getErrorMessage());
1932 $role->addUser(user_get_object($user_id)) ;
1933 if (!$SYS->sysCheckCreateGroup($this->getID())){
1934 $this->setError($SYS->getErrorMessage());
1938 if (!$SYS->sysCheckCreateUser($user_id)) {
1939 $this->setError($SYS->getErrorMessage());
1943 if (!$SYS->sysGroupCheckUser($this->getID(),$user_id)) {
1944 $this->setError($SYS->getErrorMessage());
1948 } else { // NOT USE_PFO_RBAC
1951 // if not already a member, add them
1953 $res_member = db_query_params('SELECT user_id
1955 WHERE user_id=$1 AND group_id=$2',
1956 array($user_id, $this->getID()));
1958 if (db_numrows($res_member) < 1) {
1960 // Create this user's row in the user_group table
1962 $res = db_query_params('INSERT INTO user_group
1963 (user_id,group_id,admin_flags,forum_flags,project_flags,
1964 doc_flags,cvs_flags,member_role,release_flags,artifact_flags)
1965 VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10)',
1977 //verify the insert worked
1978 if (!$res || db_affected_rows($res) < 1) {
1979 $this->setError(sprintf(_('ERROR: Could Not Add User To Group: %s'),db_error()));
1984 // check and create if group doesn't exists
1986 //echo "<h2>Group::addUser SYS->sysCheckCreateGroup(".$this->getID().")</h2>";
1987 if (!$SYS->sysCheckCreateGroup($this->getID())){
1988 $this->setError($SYS->getErrorMessage());
1993 // check and create if user doesn't exists
1995 //echo "<h2>Group::addUser SYS->sysCheckCreateUser($user_id)</h2>";
1996 if (!$SYS->sysCheckCreateUser($user_id)) {
1997 $this->setError($SYS->getErrorMessage());
2004 //echo "<h2>Group::addUser role->setUser($user_id)</h2>";
2005 if (!$role->setUser($user_id)) {
2006 $this->setError('addUser::role::setUser'.$role->getErrorMessage());
2012 // user was already a member
2013 // make sure they are set up
2015 $user= user_get_object($user_id,$res_newuser);
2016 $user->fetchData($user->getID());
2017 $role = new Role($this,$role_id);
2018 if (!$role || !is_object($role)) {
2019 $this->setError(_('Error Getting Role Object'));
2022 } elseif ($role->isError()) {
2023 $this->setError('addUser::roleget::'.$role->getErrorMessage());
2027 //echo "<h2>Already Member Group::addUser role->setUser($user_id)</h2>";
2028 if (!$role->setUser($user_id)) {
2029 $this->setError('addUser::role::setUser'.$role->getErrorMessage());
2034 // set up their system info
2036 //echo "<h2>Already Member Group::addUser SYS->sysCheckCreateUser($user_id)</h2>";
2037 if (!$SYS->sysCheckCreateUser($user_id)) {
2038 $this->setError($SYS->getErrorMessage());
2046 // user doesn't exist
2048 $this->setError(_('ERROR: User does not exist'));
2053 $hook_params['group'] = $this;
2054 $hook_params['group_id'] = $this->getID();
2055 $hook_params['user'] = user_get_object($user_id);
2056 $hook_params['user_id'] = $user_id;
2057 plugin_hook ("group_adduser", $hook_params);
2062 $this->addHistory('Added User',$user_identifier);
2068 * removeUser - controls removing a user from a group.
2070 * Users can remove themselves.
2072 * @param int The ID of the user to remove.
2073 * @return boolean success.
2075 function removeUser($user_id) {
2078 if ($user_id != user_getid()
2079 || !forge_check_perm('project_admin', $this->getID())) {
2080 $this->setPermissionDeniedError();
2087 $user = user_get_object($user_id);
2088 $roles = RBACEngine::getInstance()->getAvailableRolesForUser($user);
2090 foreach ($roles as $role) {
2091 if ($role->getHomeProject() && $role->getHomeProject()->getID() == $this->getID()) {
2092 $found_role = $role;
2096 if ($found_role == NULL) {
2097 $this->setError(sprintf(_('ERROR: User not removed: %s')));
2101 $found_role->removeUser($user);
2102 if (!$SYS->sysGroupCheckUser($this->getID(), $user_id)) {
2103 $this->setError($SYS->getErrorMessage());
2109 $res = db_query_params('DELETE FROM user_group WHERE group_id=$1 AND user_id=$2',
2110 array($this->getID(),
2112 if (!$res || db_affected_rows($res) < 1) {
2113 $this->setError(_('ERROR: User not removed:').' '.db_error());
2120 // reassign open artifacts to id=100
2122 $res = db_query_params('UPDATE artifact SET assigned_to=100
2123 WHERE group_artifact_id
2124 IN (SELECT group_artifact_id
2125 FROM artifact_group_list
2126 WHERE group_id=$1 AND status_id=1 AND assigned_to=$2)',
2127 array($this->getID(),
2130 $this->setError(_('ERROR: DB: artifact:').' '.db_error());
2136 // reassign open tasks to id=100
2137 // first have to purge any assignments that would cause
2138 // conflict with existing assignment to 100
2140 $res = db_query_params('DELETE FROM project_assigned_to
2141 WHERE project_task_id IN (SELECT pt.project_task_id
2142 FROM project_task pt, project_group_list pgl, project_assigned_to pat
2143 WHERE pt.group_project_id = pgl.group_project_id
2144 AND pat.project_task_id=pt.project_task_id
2145 AND pt.status_id=1 AND pgl.group_id=$1
2146 AND pat.assigned_to_id=$2)
2147 AND assigned_to_id=100',
2148 array($this->getID(),
2151 $this->setError(sprintf(_('ERROR: DB: project_assigned_to %d: %s'), 1, db_error()));
2155 $res = db_query_params('UPDATE project_assigned_to SET assigned_to_id=100
2156 WHERE project_task_id IN (SELECT pt.project_task_id
2157 FROM project_task pt, project_group_list pgl
2158 WHERE pt.group_project_id = pgl.group_project_id
2159 AND pt.status_id=1 AND pgl.group_id=$1)
2160 AND assigned_to_id=$2',
2161 array($this->getID(),
2164 $this->setError(sprintf(_('ERROR: DB: project_assigned_to %d: %s'), 2, db_error()));
2170 // Remove user from system
2172 if (!$SYS->sysGroupRemoveUser($this->getID(), $user_id)) {
2173 $this->setError($SYS->getErrorMessage());
2178 $hook_params['group'] = $this;
2179 $hook_params['group_id'] = $this->getID();
2180 $hook_params['user'] = user_get_object($user_id);
2181 $hook_params['user_id'] = $user_id;
2182 plugin_hook ("group_removeuser", $hook_params);
2185 $this->addHistory('Removed User',$user_id);
2192 * updateUser - controls updating a user's role in this group.
2194 * @param int The ID of the user.
2195 * @param int The role_id to set this user to.
2196 * @return boolean success.
2198 function updateUser($user_id,$role_id) {
2201 if (!forge_check_perm ('project_admin', $this->getID())) {
2202 $this->setPermissionDeniedError();
2207 $newrole = RBACEngine::getInstance()->getRoleById ($role_id) ;
2208 if (!$newrole || !is_object($newrole)) {
2209 $this->setError(_('Could Not Get Role'));
2211 } elseif ($newrole->isError()) {
2212 $this->setError(sprintf(_('Role: %s'),$role->getErrorMessage()));
2214 } elseif ($newrole->getHomeProject() == NULL
2215 || $newrole->getHomeProject()->getID() != $this->getID()) {
2216 $this->setError(_('Wrong destination role'));
2219 $user = user_get_object ($user_id) ;
2220 $roles = RBACEngine::getInstance()->getAvailableRolesForUser ($user) ;
2221 $found_role = NULL ;
2222 foreach ($roles as $role) {
2223 if ($role->getHomeProject() && $role->getHomeProject()->getID() == $this->getID()) {
2224 $found_role = $role ;
2228 if ($found_role == NULL) {
2229 $this->setError(sprintf(_('ERROR: User not removed: %s')));
2233 $found_role->removeUser ($user) ;
2234 $newrole->addUser ($user) ;
2236 $role = new Role($this,$role_id);
2237 if (!$role || !is_object($role)) {
2238 $this->setError(_('Could Not Get Role'));
2240 } elseif ($role->isError()) {
2241 $this->setError(sprintf(_('Role: %s'),$role->getErrorMessage()));
2244 //echo "<h3>Group::updateUser role->setUser($user_id)</h3>";
2245 if (!$role->setUser($user_id)) {
2246 $this->setError(sprintf(_('Role: %s'),$role->getErrorMessage()));
2251 $this->addHistory('Updated User',$user_id);
2256 * addHistory - Makes an audit trail entry for this project.
2258 * @param string The name of the field.
2259 * @param string The Old Value for this $field_name.
2260 * @return database result handle.
2263 function addHistory($field_name, $old_value) {
2264 return db_query_params ('INSERT INTO group_history(group_id,field_name,old_value,mod_by,adddate)
2265 VALUES ($1,$2,$3,$4,$5)',
2266 array ($this->getID(),
2274 * activateUsers - Make sure that group members have unix accounts.
2276 * Setup unix accounts for group members. Can be called even
2277 * if members are already active.
2281 function activateUsers() {
2283 Activate member(s) of the project
2287 $members = $this->getUsers (true) ;
2289 foreach ($members as $member) {
2291 foreach (RBACEngine::getInstance()->getAvailableRolesForUser ($member) as $role) {
2292 if ($role->getHomeProject() && $role->getHomeProject()->getID() == $this->getID()) {
2295 if (!$this->addUser($member->getUnixName(),$role->getID())) {
2302 $res_member = db_query_params('SELECT user_id,role_id FROM user_group WHERE group_id=$1',
2303 array ($this->getID()));
2304 while ($row_member = db_fetch_array($res_member)) {
2305 $u = user_get_object($row_member['user_id']);
2306 if (!$this->addUser($u->getUnixName(),$row_member['role_id'])) {
2316 * getMembers - returns array of User objects for this project
2318 * @return array of User objects for this group.
2320 function getMembers() {
2321 return $this->getUsers (true) ;
2325 * replaceTemplateStrings - fill-in some blanks with project name
2327 * @param string Template string
2328 * @return string String after replacements
2330 function replaceTemplateStrings($string) {
2331 $string = str_replace ('UNIXNAME', $this->getUnixName(), $string) ;
2332 $string = str_replace ('PUBLICNAME', $this->getPublicName(), $string) ;
2333 $string = str_replace ('DESCRIPTION', $this->getDescription(), $string) ;
2338 * approve - Approve pending project.
2340 * @param object The User object who is doing the updating.
2343 function approve(&$user) {
2344 global $gfcommon,$gfwww;
2345 require_once $gfcommon.'widget/WidgetLayoutManager.class.php';
2347 if ($this->getStatus()=='A') {
2348 $this->setError(_("Group already active"));
2354 // Step 1: Activate group and create LDAP entries
2355 if (!$this->setStatus($user, 'A')) {
2360 // Switch to system language for item creation
2361 setup_gettext_from_sys_lang();
2363 // Create default roles
2365 $idadmin_group = NULL;
2366 foreach (get_group_join_requests ($this) as $gjr) {
2367 $idadmin_group = $gjr->getUserID();
2370 if ($idadmin_group == NULL) {
2371 $idadmin_group = $user->getID();
2374 $admin_group = db_query_params('SELECT user_id FROM user_group WHERE group_id=$1 AND admin_flags=$2',
2375 array($this->getID(),
2377 if (db_numrows($admin_group) > 0) {
2378 $idadmin_group = db_result($admin_group,0,'user_id');
2380 $idadmin_group = $user->getID();
2381 db_query_params('INSERT INTO user_group (user_id, group_id, admin_flags) VALUES ($1, $2, $3)',
2382 array($idadmin_group,
2388 $template = $this->getTemplateProject();
2389 $id_mappings = array();
2390 $seen_local_roles = false;
2392 // Copy roles from template project
2393 foreach($template->getRoles() as $oldrole) {
2394 if ($oldrole->getHomeProject() != NULL) {
2395 $role = new Role($this);
2397 // Need to use a different role name so that the permissions aren't set from the hardcoded defaults
2398 $role->create('TEMPORARY ROLE NAME', $data, true);
2399 $role->setName($oldrole->getName());
2400 $seen_local_roles = true;
2403 $role->linkProject($this);
2405 $id_mappings['role'][$oldrole->getID()] = $role->getID();
2406 // Reuse the project_admin permission
2407 $role->setSetting ('project_admin', $this->getID(), $oldrole->getSetting ('project_admin', $template->getID())) ;
2411 if (!$seen_local_roles) {
2412 $role = new Role($this);
2413 $adminperms = array ('project_admin' => array ($this->getID() => 1)) ;
2414 $role_id = $role->create ('Admin', $adminperms, true) ;
2418 $roles = $this->getRoles() ;
2419 foreach ($roles as $r) {
2420 if ($r->getSetting ('project_admin', $this->getID())) {
2421 $r->addUser(user_get_object ($idadmin_group));
2426 // Temporarily switch to the submitter's identity
2427 $saved_session = session_get_user();
2428 session_set_internal($idadmin_group);
2431 if (forge_get_config('use_tracker')) {
2432 $this->setUseTracker ($template->usesTracker());
2433 if ($template->usesTracker()) {
2434 $oldatf = new ArtifactTypeFactory($template);
2435 foreach ($oldatf->getArtifactTypes() as $o) {
2436 $t = new ArtifactType ($this) ;
2437 $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()) ;
2438 $id_mappings['tracker'][$o->getID()] = $t->getID();
2439 $t->cloneFieldsFrom ($o->getID());
2444 if (forge_get_config('use_pm')) {
2445 $this->setUsePM ($template->usesPM());
2446 if ($template->usesPM()) {
2447 $oldpgf = new ProjectGroupFactory($template);
2448 foreach ($oldpgf->getProjectGroups() as $o) {
2449 $pg = new ProjectGroup($this);
2450 $pg->create($this->replaceTemplateStrings($o->getName()),$this->replaceTemplateStrings($o->getDescription()),$o->isPublic(),$o->getSendAllPostsTo());
2451 $id_mappings['pm'][$o->getID()] = $pg->getID();
2456 if (forge_get_config('use_forum')) {
2457 $this->setUseForum($template->usesForum()) ;
2458 if ($template->usesForum()) {
2459 $oldff = new ForumFactory($template) ;
2460 foreach ($oldff->getForums() as $o) {
2461 $f = new Forum($this);
2462 $f->create($this->replaceTemplateStrings($o->getName()),$this->replaceTemplateStrings($o->getDescription()),$o->isPublic(),$o->getSendAllPostsTo(),1,$o->allowAnonymous(),$o->getModerationLevel());
2463 $id_mappings['forum'][$o->getID()] = $f->getID();
2468 if (forge_get_config('use_docman')) {
2469 $this->setUseDocman($template->usesDocman());
2470 if ($template->usesDocman()) {
2471 $olddgf = new DocumentGroupFactory($template);
2472 // First pass: create all docgroups
2473 $id_mappings['docman_docgroup'][0] = 0;
2474 foreach ($olddgf->getDocumentGroups() as $o) {
2475 $ndgf = new DocumentGroup($this);
2476 // .trash is a reserved directory
2477 if ($o->getName() != '.trash' && $o->getParentID() == 0) {
2478 $ndgf->create($this->replaceTemplateStrings($o->getName()));
2479 $id_mappings['docman_docgroup'][$o->getID()] = $ndgf->getID();
2482 // Second pass: restore hierarchy links
2483 foreach ($olddgf->getDocumentGroups() as $o) {
2484 $ndgf = new DocumentGroup($this);
2485 if ($o->getName() != '.trash' && $o->getParentID() == 0) {
2486 $ndgf->fetchData($id_mappings['docman_docgroup'][$o->getID()]);
2487 $ndgf->update($ndgf->getName(), $id_mappings['docman_docgroup'][$o->getParentID()]);
2493 if (forge_get_config('use_frs')) {
2494 $this->setUseFRS ($template->usesFRS());
2495 if ($template->usesFRS()) {
2496 foreach (get_frs_packages($template) as $o) {
2497 $newp = new FRSPackage($this);
2498 $nname = $this->replaceTemplateStrings($o->getName());
2499 $newp->create ($nname, $o->isPublic());
2504 if (forge_get_config('use_mail')) {
2505 $this->setUseMail($template->usesMail()) ;
2506 if ($template->usesMail()) {
2507 $oldmlf = new MailingListFactory($template);
2508 foreach ($oldmlf->getMailingLists() as $o) {
2509 $ml = new MailingList($this);
2510 $nname = preg_replace ('/^'.$template->getUnixName().'-/','',$o->getName()) ;
2512 $ndescription = $this->replaceTemplateStrings($o->getDescription()) ;
2513 $ml->create($nname, $ndescription, $o->isPublic());
2518 $this->setUseSCM ($template->usesSCM()) ;
2520 foreach ($template->getPlugins() as $plugin_id => $plugin_name) {
2521 $this->setPluginUse ($plugin_name) ;
2524 foreach ($template->getRoles() as $oldrole) {
2525 $newrole = RBACEngine::getInstance()->getRoleById ($id_mappings['role'][$oldrole->getID()]) ;
2526 if ($oldrole->getHomeProject() != NULL
2527 && $oldrole->getHomeProject()->getID() == $template->getID()) {
2528 $newrole->setPublic ($oldrole->isPublic()) ;
2530 $oldsettings = $oldrole->getSettingsForProject ($template) ;
2532 $sections = array ('project_read', 'project_admin', 'frs', 'scm', 'docman', 'tracker_admin', 'new_tracker', 'forum_admin', 'new_forum', 'pm_admin', 'new_pm') ;
2533 foreach ($sections as $section) {
2534 $newrole->setSetting ($section, $this->getID(), $oldsettings[$section][$template->getID()]) ;
2537 $sections = array ('tracker', 'pm', 'forum') ;
2538 foreach ($sections as $section) {
2539 if (isset ($oldsettings[$section])) {
2540 foreach ($oldsettings[$section] as $k => $v) {
2541 // Only copy perms for tools that have been copied
2542 if (isset ($id_mappings[$section][$k])) {
2543 $newrole->setSetting ($section,
2544 $id_mappings[$section][$k],
2552 $lm = new WidgetLayoutManager();
2553 $lm->createDefaultLayoutForProject ($this->getID(), $template->getID()) ;
2555 $params = array () ;
2556 $params['template'] = $template ;
2557 $params['project'] = $this ;
2558 $params['id_mappings'] = $id_mappings ;
2559 plugin_hook_by_reference ('clone_project_from_template', $params) ;
2561 // Disable everything
2562 $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',
2564 array ($this->getID())) ;
2567 $this->normalizeAllRoles();
2568 $this->activateUsers();
2570 // Switch back to user preference
2571 session_set_internal($saved_session->getID());
2572 setup_gettext_from_context();
2576 $this->sendApprovalEmail();
2577 $this->addHistory('Approved', 'x');
2580 // Plugin can make approve operation there
2582 $params[0] = $idadmin_group;
2583 $params[1] = $this->getID();
2584 plugin_hook('group_approved', $params);
2592 * sendApprovalEmail - Send new project email.
2594 * @return boolean success.
2597 function sendApprovalEmail() {
2598 $admins = RBACEngine::getInstance()->getUsersByAllowedAction ('project_admin', $this->getID()) ;
2600 if (count($admins) < 1) {
2601 $this->setError(_("Group does not have any administrators."));
2605 // send one email per admin
2606 foreach ($admins as $admin) {
2607 setup_gettext_for_user ($admin) ;
2609 $message=sprintf(_('Your project registration for %4$s has been approved.
2611 Project Full Name: %1$s
2612 Project Unix Name: %2$s
2614 Your DNS will take up to a day to become active on our site.
2615 Your web site is accessible through your shell account. Please read
2616 site documentation (see link below) about intended usage, available
2617 services, and directory layout of the account.
2620 own project page in %4$s while logged in, you will find
2621 additional menu functions to your left labeled \'Project Admin\'.
2623 We highly suggest that you now visit %4$s and create a public
2624 description for your project. This can be done by visiting your project
2625 page while logged in, and selecting \'Project Admin\' from the menus
2626 on the left (or by visiting %3$s
2629 Your project will also not appear in the Trove Software Map (primary
2630 list of projects hosted on %4$s which offers great flexibility in
2631 browsing and search) until you categorize it in the project administration
2632 screens. So that people can find your project, you should do this now.
2633 Visit your project while logged in, and select \'Project Admin\' from the
2636 Enjoy the system, and please tell others about %4$s. Let us know
2637 if there is anything we can do to help you.
2640 htmlspecialchars_decode($this->getPublicName()),
2641 $this->getUnixName(),
2642 util_make_url ('/project/admin/?group_id='.$this->getID()),
2643 forge_get_config ('forge_name'));
2645 util_send_message($admin->getEmail(), sprintf(_('%1$s Project Approved'), forge_get_config ('forge_name')), $message);
2647 setup_gettext_from_context();
2655 * sendRejectionEmail - Send project rejection email.
2657 * This function sends out a rejection message to a user who
2658 * registered a project.
2660 * @param int The id of the response to use.
2661 * @param string The rejection message.
2662 * @return boolean completion status.
2665 function sendRejectionEmail($response_id, $message="zxcv") {
2666 $submitters = array () ;
2668 foreach (get_group_join_requests ($this) as $gjr) {
2669 $submitters[] = user_get_object($gjr->getUserID());
2672 $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",
2674 while ($arr = db_fetch_array($res)) {
2675 $submitter[] = user_get_object($arr['user_id']);
2679 if (count ($submitters) < 1) {
2680 $this->setError(_("Group does not have any administrators."));
2684 foreach ($submitters as $admin) {
2685 setup_gettext_for_user($admin);
2687 $response=sprintf(_('Your project registration for %3$s has been denied.
2689 Project Full Name: %1$s
2690 Project Unix Name: %2$s
2692 Reasons for negative decision:
2694 '), $this->getPublicName(), $this->getUnixName(), forge_get_config('forge_name'));
2696 // Check to see if they want to send a custom rejection response
2697 if ($response_id == 0) {
2698 $response .= $message;
2700 $response .= db_result(
2701 db_query_params('SELECT response_text FROM canned_responses WHERE response_id=$1', array ($response_id)),
2706 util_send_message($admin->getEmail(), sprintf(_('%1$s Project Denied'), forge_get_config ('forge_name')), $response);
2707 setup_gettext_from_context();
2714 * sendNewProjectNotificationEmail - Send new project notification email.
2716 * This function sends out a notification email to the
2717 * SourceForge admin user when a new project is
2720 * @return boolean success.
2723 function sendNewProjectNotificationEmail() {
2724 // Get the user who wants to register the project
2725 $submitters = array();
2727 foreach (get_group_join_requests ($this) as $gjr) {
2728 $submitters[] = user_get_object($gjr->getUserID());
2731 $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",
2733 while ($arr = db_fetch_array ($res)) {
2734 $submitter[] = user_get_object($arr['user_id']);
2737 if (count ($submitters) < 1) {
2738 $this->setError(_("Could not find user who has submitted the project."));
2742 $admins = RBACEngine::getInstance()->getUsersByAllowedAction ('approve_projects', -1) ;
2744 if (count($admins) < 1) {
2745 $this->setError(_("There is no administrator to send the mail to."));
2749 foreach ($admins as $admin) {
2750 $admin_email = $admin->getEmail () ;
2751 setup_gettext_for_user ($admin) ;
2753 foreach ($submitters as $u) {
2754 $submitter_names[] = $u->getRealName() ;
2757 $message = sprintf(_('New %1$s Project Submitted
2759 Project Full Name: %2$s
2760 Submitted Description: %3$s
2762 forge_get_config ('forge_name'),
2763 htmlspecialchars_decode($this->getPublicName()),
2764 htmlspecialchars_decode($this->getRegistrationPurpose()));
2766 foreach ($submitters as $submitter) {
2767 $message .= sprintf(_('Submitter: %1$s (%2$s)
2769 $submitter->getRealName(),
2770 $submitter->getUnixName());
2773 $message .= sprintf (_('
2774 Please visit the following URL to approve or reject this project:
2776 util_make_url ('/admin/approve-pending.php')) ;
2777 util_send_message($admin_email, sprintf(_('New %1$s Project Submitted'), forge_get_config ('forge_name')), $message);
2778 setup_gettext_from_context();
2782 $email = $submitter->getEmail() ;
2783 setup_gettext_for_user ($submitter) ;
2785 $message=sprintf(_('New %1$s Project Submitted
2787 Project Full Name: %2$s
2788 Submitted Description: %3$s
2790 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'));
2792 util_send_message($email, sprintf(_('New %1$s Project Submitted'), forge_get_config ('forge_name')), $message);
2793 setup_gettext_from_context();
2802 * validateGroupName - Validate the group name
2804 * @param string Group name.
2806 * @return boolean an error false and set an error is the group name is invalide otherwise return true
2808 function validateGroupName($group_name) {
2809 if (strlen($group_name)<3) {
2810 $this->setError(_('Group name is too short'));
2812 } else if (strlen(htmlspecialchars($group_name))>50) {
2813 $this->setError(_('Group name is too long'));
2815 } else if ($group=group_get_object_by_publicname($group_name)) {
2816 $this->setError(_('Group name already taken'));
2824 * getRoles - Get the roles of the group.
2826 * @return array Role ids of this group.
2828 function getRolesId() {
2829 $role_ids = array();
2832 $res = db_query_params('SELECT role_id FROM pfo_role WHERE home_group_id=$1',
2833 array($this->getID()));
2834 while ($arr = db_fetch_array($res)) {
2835 $role_ids[] = $arr['role_id'];
2837 $res = db_query_params('SELECT role_id FROM role_project_refs WHERE group_id=$1',
2838 array($this->getID()));
2839 while ($arr = db_fetch_array($res)) {
2840 $role_ids[] = $arr['role_id'];
2843 $res = db_query_params('SELECT role_id FROM role WHERE group_id=$1',
2844 array($this->getID()));
2845 while ($arr = db_fetch_array($res)) {
2846 $role_ids[] = $arr['role_id'];
2850 return array_unique($role_ids);
2854 * getRoles - Get the roles of the group.
2856 * @return array Roles of this group.
2858 function getRoles() {
2861 $roles = $this->getRolesId();
2863 $engine = RBACEngine::getInstance();
2864 foreach ($roles as $role_id) {
2865 $result[] = $engine->getRoleById ($role_id);
2868 foreach ($roles as $role_id) {
2869 $result[] = new Role ($this, $role_id);
2876 function normalizeAllRoles() {
2877 $roles = $this->getRoles();
2879 foreach ($roles as $r) {
2880 $r->normalizeData();
2885 * getUnixStatus - Status of activation of unix account.
2887 * @return char (N)one, (A)ctive, (S)uspended or (D)eleted
2889 function getUnixStatus() {
2890 return $this->data_array['unix_status'];
2894 * setUnixStatus - Sets status of activation of unix account.
2896 * @param string The unix status.
2902 * @return boolean success.
2904 function setUnixStatus($status) {
2907 $res = db_query_params ('UPDATE groups SET unix_status=$1 WHERE group_id=$2',
2912 $this->setError(sprintf(_('ERROR - Could Not Update Group Unix Status: %s'),db_error()));
2916 if ($status == 'A') {
2917 if (!$SYS->sysCheckCreateGroup($this->getID())) {
2918 $this->setError($SYS->getErrorMessage());
2923 if ($SYS->sysCheckGroup($this->getID())) {
2924 if (!$SYS->sysRemoveGroup($this->getID())) {
2925 $this->setError($SYS->getErrorMessage());
2932 $this->data_array['unix_status']=$status;
2939 * getUsers - Get the users of a group
2941 * @return array of user's objects.
2943 function getUsers($onlylocal = true) {
2944 if (!isset($this->membersArr)) {
2945 $this->membersArr = array () ;
2949 foreach ($this->getRoles() as $role) {
2951 && ($role->getHomeProject() == NULL || $role->getHomeProject()->getID() != $this->getID())) {
2954 foreach ($role->getUsers() as $user) {
2955 $ids[] = $user->getID() ;
2958 $ids = array_unique ($ids) ;
2959 foreach ($ids as $id) {
2960 $u = user_get_object ($id) ;
2961 if ($u->isActive()) {
2962 $this->membersArr[] = $u ;
2967 $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',
2968 array ($this->getID(),
2970 if (!$users_group_res) {
2971 $this->setError(_('Error: Enable to get users from group'). ' ' . $this->getID() . ' ' .db_error());
2975 for ($i=0; $i<db_numrows($users_group_res); $i++) {
2976 $this->membersArr[$i] = new GFUser(db_result($users_group_res,$i,'user_id'),false);
2981 return $this->membersArr;
2984 function setDocmanCreateOnlineStatus($status) {
2986 /* if we activate search engine, we probably want to reindex */
2987 $res = db_query_params('UPDATE groups SET use_docman_create_online=$1 WHERE group_id=$2',
2988 array($status, $this->getID()));
2991 $this->setError(sprintf(_('ERROR - Could Not Update Group DocmanCreateOnline Status: %s'),db_error()));
2995 $this->data_array['use_docman_create_online']=$status;
3001 function setDocmanWebdav($status) {
3003 /* if we activate search engine, we probably want to reindex */
3004 $res = db_query_params('UPDATE groups SET use_webdav=$1 WHERE group_id=$2',
3009 $this->setError(sprintf(_('ERROR - Could Not Update Group UseWebdab Status: %s'),db_error()));
3013 $this->data_array['use_webdav']=$status;
3019 function setDocmanSearchStatus($status) {
3021 /* if we activate search engine, we probably want to reindex */
3022 $res = db_query_params('UPDATE groups SET use_docman_search=$1, force_docman_reindex=$1 WHERE group_id=$2',
3027 $this->setError(sprintf(_('ERROR - Could Not Update Group UseDocmanSearch Status: %s'),db_error()));
3031 $this->data_array['use_docman_search']=$status;
3037 function setDocmanForceReindexSearch($status) {
3039 /* if we activate search engine, we probably want to reindex */
3040 $res = db_query_params('UPDATE groups SET force_docman_reindex=$1 WHERE group_id=$2',
3045 $this->setError(sprintf(_('ERROR - Could Not Update Group force_docman_reindex %s'),db_error()));
3049 $this->data_array['force_docman_reindex']=$status;
3055 function setStorageAPI($type) {
3059 function getStorageAPI() {
3065 * group_getname() - get the group name
3067 * @param int The group ID
3071 function group_getname ($group_id = 0) {
3072 $grp = group_get_object($group_id);
3074 return $grp->getPublicName();
3081 * group_getunixname() - get the unixname for a group
3083 * @param int The group ID
3087 function group_getunixname ($group_id) {
3088 $grp = group_get_object($group_id);
3090 return $grp->getUnixName();
3097 * group_get_result() - Get the group object result ID.
3099 * @param int The group ID
3103 function &group_get_result($group_id=0) {
3104 $grp = group_get_object($group_id);
3106 return $grp->getData();
3112 function getAllProjectTags($onlyvisible = true) {
3113 $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',
3116 if (!$res || db_numrows($res) == 0) {
3122 while ($arr = db_fetch_array($res)) {
3124 $group_id = $arr[1];
3125 if (!isset($result[$tag])) {
3126 $result[$tag] = array();
3129 if (!$onlyvisible || forge_check_perm('project_read', $group_id)) {
3130 $p = group_get_object($group_id);
3131 $result[$tag][] = array('unix_group_name' => $p->getUnixName(),
3132 'group_id' => $group_id);
3140 * Utility class to compare project based in various criteria (names, unixnames, id, ...)
3143 class ProjectComparator {
3144 var $criterion = 'name' ;
3146 function Compare ($a, $b) {
3147 switch ($this->criterion) {
3150 $namecmp = strcoll ($a->getPublicName(), $b->getPublicName()) ;
3151 if ($namecmp != 0) {
3154 /* If several projects share a same public name */
3155 return strcoll ($a->getUnixName(), $b->getUnixName()) ;
3158 return strcmp ($a->getUnixName(), $b->getUnixName()) ;
3161 $aid = $a->getID() ;
3162 $bid = $b->getID() ;
3166 return ($a < $b) ? -1 : 1;
3172 function sortProjectList (&$list, $criterion='name') {
3173 $cmp = new ProjectComparator () ;
3174 $cmp->criterion = $criterion ;
3176 return usort ($list, array ($cmp, 'Compare')) ;
3181 // c-file-style: "bsd"