| +--------------------------------------------------------------------------+ | Author: Aleksander Machniak | +--------------------------------------------------------------------------+ */ class kolab_client_task_ou extends kolab_client_task { protected $ajax_only = true; protected $menu = array( 'add' => 'ou.add', ); protected $list_attribs = array('ou'); protected $search_attribs = array('name' => array('ou')); /** * Default action. */ public function action_default() { $this->output->set_object('content', 'ou', true); $this->output->set_object('task_navigation', $this->menu()); $this->action_list(); // display form to add OU if logged-in user has right to do so $caps = $this->get_capability('actions'); if (!empty($caps['ou.add'])) { $this->action_add(); } else { $this->output->command('set_watermark', 'taskcontent'); } } /** * Organizational unit adding (form) action. */ public function action_add() { $data = $this->get_input('data', 'POST'); $output = $this->ou_form(null, $data, true); $this->output->set_object('taskcontent', $output); } /** * Organizational unit information (form) action. */ public function action_info() { $id = $this->get_input('id', 'POST'); $result = $this->api_get('ou.info', array('id' => $id)); $unit = $result->get(); $output = $this->ou_form(null, $unit); $this->output->set_object('taskcontent', $output); } /** * OU list result handler, tree list builder */ protected function list_result_handler($result, $head, $foot, $table_class) { $result = $this->ou_list_sort($result); $result = $this->ou_list_build_tree($result, $max_tree_level); foreach ($result as $idx => $item) { $class = array('selectable'); $tree = ''; $style = ''; if ($item['level']) { $tree .= ''; $style = 'display:none'; } if ($item['has_children']) { $tree .= ''; } else if ($max_tree_level) { $tree .= ''; } $i++; $cells = array(); $cells[] = array( 'class' => 'name', 'body' => $tree . kolab_html::escape($item['name']), 'onclick' => "kadm.command('ou.info', '$idx')", ); $rows[] = array( 'id' => $i, 'class' => implode(' ', $class), 'cells' => $cells, 'style' => $style, 'data-level' => !empty($item['level']) ? $item['level'] : '', ); } if ($max_tree_level) { $this->output->command('tree_list_init'); } return array($rows, $head, '', $table_class . ' tree'); } private function ou_form($attribs, $data = array()) { if (empty($attribs['id'])) { $attribs['id'] = 'ou-form'; } // Form sections $sections = array( 'system' => 'ou.system', 'aci' => 'ou.aci', 'other' => 'ou.other', ); // field-to-section map and fields order $fields_map = array( 'type_id' => 'system', 'type_id_name' => 'system', 'ou' => 'system', 'base_dn' => 'system', 'description' => 'system', 'aci' => 'aci', ); // Prepare fields list($fields, $types, $type) = $this->form_prepare('ou', $data); $add_mode = empty($data['id']); $accttypes = array(); foreach ($types as $idx => $elem) { $accttypes[$idx] = array('value' => $idx, 'content' => $elem['name']); } // Add OU type id selector $fields['type_id'] = array( 'section' => 'system', 'type' => kolab_form::INPUT_SELECT, 'options' => $accttypes, 'onchange' => "kadm.ou_save(true, 'system')", ); // Hide account type selector if there's only one type if (count($accttypes) < 2 || !$add_mode) { //console("setting type_id form type to hidden"); $fields['type_id']['type'] = kolab_form::INPUT_HIDDEN; } $ou_roots = array_merge(array(''), $this->ou_list()); // Add OU root selector $fields['base_dn'] = array( 'section' => 'system', 'type' => kolab_form::INPUT_SELECT, 'options' => $ou_roots, 'escaped' => true, 'default' => $data['base_dn'], ); // Create mode if ($add_mode) { // Page title $title = $this->translate('ou.add'); } // Edit mode else { $title = $data['ou']; // Add OU type name $fields['type_id_name'] = array( 'label' => 'ou.type_id', 'section' => 'system', 'value' => $accttypes[$type]['content'], ); } // Create form object and populate with fields $form = $this->form_create('ou', $attribs, $sections, $fields, $fields_map, $data, $add_mode); $form->set_title(kolab_html::escape($title)); return $form->output(); } private function ou_list() { $result = $this->api_get('ous.list', null, array('page_size' => 999)); $list = (array) $result->get('list'); $sorted = $this->ou_list_sort($list); return $this->ou_list_build($sorted); } private function ou_list_sort($list) { // build the list for sorting foreach (array_keys($list) as $dn) { $name = kolab_utils::dn2ufn($dn); $name = explode(',', $name); $sort_name = array_pop($name) . ',' . implode(',', array_reverse($name)); $list[$dn] = mb_strtolower($sort_name); } // sort asort($list, SORT_LOCALE_STRING); return $list; } private function ou_list_build($list) { // @TODO: this code assumes parent always exist foreach (array_keys($list) as $dn) { $item = $this->parse_dn($dn); $list[$dn] = str_repeat('   ', $item['level']) . kolab_html::escape($item['name']); } return $list; } /** * Builds a tree from OUs list */ private function ou_list_build_tree($list, &$max_level) { $last = ''; $result = array(); foreach (array_keys($list) as $dn) { $item = $this->parse_dn($dn); if ($item['level']) { // create a parent unit entry if it does not exist (search result) $parent = $this->domain_dn($item['domain']); foreach ($item['path'] as $sub) { $parent = "ou=$sub,$parent"; if (!isset($result[$parent])) { $result[$parent] = $this->parse_dn($parent); $last = $parent; } $result[$parent]['has_children'] = true; } } $result[$dn] = $item; $last = $dn; $max_level = max($max_level, $item['level']); } return $result; } /** * Parse OU DN string into an array */ private function parse_dn($dn) { $path = kolab_utils::dn2ufn($dn); $path = explode(', ', $path); $domain = array_pop($path); // remove domain return array( 'name' => array_shift($path), 'path' => array_reverse($path), 'level' => count($path), 'domain' => $domain, ); } /** * Converts domain name into DN string */ private function domain_dn($domain) { return "dc=" . implode(',dc=', explode('.', $domain)); } }