Thomas Bruederli
2013-02-01 c5a5f989a9bf91927e6bb627f9f789800ce02fad
Allow to list contact groups in (paged) list (yet incomplete)
6 files modified
97 ■■■■ changed files
config/main.inc.php.dist 1 ●●●● patch | view | raw | blame | history
program/js/app.js 16 ●●●● patch | view | raw | blame | history
program/lib/Roundcube/rcube_ldap.php 32 ●●●●● patch | view | raw | blame | history
program/localization/en_US/labels.inc 1 ●●●● patch | view | raw | blame | history
program/steps/addressbook/func.inc 36 ●●●● patch | view | raw | blame | history
skins/larry/addressbook.css 11 ●●●●● patch | view | raw | blame | history
config/main.inc.php.dist
@@ -680,6 +680,7 @@
    'object_classes' => array("top", "groupOfNames"),
    'member_attr'  => 'member',   // name of the member attribute, e.g. uniqueMember
    'name_attr'    => 'cn',       // attribute to be used as group name
    'member_filter' => '(objectclass=*)',  // optional filter to use when querying for group members
  ),
);
*/
program/js/app.js
@@ -322,7 +322,7 @@
          this.env.contactfolders = $.extend($.extend({}, this.env.address_sources), this.env.contactgroups);
        this.enable_command('add', 'import', this.env.writable_source);
        this.enable_command('list', 'listgroup', 'listsearch', 'advanced-search', true);
        this.enable_command('list', 'listgroup', 'pushgroup', 'listsearch', 'advanced-search', true);
        if (this.gui_objects.contactslist) {
          this.contact_list = new rcube_list_widget(this.gui_objects.contactslist,
@@ -1080,6 +1080,8 @@
        }
        break;
      case 'pushgroup':
        // TODO: so some magic stuff here
      case 'listgroup':
        this.reset_qsearch();
        this.list_contacts(props.source, props.id);
@@ -4151,6 +4153,7 @@
  this.list_contacts_clear = function()
  {
    this.contact_list.data = {};
    this.contact_list.clear(true);
    this.show_contentframe(false);
    this.enable_command('delete', false);
@@ -4160,7 +4163,12 @@
  // load contact record
  this.load_contact = function(cid, action, framed)
  {
    var win, url = {}, target = window;
    var win, url = {}, target = window,
      rec = this.contact_list.data[cid];
    if (rec && rec.type == 'group') {
      alert('group ' + cid)
    }
    if (win = this.get_frame_window(this.env.contentframe)) {
      url._framed = 1;
@@ -4311,7 +4319,7 @@
  };
  // add row to contacts list
  this.add_contact_row = function(cid, cols, classes)
  this.add_contact_row = function(cid, cols, classes, data)
  {
    if (!this.gui_objects.contactslist)
      return false;
@@ -4333,6 +4341,8 @@
      row.appendChild(col);
    }
    // store data in list member
    list.data[cid] = data;
    list.insert_row(row);
    this.enable_command('export', list.rowcount > 0);
program/lib/Roundcube/rcube_ldap.php
@@ -657,6 +657,21 @@
        if (empty($entry[$attr]))
            return $group_members;
        // add group record to cache if it isn't yet there
        $group_id = self::dn_encode($dn);
        $group_cache = $this->cache->get('groups');
        if (!$group_cache[$group_id]) {
            $name_attr = $this->prop['groups']['name_attr'];
            $group_name = is_array($ldap_data[$i][$name_attr]) ? $ldap_data[$i][$name_attr][0] : $ldap_data[$i][$name_attr];
            $group_cache[$group_id]['ID'] = $group_id;
            $group_cache[$group_id]['dn'] = $dn;
            $group_cache[$group_id]['name'] = $group_name;
            $group_cache[$group_id]['member_attr'] = $this->get_group_member_attr($entry[$i]['objectclass']);
            $this->cache->set('groups', $group_cache);
        }
        // read these attributes for all members
        $attrib = $count ? array('dn') : array_values($this->fieldmap);
        $attrib[] = 'objectClass';
@@ -664,12 +679,14 @@
        $attrib[] = 'uniqueMember';
        $attrib[] = 'memberURL';
        $filter = $this->prop['groups']['member_filter'] ? $this->prop['groups']['member_filter'] : '(objectclass=*)';
        for ($i=0; $i < $entry[$attr]['count']; $i++)
        {
            if (empty($entry[$attr][$i]))
                continue;
            $result = @ldap_read($this->conn, $entry[$attr][$i], '(objectclass=*)',
            $result = @ldap_read($this->conn, $entry[$attr][$i], $filter,
                $attrib, 0, (int)$this->prop['sizelimit'], (int)$this->prop['timelimit']);
            $members = @ldap_get_entries($this->conn, $result);
@@ -1522,10 +1539,19 @@
     */
    private function _ldap2result($rec)
    {
        $out = array();
        $out = array('_type' => 'person');
        if ($rec['dn'])
            $out[$this->primary_key] = self::dn_encode($rec['dn']);
        // determine record type
        if (array_intersect(array('groupofuniquenames','kolabgroupofuniquenames'), (array)$rec['objectclass'])) {
            $out['_type'] = 'group';
            $out['readonly'] = true;
            if ($this->fieldmap['groupname']) {
                $this->fieldmap['name'] = $this->fieldmap['groupname'];
            }
        }
        foreach ($this->fieldmap as $rf => $lf)
        {
@@ -1780,7 +1806,7 @@
        for ($i=0; $i < $group_count; $i++)
        {
            $group_name = is_array($ldap_data[$i][$name_attr]) ? $ldap_data[$i][$name_attr][0] : $ldap_data[$i][$name_attr];
            $group_id = self::dn_encode($group_name);
            $group_id = self::dn_encode($ldap_data[$i]['dn']);
            $groups[$group_id]['ID'] = $group_id;
            $groups[$group_id]['dn'] = $ldap_data[$i]['dn'];
            $groups[$group_id]['name'] = $group_name;
program/localization/en_US/labels.inc
@@ -350,6 +350,7 @@
$labels['group'] = 'Group';
$labels['groups'] = 'Groups';
$labels['listgroup'] = 'List group members';
$labels['personaladrbook'] = 'Personal Addresses';
$labels['searchsave'] = 'Save search';
program/steps/addressbook/func.inc
@@ -310,7 +310,7 @@
    global $CONTACTS, $OUTPUT;
    // define list of cols to be displayed
    $a_show_cols = array('name');
    $a_show_cols = array('name','action');
    // add id to message list table if not specified
    if (!strlen($attrib['id']))
@@ -339,27 +339,51 @@
        return;
    // define list of cols to be displayed
    $a_show_cols = array('name');
    $a_show_cols = array('name','action');
    while ($row = $result->next()) {
        $row['CID'] = $row['ID'];
        $source_id = $OUTPUT->get_env('source');
        $a_row_cols = array();
        $classes = array('person');  // org records will follow some day
        $classes = array($row['_type'] ? $row['_type'] : 'person');
        // build contact ID with source ID
        if (isset($row['sourceid'])) {
            $row['ID'] = $row['ID'].'-'.$row['sourceid'];
            $source_id = $row['sourceid'];
        }
        // format each col
        foreach ($a_show_cols as $col) {
            $val = $col == 'name' ? rcube_addressbook::compose_list_name($row) : $row[$col];
            $a_row_cols[$col] = Q($val);
            $val = '';
            switch ($col) {
                case 'name':
                    $val = Q(rcube_addressbook::compose_list_name($row));
                    break;
                case 'action':
                    if ($row['_type'] == 'group') {
                        $val = html::a(array(
                            'href' => '#list',
                            'rel' => $row['ID'],
                            'title' => rcube_label('listgroup'),
                            'onclick' => sprintf("return %s.command('pushgroup',{'source':'%s','id':'%s'},this)", JS_OBJECT_NAME, $source_id, $row['CID']),
                        ), '&raquo;');
                    }
                    break;
                default:
                    $val = Q($row[$col]);
                    break;
            }
            $a_row_cols[$col] = $val;
        }
        if ($row['readonly'])
            $classes[] = 'readonly';
        $OUTPUT->command($prefix.'add_contact_row', $row['ID'], $a_row_cols, join(' ', $classes));
        $OUTPUT->command($prefix.'add_contact_row', $row['ID'], $a_row_cols, join(' ', $classes), $row);
    }
}
skins/larry/addressbook.css
@@ -141,6 +141,17 @@
    font-weight: bold;
}
#contacts-table .group td.name {
    background-position: 6px -1555px;
}
#contacts-table .group.selected td.name,
#contacts-table .group.unfocused td.name {
    background-position: 6px -1579px;
    font-weight: bold;
}
#contact-frame {
    position: absolute;
    top: 0;