3 * projects_hierarchyPlugin Class
5 * Copyright 2006 (c) Fabien Regnier - Sogeti
6 * Copyright 2010-2011, Franck Villaume - Capgemini
7 * http://fusionforge.org
9 * This file is part of FusionForge. FusionForge is free software;
10 * you can redistribute it and/or modify it under the terms of the
11 * GNU General Public License as published by the Free Software
12 * Foundation; either version 2 of the Licence, or (at your option)
15 * FusionForge is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License along
21 * with FusionForge; if not, write to the Free Software Foundation, Inc.,
22 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
25 class projects_hierarchyPlugin extends Plugin {
26 function projects_hierarchyPlugin() {
28 $this->name = 'projects_hierarchy';
29 $this->text = _('Project Hierarchy'); // To show in the tabs, use...
30 $this->_addHook('groupisactivecheckbox'); // The "use ..." checkbox in editgroupinfo
31 $this->_addHook('groupisactivecheckboxpost');
32 $this->_addHook('hierarchy_views'); // include specific views
33 $this->_addHook('display_hierarchy'); // to see the tree of projects
34 $this->_addHook('group_delete'); // clean tables on delete
35 $this->_addHook('project_admin_plugins'); // to show up in the admin page fro group
36 $this->_addHook('site_admin_option_hook');
39 function CallHook($hookname, &$params) {
40 global $G_SESSION, $HTML;
43 case "display_hierarchy": {
44 if ($this->displayHierarchy()) {
49 case "hierarchy_views": {
51 require_once $gfplugins.$this->name.'/include/hierarchy_utils.php';
52 $group_id = $params[0];
53 $project = group_get_object($group_id);
54 if ($project->usesPlugin($this->name)) {
59 include($gfplugins.$this->name.'/view/'.$params[1].'_project_link.php');
70 case "group_delete": {
71 if ($params['group']->usesPlugins($this->name)) {
72 if ($this->remove($params['group_id'])) {
80 case "project_admin_plugins": {
81 // this displays the link in the project admin options page to it's administration
82 $group_id = $params['group_id'];
83 $group = group_get_object($group_id);
84 if ($group->usesPlugin($this->name)) {
86 echo util_make_link('/plugins/'.$this->name.'/?group_id='.$group_id.'&type=admin&pluginname='.$this->name, _('Hierarchy Admin'));
92 case "site_admin_option_hook": {
93 echo '<li>'.$this->getAdminOptionLink().'</li>';
101 function displayHierarchy() {
102 $tree = $this->buildTree();
103 $displayTree = $this->affTree($tree, 0);
110 echo '<link rel="StyleSheet" href="/plugins/projects_hierarchy/dtree.css" type="text/css" />
111 <script type="text/javascript" src="/plugins/projects_hierarchy/dtree.js"></script>';
114 function buildTree() {
115 global $project_name;
116 $res = db_query_params('select p1.group_id as father_id,p1.unix_group_name as father_unix_name,p1.group_name as father_name,p2.group_id as son_id,p2.unix_group_name as son_unix_name,p2.group_name as son_name
117 from groups as p1,groups as p2,plugin_projects_hierarchy_relationship
118 where p1.group_id=plugin_projects_hierarchy_relationship.project_id
119 and p2.group_id=plugin_projects_hierarchy_relationship.sub_project_id
120 and plugin_projects_hierarchy_relationship.status=$1
121 order by father_name, son_name',
124 // construction du tableau associatif
125 // key = name of the father
126 // value = list of sons
128 while ($row = db_fetch_array($res)) {
129 if (forge_check_perm('project_read', $row['father_id'])) {
130 $tree[$row['father_id']][] = $row['son_id'];
131 //get the unix name of the project
132 $project_name[$row['father_id']][0] = $row['father_name'];
133 $project_name[$row['son_id']][0] = $row['son_name'];
134 $project_name[$row['father_id']][1] = $row['father_unix_name'];
135 $project_name[$row['son_id']][1] = $row['son_unix_name'];
141 function affTree($tree, $lvl) {
142 global $project_name;
148 while (list($key, $sons) = each($tree)) {
149 // Really don't know why there is a warning there, and added @
150 if(@!$arbre[$key] != 0){
154 foreach ($sons as $son) {
155 $arbre[$son] = $cpt_pere;
159 if (sizeof($arbre)) {
160 $returnTree .= '<table ><tr><td>';
161 $returnTree .= '<script type="text/javascript">';
162 $returnTree .= 'd = new dTree(\'d\');';
163 $returnTree .= 'd.add(0,-1,\'Project Tree\');';
165 //construction automatique de l'arbre format : (num_fils, num_pere,nom,nom_unix)
166 while (list($key2, $sons2) = each($arbre)) {
167 $returnTree .= "d.add('".$key2."','".$sons2."','".$project_name[$key2][0]."','".util_make_url( '/projects/'.$project_name[$key2][1] .'/', $project_name[$key2][1] ) ."');";
170 $returnTree .= 'document.write(d);';
171 $returnTree .= '</script>';
172 $returnTree .= '</td></tr></table>';
178 * getFamily - find the children or parent group_id of this project.
180 * @param integer group_id to search for
181 * @param string parent or child ?
182 * @param boolean recurcive or not ?
183 * @param string validated or pending or any relation ?
184 * @return array array of arrays with group_id of parent or childs
187 function getFamily($group_id, $order, $deep = false, $status = 'any') {
188 $localFamily = array();
191 $statusCondition = 't';
196 $statusCondition = 'f';
206 $qpa = db_construct_qpa(false, 'SELECT project_id as id FROM plugin_projects_hierarchy_relationship
207 WHERE sub_project_id = $1', array($group_id));
208 if (isset($statusCondition))
209 $qpa = db_construct_qpa($qpa, ' AND status = $1', array($statusCondition));
211 $res = db_query_qpa($qpa);
215 $qpa = db_construct_qpa(false, 'SELECT sub_project_id as id FROM plugin_projects_hierarchy_relationship
216 WHERE project_id = $1', array($group_id));
217 if (isset($statusCondition))
218 $qpa = db_construct_qpa($qpa, ' AND status = $1', array($statusCondition));
220 $res = db_query_qpa($qpa);
228 if ($res && db_numrows($res) > 0) {
229 while ($arr = db_fetch_array($res)) {
230 $localFamily[] = array($arr['id']);
235 for ( $i = 0; $i < count($localFamily); $i++) {
236 $localFamily[$i][] = $this->getFamily($localFamily[$i], $order, $deep, $status);
243 * getFamilyID - returns a flatted array containing all ids of the family, based on getFamily function.
245 * @param integer group_id to search for
246 * @param string parent or child ?
247 * @param boolean recurcive or not ?
248 * @param string validated or pending or any relation ?
249 * @return array flatted array with group_id of parent or childs
252 function getFamilyID($group_id, $order, $deep = false, $status = 'any') {
253 $familyFlatArray = array();
254 $familyArray = $this->getFamily($group_id, $order, $deep, $status);
255 array_walk_recursive($familyArray, create_function('$val, $key, $obj', 'array_push($obj, $val);'), &$familyFlatArray);
256 return $familyFlatArray;
260 * getDocmanStatus - returns the docman status for this project
262 * @param integer group_id
263 * @return boolean true/false
266 function getDocmanStatus($group_id) {
267 $res = db_query_params('SELECT docman FROM plugin_projects_hierarchy WHERE project_id = $1 limit 1',
272 $resArr = db_fetch_array($res);
273 if ($resArr['docman'] == 't')
280 * setDocmanStatus - allow parent to browse your document manager and allow yourself to select your childs to be browsed.
282 * @param integer your groud_id
283 * @param boolean the status to set
284 * @return boolean success or not
286 function setDocmanStatus($group_id, $status = 0) {
287 $res = db_query_params('UPDATE plugin_projects_hierarchy set docman = $1 WHERE project_id = $2',
288 array($status, $group_id));
297 * redirect - encapsulate session_redirect to handle correctly the redirection URL
299 * @param string usually http_referer from $_SERVER
300 * @param string type of feedback : error, warning, feedback
301 * @param string the message of feedback
304 function redirect($http_referer, $type, $message) {
315 $url = util_find_relative_referer($http_referer);
316 if (strpos($url,'?')) {
317 session_redirect($url.'&'.$type.'='.urlencode($message));
319 session_redirect($url.'?'.$type.'='.urlencode($message));
323 * override default groupisactivecheckboxpost function for init value in db
325 function groupisactivecheckboxpost(&$params) {
326 // this code actually activates/deactivates the plugin after the form was submitted in the project edit public info page
327 $group = group_get_object($params['group']);
328 $flag = strtolower('use_'.$this->name);
329 if ( getIntFromRequest($flag) == 1 ) {
330 $group->setPluginUse($this->name);
331 $this->add($group->getID());
333 $group->setPluginUse($this->name, false);
334 $this->remove($group->getID());
340 * add - add a new group_id using the plugin
342 * @param integer group_id
343 * @return boolean true on success
346 function add($group_id) {
347 if (!$this->exists($group_id)) {
348 $res = db_query_params('INSERT INTO plugin_projects_hierarchy (project_id) VALUES ($1)', array($group_id));
357 * remove - remove group_id using the plugin
359 * @param integer group_id
360 * @return boolean true on success
363 function remove($group_id) {
364 if ($this->exists($group_id)) {
366 $res = db_query_params('DELETE FROM plugin_projects_hierarchy where project_id = $1', array($group_id));
372 $res = db_query_params('DELETE FROM plugin_projects_hierarchy_relationship where project_id = $1 OR sub_project_id = $1',
384 * addChild - add a new child to this project
386 * @param integer group_id
387 * @param integer sub_group_id
388 * @return boolean true on success
391 function addChild($project_id, $sub_project_id) {
392 if ($this->exists($project_id) && $this->exists($sub_project_id)) {
393 if (!$this->hasRelation($project_id, $sub_project_id)) {
394 $res = db_query_params('INSERT INTO plugin_projects_hierarchy_relationship (project_id, sub_project_id)
395 VALUES ($1, $2)', array($project_id, $sub_project_id));
406 * removeChild - remove a child to this project
408 * @param integer group_id
409 * @param integer sub_group_id
410 * @return boolean true on success
413 function removeChild($project_id, $sub_project_id) {
414 if ($this->exists($project_id) && $this->exists($sub_project_id)) {
415 if ($this->hasRelation($project_id, $sub_project_id)) {
416 $res = db_query_params('DELETE FROM plugin_projects_hierarchy_relationship
417 WHERE project_id = $1 AND sub_project_id = $2',
418 array($project_id, $sub_project_id));
429 * removeParent - remove a parent to this project
431 * @param integer group_id
432 * @param integer sub_group_id
433 * @return boolean true on success
436 function removeParent($project_id, $sub_project_id) {
437 if ($this->exists($project_id) && $this->exists($sub_project_id)) {
438 if ($this->hasRelation($project_id, $sub_project_id)) {
439 $res = db_query_params('DELETE FROM plugin_projects_hierarchy_relationship
440 WHERE project_id = $1 AND sub_project_id = $2',
441 array($sub_project_id, $project_id));
452 * hasRelation - check if there is a relation child->parent or parent->child between 2 projects
454 * @param integer group_id
455 * @param integer sub_group_id
456 * @return boolean true on success
459 function hasRelation($project_id, $sub_project_id) {
460 if ($this->exists($project_id) && $this->exists($sub_project_id)) {
461 $res = db_query_params('SELECT * FROM plugin_projects_hierarchy_relationship
462 WHERE ( project_id = $1 AND sub_project_id = $2 )
463 OR ( project_id = $2 AND sub_project_id = $1 )',
464 array($project_id, $sub_project_id));
465 if ($res && db_numrows($res) == 1 )
472 * validateRelationship - validate or reject a relation between 2 projects
474 * @param integer group_id
475 * @param integer sub_group_id
476 * @param integer status of the relation
477 * @return boolean true on success
480 function validateRelationship($project_id, $sub_project_id, $status) {
481 if ($this->exists($project_id) && $this->exists($sub_project_id)) {
482 if ($this->hasRelation($project_id, $sub_project_id)) {
484 $res = db_query_params('UPDATE plugin_projects_hierarchy_relationship
486 WHERE project_id = $2 AND sub_project_id = $3',
487 array($status, $project_id, $sub_project_id));
491 if (db_affected_rows($res))
494 $res = db_query_params('DELETE FROM plugin_projects_hierarchy_relationship
495 WHERE project_id = $1 AND sub_project_id = $2',
496 array($project_id, $sub_project_id));
501 if (db_affected_rows($res))
510 * exists - if this project use the plugin
512 * @param integer group_id
513 * @return boolean true on success
516 function exists($group_id) {
517 $res = db_query_params('SELECT project_id FROM plugin_projects_hierarchy WHERE project_id = $1', array($group_id));
521 if (db_numrows($res))
528 * getAdminOptionLink - return the admin link url
530 * @return string html url
533 function getAdminOptionLink() {
534 return util_make_link('/plugins/'.$this->name.'/?type=globaladmin&pluginname='.$this->name,_('Global Hierarchy admin'));
538 * getHeader - initialize header and js
539 * @param string type : user, project (aka group)
540 * @return bool success or not
542 function getHeader($type) {
546 case 'globaladmin': {
547 session_require_global_perm('forge_admin');
549 require_once($gfwww.'admin/admin_utils.php');
550 site_admin_header(array('title'=>_('Site Global Hierarchy Admin'), 'toptab' => ''));
562 * getGlobalAdminView - display the global configuration view
564 * @return boolean True
567 function getGlobalAdminView() {
568 global $gfplugins, $use_tooltips;
569 include $gfplugins.$this->name.'/view/admin/viewGlobalConfiguration.php';
574 * getGlobalconf - return the global configuration defined at forge level
576 * @return array the global configuration array
578 function getGlobalconf() {
579 $resGlobConf = db_query_params('SELECT * from plugin_projects_hierarchy_global',array());
584 $row = db_numrows($resGlobConf);
586 if ($row == null || count($row) > 2) {
590 $resArr = db_fetch_array($resGlobConf);
591 $returnArr = array();
593 foreach($resArr as $column => $value) {
595 $returnArr[$column] = true;
597 $returnArr[$column] = false;
605 * getFooter - display footer
607 function getFooter() {
608 site_admin_footer(array());
612 * updateGlobalConf - update the global configuration in database
614 * @param array configuration array (tree, docman, delegate)
615 * @return bool true on success
617 function updateGlobalConf($confArr) {
618 if (!isset($confArr['tree']) || !isset($confArr['docman']) || !isset($confArr['delegate']))
621 $res = db_query_params('truncate plugin_projects_hierarchy_global',array());
625 $res = db_query_params('insert into plugin_projects_hierarchy_global (tree, docman, delegate)
626 values ($1, $2, $3)',
630 $confArr['delegate'],
639 * son_box - display a select box for son selection
641 * @param integer group_id
643 * @param string selected value
644 * @return string html box
647 function son_box($group_id, $name, $selected = 'xzxzxz') {
648 $sons = $this->getFamilyID($group_id, 'child', true, 'any');
649 $parent = $this->getFamilyID($group_id, 'parent', true, 'any');
650 $family = array_merge($parent, $sons);
651 $son = db_query_params('SELECT group_id, group_name FROM groups
654 AND group_id <> ALL ($3)
655 AND group_id NOT IN (SELECT sub_project_id FROM plugin_projects_hierarchy_relationship)
656 AND group_id IN (select group_id from group_plugin,plugins where group_plugin.plugin_id = plugins.plugin_id and plugins.plugin_name = $4);',
659 db_int_array_to_any_clause($family),
661 return html_build_select_box($son, $name, $selected, false);
666 // c-file-style: "bsd"