X-Git-Url: https://git.tokkee.org/?a=blobdiff_plain;f=gosa-core%2Finclude%2Fclass_listing.inc;h=ef7e038c30b9a64fa145bdd5306112e639047671;hb=ed2e61f01da6d459cbfc9bda3aaeaa61db00eac8;hp=ed1354a844b57d3d0dee4d5a0e8dcd1896f44fe1;hpb=04ee5661105b2f508fa42264a320b66abfbc3142;p=gosa.git diff --git a/gosa-core/include/class_listing.inc b/gosa-core/include/class_listing.inc index ed1354a84..ef7e038c3 100644 --- a/gosa-core/include/class_listing.inc +++ b/gosa-core/include/class_listing.inc @@ -30,47 +30,104 @@ class listing { var $multiSelect= false; var $template; var $headline; - var $module; var $base; var $sortDirection= null; var $sortColumn= null; var $sortAttribute; var $sortType; + var $numColumns; var $baseMode= false; var $bases= array(); var $header= array(); var $colprops= array(); var $filters= array(); + var $filter= null; var $pid; - var $objectTypes; + var $objectTypes= array(); var $objectTypeCount= array(); + var $objectDnMapping= array(); + var $copyPasteHandler= null; + var $snapshotHandler= null; + var $exporter= array(); + var $exportColumns= array(); + var $useSpan= false; + var $height= 0; + var $scrollPosition= 0; + var $baseSelector; function listing($filename) { global $config; + global $class_mapping; + + // Initialize pid + $this->pid= preg_replace("/[^0-9]/", "", microtime(TRUE)); if (!$this->load($filename)) { die("Cannot parse $filename!"); } // Set base for filter - $this->base= session::global_get("CurrentMainBase"); - if ($this->base == null) { + if ($this->baseMode) { + $this->base= session::global_get("CurrentMainBase"); + if ($this->base == null) { + $this->base= $config->current['BASE']; + } + $this->refreshBasesList(); + } else { $this->base= $config->current['BASE']; } - $this->refreshBasesList(); // Move footer information $this->showFooter= ($config->get_cfg_value("listSummary") == "true"); // Register build in filters $this->registerElementFilter("objectType", "listing::filterObjectType"); + $this->registerElementFilter("departmentLink", "listing::filterDepartmentLink"); $this->registerElementFilter("link", "listing::filterLink"); $this->registerElementFilter("actions", "listing::filterActions"); - // Initialize pid - $this->pid= preg_replace("/[^0-9]/", "", microtime(TRUE)); + // Load exporters + foreach($class_mapping as $class => $dummy) { + if (preg_match('/Exporter$/', $class)) { + $info= call_user_func(array($class, "getInfo")); + if ($info != null) { + $this->exporter= array_merge($this->exporter, $info); + } + } + } + + // Instanciate base selector + $this->baseSelector= new baseSelector($this->bases, $this->base); + } + + + function setCopyPasteHandler($handler) + { + $this->copyPasteHandler= &$handler; + } + + + function setHeight($height) + { + $this->height= $height; + } + + + function setSnapshotHandler($handler) + { + $this->snapshotHandler= &$handler; + } + + + function setFilter($filter) + { + $this->filter= &$filter; + if ($this->departmentBrowser){ + $this->departments= $this->getDepartments(); + } + $this->filter->setBase($this->base); } @@ -104,12 +161,27 @@ class listing { } } - // Fill objectTypes + // Fill objectTypes from departments and xml definition + $types = departmentManagement::get_support_departments(); + foreach ($types as $class => $data) { + $this->objectTypes[$data['OC']]= array("label" => $data['TITLE'], + "objectClass" => $data['OC'], + "image" => $data['IMG']); + } + $this->categories= array(); if (isset($this->xmlData['definition']['objectType'])) { + if(isset($this->xmlData['definition']['objectType']['label'])) { + $this->xmlData['definition']['objectType']= array($this->xmlData['definition']['objectType']); + } foreach ($this->xmlData['definition']['objectType'] as $index => $otype) { - $this->objectTypes[]= $this->xmlData['definition']['objectType'][$index]; + $tmp = $this->xmlData['definition']['objectType'][$index]; + $this->objectTypes[$tmp['objectClass']]= $tmp; + if (isset($this->xmlData['definition']['objectType'][$index]['category'])){ + $this->categories[]= $otype['category']; + } } } + $this->objectTypes = array_values($this->objectTypes); // Parse layout per column $this->colprops= $this->parseLayout($this->xmlData['table']['layout']); @@ -117,9 +189,20 @@ class listing { // Prepare table headers $this->renderHeader(); - // Assign headline/module + // Assign headline/Categories $this->headline= _($this->xmlData['definition']['label']); - $this->module= $this->xmlData['definition']['module']; + if (!is_array($this->categories)){ + $this->categories= array($this->categories); + } + + // Evaluate columns to be exported + if (isset($this->xmlData['table']['column'])){ + foreach ($this->xmlData['table']['column'] as $index => $config) { + if (isset($config['export']) && $config['export'] == "true"){ + $this->exportColumns[]= $index; + } + } + } return true; } @@ -128,6 +211,7 @@ class listing { function renderHeader() { $this->header= array(); + $this->plainHeader= array(); // Initialize sort? $sortInit= false; @@ -154,116 +238,204 @@ class listing { isset($config['sortType'])) { $this->sortAttribute= $config['sortAttribute']; $this->sortType= $config['sortType']; - $sorter= " "; + $sorter= " ".image("images/lists/sort-".($this->sortDirection[$index]?"up":"down").".png", null, null, $this->sortDirection[$index]?_("Up"):_("Down"), "text-top"); } $sortable= (isset($config['sortAttribute'])); - $link= "href='?plug=".$_GET['plug']."&PID=$this->pid&act=SORT_$index'"; + $link= "href='?plug=".$_GET['plug']."&PID=".$this->pid."&act=SORT_$index'"; if (isset($config['label'])) { if ($sortable) { $this->header[$index]= "colprops[$index].">"._($config['label'])."$sorter"; } else { $this->header[$index]= "colprops[$index].">"._($config['label']).""; } + $this->plainHeader[]= _($config['label']); } else { if ($sortable) { $this->header[$index]= "colprops[$index]."> $sorter"; } else { $this->header[$index]= "colprops[$index]."> "; } + $this->plainHeader[]= ""; } } } } + function render() { -echo "department browsing, copypaste handler, snapshot handler, daemon handler
"; + // Check for exeeded sizelimit + if (($message= check_sizelimit()) != ""){ + return($message); + } + + // Some browsers don't have the ability do do scrollable table bodies, filter them + // here. + $switch= false; + if (preg_match('/(Opera|Konqueror|Safari)/i', $_SERVER['HTTP_USER_AGENT'])){ + $switch= true; + } // Initialize list - $result= ""; - $result.= "
"; - $result.= " -"; - - // New table for the real list contents - $result.= ""; + // Close list body + $result.= "
"; - $num_cols= count($this->colprops) + ($this->multiSelect?1:0); + $result= "\n"; + $result.= "\n"; + $height= 450; + if ($this->height != 0) { + $result.= "\n"; + $height= $this->height; + } + + $result.= "
\n"; + $result.= "
\n"; + $this->numColumns= count($this->colprops) + ($this->multiSelect?1:0); // Build list header - $result.= ""; + $result.= "\n"; if ($this->multiSelect) { - $result.= ""; + $width= "24px"; + if (preg_match('/Konqueror/i', $_SERVER['HTTP_USER_AGENT'])){ + $width= "28px"; + } + $result.= "\n"; } foreach ($this->header as $header) { $result.= $header; } + $result.= "\n"; - // Add 13px for scroller - $result.= "
 
"; + // Build list body + $result.= "\n"; // No results? Just take an empty colspanned row if (count($this->entries) + count($this->departments) == 0) { - $result.= ""; + $result.= ""; } - // Fill with department browser if configured this way -############### + // Line color alternation + $alt= 0; + $deps= 0; + + // Draw department browser if configured and we're not in sub mode + $this->useSpan= false; + if ($this->departmentBrowser && $this->filter->scope != "sub") { + // Fill with department browser if configured this way + $departmentIterator= new departmentSortIterator($this->departments, $this->sortDirection[$this->sortColumn]); + foreach ($departmentIterator as $row => $entry){ + $result.=""; + + // Render multi select if needed + if ($this->multiSelect) { + $result.=""; + } + + // Render defined department columns, fill the rest with some stuff + $rest= $this->numColumns - 1; + foreach ($this->xmlData['table']['department'] as $index => $config) { + $colspan= 1; + if (isset($config['span'])){ + $colspan= $config['span']; + $this->useSpan= true; + } + $result.=""; + $rest-= $colspan; + } + + // Fill remaining cols with nothing + $last= $this->numColumns - $rest; + for ($i= 0; $i<$rest; $i++){ + $result.= ""; + } + $result.=""; + + $alt++; + } + $deps= $alt; + } // Fill with contents, sort as configured - $entryIterator= new listingSortIterator($this->entries, $this->sortDirection[$this->sortColumn], $this->sortAttribute, $this->sortType); - foreach ($entryIterator as $row => $entry){ - $result.=""; + foreach ($this->entries as $row => $entry) { + $trow= ""; // Render multi select if needed if ($this->multiSelect) { - $result.=""; + $trow.="\n"; } foreach ($this->xmlData['table']['column'] as $index => $config) { - $result.=""; + $renderedCell= $this->renderCell($config['value'], $entry, $row); + $trow.="\n"; + + // Save rendered column + $sort= preg_replace('/.*>([^<]+)<.*$/', '$1', $renderedCell); + $sort= preg_replace('/ /', '', $sort); + if (preg_match('/entries[$row]["_sort$index"]= $sort; } - $result.=""; + + // Save rendered entry + $this->entries[$row]['_rendered']= $trow; + } + + // Complete list by sorting entries for _sort$index and appending them to the output + $entryIterator= new listingSortIterator($this->entries, $this->sortDirection[$this->sortColumn], "_sort".$this->sortColumn, $this->sortType); + foreach ($entryIterator as $row => $entry){ + $result.="\n"; + $result.= $entry['_rendered']; + $result.="\n"; + $alt++; } // Need to fill the list if it's not full (nobody knows why this is 22 ;-)) - $emptyListStyle= (count($this->entries) == 0)?"border:0;":""; - if (count($this->entries) < 22) { + $emptyListStyle= (count($this->entries) + (($this->useSpan && count($this->entries))?$deps:0) == 0)?"border:0;":""; + if ((count($this->entries) + $deps) < 22) { $result.= ""; - for ($i= 0; $i<$num_cols; $i++) { + for ($i= 0; $i<$this->numColumns; $i++) { if ($i == 0) { $result.= ""; continue; } - if ($i != $num_cols-1) { + if ($i != $this->numColumns-1) { $result.= ""; } else { - $result.= ""; + $result.= ""; } } $result.= ""; } - $result.= "
 
 
 colprops[$index]." class='list1'>".$this->renderCell($config['value'], $entry, $row)."colprops[$last+$i-1]." class='list1'> 
colprops[$index]." class='list0'>".$this->renderCell($config['value'], $entry, $row)."colprops[$index]." class='list0'>".$renderedCell."
    
"; // Add the footer if requested if ($this->showFooter) { - $result.= "
"; + $result.= "
"; foreach ($this->objectTypes as $objectType) { if (isset($this->objectTypeCount[$objectType['label']])) { $label= _($objectType['label']); - $result.= "$label ".$this->objectTypeCount[$objectType['label']]."    "; + $result.= image($objectType['image'], null, null, $label)." ".$this->objectTypeCount[$objectType['label']]."  "; } } - $result.= "
 
"; + $result.= ""; } - $result.= ""; + // Close list + $result.= $switch?"":""; + + // Add scroll positioner + $result.= ''; $smarty= get_smarty(); + $smarty->assign("usePrototype", "true"); $smarty->assign("FILTER", $this->filter->render()); + $smarty->assign("SIZELIMIT", print_sizelimit_warning()); $smarty->assign("LIST", $result); // Assign navigation elements @@ -282,18 +454,15 @@ echo "department browsing, copypaste handler, snapshot handler, daemon handlerassign("HEADLINE", $this->headline); - return ($smarty->fetch(get_template_path($this->xmlData['definition']['template'], true))); - } + // Try to load template from plugin the folder first... + $file = get_template_path($this->xmlData['definition']['template'], true); - - function setFilter($filter) - { - $this->filter= &$filter; - if ($this->departmentBrowser){ - # $this->departments= $this->filter->getDepartments(); + // ... if this fails, try to load the file from the theme folder. + if(!file_exists($file)){ + $file = get_template_path($this->xmlData['definition']['template']); } - $this->filter->setBase($this->base); - $this->entries= $this->filter->query(); + + return ($smarty->fetch($file)); } @@ -302,73 +471,144 @@ echo "department browsing, copypaste handler, snapshot handler, daemon handlerpid) { - return; + // Take care of base selector + if ($this->baseMode) { + $this->baseSelector->update(); + // Check if a wrong base was supplied + if(!$this->baseSelector->checkLastBaseUpdate()){ + msg_dialog::display(_("Error"), msgPool::check_base(), ERROR_DIALOG); + } } - if ($this->departmentBrowser){ - # $this->departments= $this->filter->getDepartments(); + // Save base + $refresh= false; + if ($this->baseMode) { + $this->base= $this->baseSelector->getBase(); + session::global_set("CurrentMainBase", $this->base); + $refresh= true; } - // Save base - if (isset($_POST['BASE']) && $this->baseMode == true) { - $base= validate($_POST['BASE']); - if (isset($this->bases[$base])) { - $this->base= $base; + + // Reset object counter / DN mapping + $this->objectTypeCount= array(); + $this->objectDnMapping= array(); + + // Do not do anything if this is not our PID + if($refresh || !(isset($_REQUEST['PID']) && $_REQUEST['PID'] != $this->pid)) { + + // Save position if set + if (isset($_POST['position_'.$this->pid]) && is_numeric($_POST['position_'.$this->pid])) { + $this->scrollPosition= $_POST['position_'.$this->pid]; } - } - // Filter GET with "act" attributes - if (isset($_GET['act'])) { - $key= validate($_GET['act']); - if (preg_match('/^SORT_([0-9]+)$/', $key, $match)) { - // Switch to new column or invert search order? - $column= $match[1]; - if ($this->sortColumn != $column) { - $this->sortColumn= $column; - } else { - $this->sortDirection[$column]= !$this->sortDirection[$column]; + // Override the base if we got a message from the browser navigation + if ($this->departmentBrowser && isset($_GET['act'])) { + if (preg_match('/^department_([0-9]+)$/', validate($_GET['act']), $match)){ + if (isset($this->departments[$match[1]])){ + $this->base= $this->departments[$match[1]]['dn']; + if ($this->baseMode) { + $this->baseSelector->setBase($this->base); + } + session::global_set("CurrentMainBase", $this->base); + } } + } - // Allow header to update itself according to the new sort settings - $this->renderHeader(); + // Filter POST with "act" attributes -> posted from action menu + if (isset($_POST['exec_act']) && $_POST['act'] != '') { + if (preg_match('/^export.*$/', $_POST['act']) && isset($this->exporter[$_POST['act']])) { + $exporter= $this->exporter[$_POST['act']]; + $userinfo= ", "._("created by")." ".$ui->cn." - ".strftime('%A, %d. %B %Y, %H:%M:%S'); + $entryIterator= new listingSortIterator($this->entries, $this->sortDirection[$this->sortColumn], "_sort".$this->sortColumn, $this->sortType); + $sortedEntries= array(); + foreach ($entryIterator as $entry){ + $sortedEntries[]= $entry; + } + $instance= new $exporter['class']($this->headline.$userinfo, $this->plainHeader, $sortedEntries, $this->exportColumns); + $type= call_user_func(array($exporter['class'], "getInfo")); + $type= $type[$_POST['act']]; + send_binary_content($instance->query(), $type['filename'], $type= $type['mime']); + } } - } - // Override base if we got signals from the navigation elements - $action= ""; - foreach ($_POST as $key => $value) { - if (preg_match('/^(ROOT|BACK|HOME)_x$/', $key, $match)) { - $action= $match[1]; - break; + // Filter GET with "act" attributes + if (isset($_GET['act'])) { + $key= validate($_GET['act']); + if (preg_match('/^SORT_([0-9]+)$/', $key, $match)) { + // Switch to new column or invert search order? + $column= $match[1]; + if ($this->sortColumn != $column) { + $this->sortColumn= $column; + } else { + $this->sortDirection[$column]= !$this->sortDirection[$column]; + } + + // Allow header to update itself according to the new sort settings + $this->renderHeader(); + } } - } - // Navigation handling - if ($action == 'ROOT') { - $deps= $ui->get_module_departments($this->module); - $this->base= $deps[0]; - } - if ($action == 'BACK') { - $deps= $ui->get_module_departments($this->module); - $base= preg_replace("/^[^,]+,/", "", $this->base); - if(in_array_ics($base, $deps)){ - $this->base= $base; + // Override base if we got signals from the navigation elements + $action= ""; + foreach ($_POST as $key => $value) { + if (preg_match('/^(ROOT|BACK|HOME)(_x)?$/', $key, $match)) { + $action= $match[1]; + break; + } + } + + // Navigation handling + if ($action == 'ROOT') { + $deps= $ui->get_module_departments($this->categories); + $this->base= $deps[0]; + $this->baseSelector->setBase($this->base); + session::global_set("CurrentMainBase", $this->base); + } + if ($action == 'BACK') { + $deps= $ui->get_module_departments($this->categories); + $base= preg_replace("/^[^,]+,/", "", $this->base); + if(in_array_ics($base, $deps)){ + $this->base= $base; + $this->baseSelector->setBase($this->base); + session::global_set("CurrentMainBase", $this->base); + } + } + if ($action == 'HOME') { + $ui= get_userinfo(); + $this->base= get_base_from_people($ui->dn); + $this->baseSelector->setBase($this->base); + session::global_set("CurrentMainBase", $this->base); } - } - if ($action == 'HOME') { - $ui= get_userinfo(); - $this->base= get_base_from_people($ui->dn); } - // Check sorting - if (isset($_GET['SORT'])) { + // Reload departments + if ($this->departmentBrowser){ + $this->departments= $this->getDepartments(); } // Update filter and refresh entries $this->filter->setBase($this->base); $this->entries= $this->filter->query(); + + // Fix filter if querie returns NULL + if ($this->entries == null) { + $this->entries= array(); + } + } + + + function setBase($base) + { + $this->base= $base; + if ($this->baseMode) { + $this->baseSelector->setBase($this->base); + } + } + + + function getBase() + { + return $this->base; } @@ -377,36 +617,48 @@ echo "department browsing, copypaste handler, snapshot handler, daemon handler $config) { if ($config != "") { - $components= split(';', $config); - $config= ""; + $res= ""; + $components= explode(';', $config); foreach ($components as $part) { if (preg_match("/^r$/", $part)) { - $config.= "text-align:right;"; + $res.= "text-align:right;"; continue; } if (preg_match("/^l$/", $part)) { - $config.= "text-align:left;"; + $res.= "text-align:left;"; continue; } if (preg_match("/^c$/", $part)) { - $config.= "text-align:center;"; + $res.= "text-align:center;"; continue; } if (preg_match("/^[0-9]+(|px|%)$/", $part)) { - $config.= "width:$part;"; + $res.= "width:$part;min-width:$part;"; continue; } } - $result[$index]= " style='$config' "; + // Add minimum width for scalable columns + if (!preg_match('/width:/', $res)){ + $res.= "min-width:200px;"; + } + + $result[$index]= " style='$res'"; } else { - $result[$index]= null; + $result[$index]= " style='min-width:100px;'"; } } + // Save number of columns for later use + $this->numColumns= count($cols); + + // Add no border to the last column + $result[$this->numColumns-1]= preg_replace("/'$/", "border-right:0;'", $result[$this->numColumns-1]); + return $result; } @@ -428,39 +680,21 @@ echo "department browsing, copypaste handler, snapshot handler, daemon handlerprocessElementFilter($data, $config, $row); + // Replace all non replaced %{...} instances because they + // are non resolved attributes or filters + $data= preg_replace('/%{[^}]+}/', ' ', $data); + return $data; } function renderBase() { - $result= ""; - - // Reset the currently used base to the first DN we found if there - // was no match. - if(!$found){ - $this->base = $firstDN; + if (!$this->baseMode) { + return; } - return $result; + return $this->baseSelector->render(); } @@ -469,11 +703,18 @@ echo "department browsing, copypaste handler, snapshot handler, daemon handlerfilters[$match[1]])) { - continue; + $cl= ""; + $method= ""; + if (preg_match('/::/', $match[1])) { + $cl= preg_replace('/::.*$/', '', $match[1]); + $method= preg_replace('/^.*::/', '', $match[1]); + } else { + if (!isset($this->filters[$match[1]])) { + continue; + } + $cl= preg_replace('/::.*$/', '', $this->filters[$match[1]]); + $method= preg_replace('/^.*::/', '', $this->filters[$match[1]]); } - $cl= preg_replace('/::.*$/', '', $this->filters[$match[1]]); - $method= preg_replace('/^.*::/', '', $this->filters[$match[1]]); // Prepare params for function call $params= array(); @@ -483,16 +724,31 @@ echo "department browsing, copypaste handler, snapshot handler, daemon handlerpid; + continue; + } + + // base is replaced by the current base + if ($param == "base") { + $params[]= $this->getBase(); + continue; } // Fixie with "" is passed directly if (preg_match('/^".*"$/', $param)){ $params[]= preg_replace('/"/', '', $param); + continue; + } + + // Move dn if needed + if ($param == "dn") { + $params[]= LDAP::fix($config["dn"]); + continue; } // LDAP variables get replaced by their objects @@ -503,13 +759,9 @@ echo "department browsing, copypaste handler, snapshot handler, daemon handlergetObjectType($this->objectTypes, $classes); if ($objectType) { - $result= ""; + $this->objectDnMapping[$dn]= $objectType["objectClass"]; + $result= image($objectType["image"], null, null, LDAP::fix($dn)); if (!isset($this->objectTypeCount[$objectType['label']])) { $this->objectTypeCount[$objectType['label']]= 0; } $this->objectTypeCount[$objectType['label']]++; } + return $result; } @@ -587,10 +841,29 @@ echo "department browsing, copypaste handler, snapshot handler, daemon handlerxmlData['actiontriggers']['action']; foreach($actions as $action) { // Skip the entry completely if there's no permission to execute it - if (!$this->hasActionPermission($action, $dn)) { + if (!$this->hasActionPermission($action, $dn, $classes)) { + $result.= image('images/empty.png'); continue; } + // Skip entry if the pseudo filter does not fit + if (isset($action['filter']) && preg_match('/^[a-z0-9_]+!?=[a-z0-9_]+$/i', $action['filter'])) { + list($fa, $fv)= explode('=', $action['filter']); + if (preg_match('/^(.*)!$/', $fa, $m)){ + $fa= $m[1]; + if (isset($this->entries[$row][$fa]) && $this->entries[$row][$fa][0] == $fv) { + $result.= image('images/empty.png'); + continue; + } + } else { + if (!isset($this->entries[$row][$fa]) && !$this->entries[$row][$fa][0] == $fv) { + $result.= image('images/empty.png'); + continue; + } + } + } + + // If there's an objectclass definition and we don't have it // add an empty picture here. if (isset($action['objectclass'])){ @@ -598,12 +871,17 @@ echo "department browsing, copypaste handler, snapshot handler, daemon handlerprocessElementFilter($action['label'], $this->entries[$row], $row); $image= $this->processElementFilter($action['image'], $this->entries[$row], $row); - $result.=""; + $result.= image($image, null, "listing_".$action['name']."_$row", $label); } // Handle special types - if ($action['type'] == "snapshot") { - #TODO - #echo "actiontriggers: snapshot missing
"; - } - if ($action['type'] == "copypaste") { - #TODO - #echo "actiontriggers: copypaste missing
"; - } - if ($action['type'] == "daemon") { - #TODO - #echo "actiontriggers: daemon missing
"; - } + if ($action['type'] == "copypaste" || $action['type'] == "snapshot") { + $objectType= $this->getObjectType($this->objectTypes, $this->entries[$row]['objectClass']); + $category= $class= null; + if ($objectType) { + $category= $objectType['category']; + $class= $objectType['class']; + } + + if ($action['type'] == "copypaste") { + $copy = !isset($action['copy']) || $action['copy'] == "true"; + $cut = !isset($action['cut']) || $action['cut'] == "true"; + $result.= $this->renderCopyPasteActions($row, $this->entries[$row]['dn'], $category, $class,$copy,$cut); + } else { + $result.= $this->renderSnapshotActions($row, $this->entries[$row]['dn'], $category, $class); + } + } } return $result; } + function filterDepartmentLink($row, $dn, $description) + { + $attr= $this->departments[$row]['sort-attribute']; + $name= $this->departments[$row][$attr]; + if (is_array($name)){ + $name= $name[0]; + } + $result= sprintf("%s [%s]", $name, $description[0]); + return("pid&act=department_$row' title='$dn'>$result"); + } + + function filterLink() { $result= " "; $row= func_get_arg(0); - $pid= func_get_arg(1); - $dn= LDAP::fix(func_get_arg(2)); - $params= array(func_get_arg(3)); + $pid= $this->pid; + $dn= LDAP::fix(func_get_arg(1)); + $params= array(func_get_arg(2)); // Collect sprintf params - for ($i = 4;$i < func_num_args();$i++) { + for ($i = 3;$i < func_num_args();$i++) { $val= func_get_arg($i); if (is_array($val)){ $params[]= $val[0]; @@ -676,7 +969,7 @@ echo "department browsing, copypaste handler, snapshot handler, daemon handlerget_module_departments($this->module); + $deps = $ui->get_module_departments($this->categories); if(!count($deps) || $deps[0] == $this->filter->base){ $enableBack = false; @@ -686,37 +979,35 @@ echo "department browsing, copypaste handler, snapshot handler, daemon handlerfilter->base == get_base_from_people($ui->dn)){ + if(!count($deps) || $this->filter->base == get_base_from_people($ui->dn)){ $enableHome = false; } /* Draw root button */ if($enableRoot){ - $result["ROOT"]= ""; + $result["ROOT"]= image('images/lists/root.png', null, 'ROOT', _("Root")); }else{ - $result["ROOT"]= ""._("Root").""; + $result["ROOT"]= image('images/lists/root-grey.png', null, null, _("Root")); } /* Draw back button */ if($enableBack){ - $result["BACK"]= ""; + $result["BACK"]= image('images/lists/back.png', null, 'BACK', _("Go up one department")); }else{ - $result["BACK"]= ""._("Up").""; + $result["BACK"]= image('images/lists/back-grey.png', null, null, _("Go up one department")); } /* Draw home button */ + /* Draw home button */ if($enableHome){ - $result["HOME"]= ""; + $result["HOME"]= image('images/lists/home.png', null, 'HOME', _("Go to users department")); }else{ - $result["HOME"]= ""._("Home").""; + $result["HOME"]= image('images/lists/home-grey.png', null, null, _("Go to users department")); } + /* Draw reload button, this button is enabled everytime */ - $result["RELOAD"]= ""; + $result["RELOAD"]= image('images/lists/reload.png', null, 'REFRESH', _("Reload list")); return ($result); } @@ -724,11 +1015,16 @@ echo "department browsing, copypaste handler, snapshot handler, daemon handlerpid) { + // Do not do anything if this is not our PID, or there's even no PID available... + if(!isset($_REQUEST['PID']) || $_REQUEST['PID'] != $this->pid) { return; } + // Save position if set + if (isset($_POST['position_'.$this->pid]) && is_numeric($_POST['position_'.$this->pid])) { + $this->scrollPosition= $_POST['position_'.$this->pid]; + } + $result= array("targets" => array(), "action" => ""); // Filter GET with "act" attributes @@ -778,7 +1074,9 @@ echo "department browsing, copypaste handler, snapshot handler, daemon handler posted from action menu if (isset($_POST['act']) && $_POST['act'] != '') { - $result['action']= validate($_POST['act']); + if (!preg_match('/^export.*$/', $_POST['act'])){ + $result['action']= validate($_POST['act']); + } } // Drop targets if empty @@ -796,11 +1094,15 @@ echo "department browsing, copypaste handler, snapshot handler, daemon handlerxmlData['actionmenu']['action']['type'])){ + $this->xmlData['actionmenu']['action']= array($this->xmlData['actionmenu']['action']); + } + // Load shortcut $actions= &$this->xmlData['actionmenu']['action']; - $result= "". - "
  • Aktionen "; + $result= "
    ". + "
    • "._("Actions")." ".image("images/lists/sort-down.png").""; // Build ul/li list $result.= $this->recurseActions($actions); @@ -811,6 +1113,7 @@ echo "department browsing, copypaste handler, snapshot handler, daemon handler "; + $img= image($action['image'])." "; } if ($action['type'] == "separator"){ @@ -837,8 +1150,14 @@ echo "department browsing, copypaste handler, snapshot handler, daemon handler"; + $result.= "$img"._($action['label'])." ".image('images/forward-arrow.png').""; + } + + // Ensure we've an array of actions, this enables sub menus with only one action. + if(isset($action['action']['type'])){ + $action['action'] = array($action['action']); } + $result.= $this->recurseActions($action['action'])."
    • "; $level--; $separator= ""; @@ -853,18 +1172,21 @@ echo "department browsing, copypaste handler, snapshot handler, daemon handler"; + $cut = !isset($action['cut']) || $action['cut'] != "false"; + $copy = !isset($action['copy']) || $action['copy'] != "false"; + $result.= $this->renderCopyPasteMenu($separator, $copy , $cut); break; case 'snapshot': - #TODO - #echo "actionmenu: snapshot missing
      "; + $result.= $this->renderSnapshotMenu($separator); + break; + + case 'exporter': + $result.= $this->renderExporterMenu($separator); break; case 'daemon': - #TODO - #echo "actionmenu: daemon missing
      "; + $result.= $this->renderDaemonMenu($separator); break; } @@ -876,7 +1198,7 @@ echo "department browsing, copypaste handler, snapshot handler, daemon handlermodule; - $acllist= array(); + $module= $this->categories; + $aclList= array(); + + // Replace %acl if available + if ($classes) { + $otype= $this->getObjectType($this->objectTypes, $classes); + $acl= str_replace('%acl', $otype['category']."/".$otype['class'], $acl); + } // Split for category and plugins if needed // match for "[rw]" style entries @@ -912,7 +1240,7 @@ echo "department browsing, copypaste handler, snapshot handler, daemon handlerget_permissions($dn, $module, $m[1]); $sAcl= $m[2]; @@ -955,7 +1283,7 @@ echo "department browsing, copypaste handler, snapshot handler, daemon handleridepartments; - $d= $ui->get_module_departments($this->module); + $d= $ui->get_module_departments($this->categories); $k_ids= array_keys($ids); $deps= array_intersect($d,$k_ids); @@ -964,9 +1292,278 @@ echo "department browsing, copypaste handler, snapshot handler, daemon handlerbases[$department] = $ids[$department]; } + + // Populate base selector if already present + if ($this->baseSelector && $this->baseMode) { + $this->baseSelector->setBases($this->bases); + $this->baseSelector->update(TRUE); + } + } + + + function getDepartments() + { + $departments= array(); + $ui= get_userinfo(); + + // Get list of supported department types + $types = departmentManagement::get_support_departments(); + + // Load departments allowed by ACL + $validDepartments = $ui->get_module_departments($this->categories); + + // Build filter and look in the LDAP for possible sub departments + // of current base + $filter= "(&(objectClass=gosaDepartment)(|"; + $attrs= array("description", "objectClass"); + foreach($types as $name => $data){ + $filter.= "(objectClass=".$data['OC'].")"; + $attrs[]= $data['ATTR']; + } + $filter.= "))"; + $res= get_list($filter, $this->categories, $this->base, $attrs, GL_NONE); + + // Analyze list of departments + foreach ($res as $department) { + if (!in_array($department['dn'], $validDepartments)) { + continue; + } + + // Add the attribute where we use for sorting + $oc= null; + foreach(array_keys($types) as $type) { + if (in_array($type, $department['objectClass'])) { + $oc= $type; + break; + } + } + $department['sort-attribute']= $types[$oc]['ATTR']; + + // Move to the result list + $departments[]= $department; + } + + return $departments; + } + + + function renderCopyPasteMenu($separator, $copy= true, $cut= true) + { + // We can only provide information if we've got a copypaste handler + // instance + if(!(isset($this->copyPasteHandler) && is_object($this->copyPasteHandler))){ + return ""; + } + + // Presets + $result= ""; + $read= $paste= false; + $ui= get_userinfo(); + + // Switch flags to on if there's at least one category which allows read/paste + foreach($this->categories as $category){ + $read= $read || preg_match('/r/', $ui->get_category_permissions($this->base, $category)); + $paste= $paste || $ui->is_pasteable($this->base, $category) == 1; + } + + + // Draw entries that allow copy and cut + if($read){ + + // Copy entry + if($copy){ + $result.= "".image('images/lists/copy.png')." "._("Copy").""; + $separator= ""; + } + + // Cut entry + if($cut){ + $result.= "".image("images/lists/cut.png")." "._("Cut").""; + $separator= ""; + } + } + + // Draw entries that allow pasting entries + if($paste){ + if($this->copyPasteHandler->entries_queued()){ + $result.= "".image("images/lists/paste.png")." "._("Paste").""; + }else{ + $result.= "".image('images/lists/paste-grey.png')." "._("Paste").""; + } + } + + return($result); + } + + + function renderCopyPasteActions($row, $dn, $category, $class, $copy= true, $cut= true) + { + // We can only provide information if we've got a copypaste handler + // instance + if(!(isset($this->copyPasteHandler) && is_object($this->copyPasteHandler))){ + return ""; + } + + // Presets + $ui = get_userinfo(); + $result = ""; + + // Render cut entries + if($cut){ + if($ui->is_cutable($dn, $category, $class)){ + $result.= image('images/lists/cut.png', null, "listing_cut_$row", _("Cut this entry")); + }else{ + $result.= image('images/empty.png'); + } + } + + // Render copy entries + if($copy){ + if($ui->is_copyable($dn, $category, $class)){ + $result.= image('images/lists/copy.png', null, "listing_copy_$row", _("Copy this entry")); + }else{ + $result.= image('images/empty.png'); + } + } + + return($result); + } + + + function renderSnapshotMenu($separator) + { + // We can only provide information if we've got a snapshot handler + // instance + if(!(isset($this->snapshotHandler) && is_object($this->snapshotHandler))){ + return ""; + } + + // Presets + $result = ""; + $ui = get_userinfo(); + + if($this->snapshotHandler->enabled() && $ui->allow_snapshot_restore($this->base, $this->categories)){ + + // Check if there is something to restore + $restore= false; + foreach($this->snapshotHandler->getSnapshotBases() as $base){ + $restore= $restore || count($this->snapshotHandler->getDeletedSnapshots($base)) > 0; + } + + // Draw icons according to the restore flag + if($restore){ + $result.= "".image('images/lists/restore.png')." "._("Restore snapshots").""; + }else{ + $result.= "".image('images/lists/restore_grey.png')." "._("Restore snapshots").""; + } + } + + return($result); + } + + + function renderExporterMenu($separator) + { + // Presets + $result = ""; + + // Draw entries + $result.= "".image('images/lists/export.png')." "._("Export list")." ".image("images/forward-arrow.png").""; + + return($result); + } + + + function renderSnapshotActions($row, $dn, $category, $class, $copy= true, $cut= true) + { + // We can only provide information if we've got a snapshot handler + // instance + if(!(isset($this->snapshotHandler) && is_object($this->snapshotHandler))){ + return ""; + } + + // Presets + $result= ""; + $ui = get_userinfo(); + + // Only act if enabled here + if($this->snapshotHandler->enabled()){ + + // Draw restore button + if ($ui->allow_snapshot_restore($dn, $category)){ + + // Do we have snapshots for this dn? + if($this->snapshotHandler->hasSnapshots($dn)){ + $result.= image('images/lists/restore.png', null, "listing_restore_$row", _("Restore snapshot")); + } else { + $result.= image('images/lists/restore_grey.png'); + } + } + + // Draw snapshot button + if($ui->allow_snapshot_create($dn, $category)){ + $result.= image('images/snapshot.png', null, "listing_snapshot_$row", _("Create a new snapshot from this object")); + }else{ + $result.= image('images/empty.png'); + } + } + + return($result); } + function renderDaemonMenu($separator) + { + $result= ""; + + // If there is a daemon registered, draw the menu entries + if(class_available("DaemonEvent")){ + $events= DaemonEvent::get_event_types_by_category($this->categories); + if(isset($events['BY_CLASS']) && count($events['BY_CLASS'])){ + foreach($events['BY_CLASS'] as $name => $event){ + $result.= "".$event['MenuImage']." ".$event['s_Menu_Name'].""; + $separator= ""; + } + } + } + + return $result; + } + + + function getEntry($dn) + { + foreach ($this->entries as $entry) { + if (isset($entry['dn']) && strcasecmp($dn, $entry['dn']) == 0){ + return $entry; + } + } + return null; + } + + + function getEntries() + { + return $this->entries; + } + + + function getType($dn) + { + if (isset($this->objectDnMapping[$dn])) { + return $this->objectDnMapping[$dn]; + } + return null; + } + } ?>