From 7d5c41fe44d0ee442505f45f934b60e7bf7e43a6 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?C=C3=B4me=20Bernigaud?= <come.bernigaud@laposte.net>
Date: Fri, 2 Aug 2013 16:15:44 +0200
Subject: [PATCH] Fixes: #2596 Departements should be based on simplePlugin

---
 plugins/admin/departments/class_country.inc   |  50 ++
 .../departments/class_countryGeneric.inc      | 100 ----
 plugins/admin/departments/class_dcObject.inc  |  72 +--
 .../admin/departments/class_department.inc    | 435 +++++-------------
 .../class_departmentManagement.inc            |  23 -
 plugins/admin/departments/class_domain.inc    |  72 +--
 plugins/admin/departments/class_locality.inc  |  51 ++
 .../departments/class_localityGeneric.inc     | 100 ----
 .../admin/departments/class_organization.inc  |  48 ++
 .../departments/class_organizationGeneric.inc | 139 ------
 plugins/admin/departments/country.tpl         |  62 ---
 plugins/admin/departments/dcObject.tpl        |  62 ---
 plugins/admin/departments/domain.tpl          |  62 ---
 plugins/admin/departments/generic.tpl         | 133 ------
 plugins/admin/departments/locality.tpl        |  61 ---
 plugins/admin/departments/organization.tpl    | 133 ------
 plugins/admin/departments/tabs_department.inc |  61 +--
 17 files changed, 308 insertions(+), 1356 deletions(-)
 create mode 100644 plugins/admin/departments/class_country.inc
 delete mode 100644 plugins/admin/departments/class_countryGeneric.inc
 create mode 100644 plugins/admin/departments/class_locality.inc
 delete mode 100644 plugins/admin/departments/class_localityGeneric.inc
 create mode 100644 plugins/admin/departments/class_organization.inc
 delete mode 100644 plugins/admin/departments/class_organizationGeneric.inc
 delete mode 100644 plugins/admin/departments/country.tpl
 delete mode 100644 plugins/admin/departments/dcObject.tpl
 delete mode 100644 plugins/admin/departments/domain.tpl
 delete mode 100644 plugins/admin/departments/generic.tpl
 delete mode 100644 plugins/admin/departments/locality.tpl
 delete mode 100644 plugins/admin/departments/organization.tpl

diff --git a/plugins/admin/departments/class_country.inc b/plugins/admin/departments/class_country.inc
new file mode 100644
index 000000000..2bf41d2ca
--- /dev/null
+++ b/plugins/admin/departments/class_country.inc
@@ -0,0 +1,50 @@
+<?php
+/*
+  This code is part of FusionDirectory (http://www.fusiondirectory.org/)
+  Copyright (C) 2013  FusionDirectory
+
+  This program is free software; you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation; either version 2 of the License, or
+  (at your option) any later version.
+
+  This program is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with this program; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
+*/
+
+class country extends department
+{
+  static $namingAttr  = "c";
+  var $structuralOC   = array("country");
+
+  static function plInfo()
+  {
+    return array(
+      "plShortName"   => _("Country"),
+      "plDescription" => _("Country"),
+      "plCategory"    => array("department"),
+      "plObjectType"  => array("country" => array(
+        "aclCategory" => "department",
+        "name"        => _("Country"),
+        "filter"      => "objectClass=country")
+      ),
+
+      "plProvidedAcls" => parent::generatePlProvidedAcls(self::getAttributesInfo())
+    );
+  }
+
+  static function getAttributesInfo ()
+  {
+    $attributesInfo = parent::getDepartmentAttributesInfo(_('country'), self::$namingAttr);
+    unset($attributesInfo['location']);
+    unset($attributesInfo['properties']['attrs'][3]); // category
+    return $attributesInfo;
+  }
+}
+?>
diff --git a/plugins/admin/departments/class_countryGeneric.inc b/plugins/admin/departments/class_countryGeneric.inc
deleted file mode 100644
index 25ac3e7e0..000000000
--- a/plugins/admin/departments/class_countryGeneric.inc
+++ /dev/null
@@ -1,100 +0,0 @@
-<?php
-
-/*
-  This code is part of FusionDirectory (http://www.fusiondirectory.org/)
-  Copyright (C) 2003  Cajus Pollmeier
-  Copyright (C) 2011-2013  FusionDirectory
-
-  This program is free software; you can redistribute it and/or modify
-  it under the terms of the GNU General Public License as published by
-  the Free Software Foundation; either version 2 of the License, or
-  (at your option) any later version.
-
-  This program is distributed in the hope that it will be useful,
-  but WITHOUT ANY WARRANTY; without even the implied warranty of
-  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-  GNU General Public License for more details.
-
-  You should have received a copy of the GNU General Public License
-  along with this program; if not, write to the Free Software
-  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
-*/
-
-class country extends department
-{
-  /* attribute list for save action */
-  var $attributes     = array( "c", "ou", "description", "manager");
-  var $objectclasses  = array("top", "gosaDepartment");
-  var $structuralOC   = array("country");
-  var $type           = "country";
-  var $c              = "";
-  var $orgi_c         = "";
-
-  var $namingAttr       = "c";
-  var $manager_name     = "";
-  var $manager          = "";
-
-
-  function check()
-  {
-    $message = plugin::check();
-
-    /* Check for presence of this department */
-    $ldap = $this->config->get_ldap_link();
-    $ldap->ls ("(&(c=".$this->c.")(objectClass=country))", $this->base, array('dn'));
-    if ($this->orig_c == "new" && $ldap->count()) {
-      $message[] = msgPool::duplicated(_("Name"));
-    } elseif ($this->orig_dn != $this->dn && $ldap->count()) {
-      $message[] = msgPool::duplicated(_("Name"));
-    }
-
-    /* All required fields are set? */
-    if ($this->c == "") {
-      $message[] = msgPool::required(_("Name"));
-    } elseif (tests::is_department_name_reserved($this->c, $this->base)) {
-      $message[] = msgPool::reserved(_("Name"));
-    } elseif (preg_match ('/[#+:=>\\\\\/]/', $this->c)) {
-      $message[] = msgPool::invalid(_("Name"), $this->c, "/[^#+:=>\\\\\/]/");
-    }
-
-    /* Check description */
-    if ($this->description == "") {
-      $message[] = msgPool::required(_("Description"));
-    }
-
-    /* Check if we are allowed to create or move this object
-     */
-    if ($this->orig_dn == "new" && !$this->acl_is_createable($this->base)) {
-      $message[] = msgPool::permCreate();
-    } elseif ($this->orig_dn != "new" && $this->base != $this->orig_base && !$this->acl_is_moveable($this->base)) {
-      $message[] = msgPool::permMove();
-    }
-
-    return $message;
-  }
-
-
-  /* Return plugin informations for acl handling */
-  static function plInfo()
-  {
-    return array(
-      "plShortName"   => _("Country"),
-      "plDescription" => _("Country"),
-      "plSelfModify"  => FALSE,
-      "plCategory"    => array("department"),
-      "plObjectType"  => array("country" => array(
-        "aclCategory" => "department",
-        "name"        => _("Country"),
-        "filter"      => "objectClass=country")
-      ),
-
-      "plProvidedAcls" => array(
-        "c"                 => _("Country name"),
-        "description"       => _("Description"),
-        "manager"           => _("Manager"),
-        "base"              => _("Base"),
-      )
-    );
-  }
-}
-?>
diff --git a/plugins/admin/departments/class_dcObject.inc b/plugins/admin/departments/class_dcObject.inc
index 4d1429adc..7eb2a3dab 100644
--- a/plugins/admin/departments/class_dcObject.inc
+++ b/plugins/admin/departments/class_dcObject.inc
@@ -1,9 +1,7 @@
 <?php
-
 /*
   This code is part of FusionDirectory (http://www.fusiondirectory.org/)
-  Copyright (C) 2003  Cajus Pollmeier
-  Copyright (C) 2011-2013  FusionDirectory
+  Copyright (C) 2013 FusionDirectory
 
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
@@ -22,66 +20,15 @@
 
 class dcObject extends department
 {
-  /* attribute list for save action */
-  var $attributes     = array("dc", "ou", "description", "manager");
+  static $namingAttr  = "dc";
   var $objectclasses  = array("top", "dcObject", "gosaDepartment");
   var $structuralOC   = array("locality");
 
-  var $type       = "dcObject";
-  var $dc         = "";
-  var $orgi_dc    = "";
-  var $namingAttr = "dc";
-
-  var $manager_name     = "";
-  var $manager          = "";
-
-
-  function check()
-  {
-    $message = plugin::check();
-
-    /* Check for presence of this department */
-    $ldap = $this->config->get_ldap_link();
-    $ldap->ls ("(&(dc=".$this->dc.")(objectClass=dcObject))", $this->base, array('dn'));
-    if ($this->orig_dc == "new" && $ldap->count()) {
-      $message[] = msgPool::duplicated(_("Name"));
-    } elseif ($this->orig_dn != $this->dn && $ldap->count()) {
-      $message[] = msgPool::duplicated(_("Name"));
-    }
-
-    /* All required fields are set? */
-    if ($this->dc == "") {
-      $message[] = msgPool::required(_("Name"));
-    } elseif (tests::is_department_name_reserved($this->dc, $this->base)) {
-      $message[] = msgPool::reserved(_("Name"));
-    } elseif (!preg_match ('/[a-z0-9 \.,\-_]/i', $this->dc)) {
-      $message[] = msgPool::invalid(_("Name"), $this->dc, "/[a-z0-9 \.,\-_]/");
-    }
-
-    /* Check description */
-    if ($this->description == "") {
-      $message[] = msgPool::required(_("Description"));
-    }
-
-    /* Check if we are allowed to create or move this object
-     */
-    if ($this->orig_dn == "new" && !$this->acl_is_createable($this->base)) {
-      $message[] = msgPool::permCreate();
-    } elseif ($this->orig_dn != "new" && $this->base != $this->orig_base && !$this->acl_is_moveable($this->base)) {
-      $message[] = msgPool::permMove();
-    }
-
-    return $message;
-  }
-
-
-  /* Return plugin informations for acl handling */
   static function plInfo()
   {
     return array(
       "plShortName"   => _("Domain Component"),
       "plDescription" => _("Domain Component"),
-      "plSelfModify"  => FALSE,
       "plCategory"    => array("department"),
       "plObjectType"  => array("dcObject" => array(
         "aclCategory" => "department",
@@ -89,13 +36,16 @@ class dcObject extends department
         "filter"      => "objectClass=dcObject")
       ),
 
-      "plProvidedAcls" => array(
-        "dc"                => _("Name"),
-        "description"       => _("Description"),
-        "manager"           => _("Manager"),
-        "base"              => _("Base"),
-      )
+      "plProvidedAcls" => parent::generatePlProvidedAcls(self::getAttributesInfo())
     );
   }
+
+  static function getAttributesInfo ()
+  {
+    $attributesInfo = parent::getDepartmentAttributesInfo(_('domain component'), self::$namingAttr);
+    unset($attributesInfo['location']);
+    unset($attributesInfo['properties']['attrs'][3]); // category
+    return $attributesInfo;
+  }
 }
 ?>
diff --git a/plugins/admin/departments/class_department.inc b/plugins/admin/departments/class_department.inc
index 050955e0a..4b8464889 100644
--- a/plugins/admin/departments/class_department.inc
+++ b/plugins/admin/departments/class_department.inc
@@ -19,44 +19,95 @@
   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
 */
 
-class department extends plugin
+class department extends simplePlugin
 {
-  /* department attributes */
-  var $ou           = "";
-  var $description  = "";
-  var $base         = "";
-  var $st           = "";
-  var $l            = "";
-
-  var $postalAddress            = "";
-  var $businessCategory         = "";
-  var $telephoneNumber          = "";
-  var $facsimileTelephoneNumber = "";
-  var $view_logged              = FALSE;
-
-  var $type       = "organizationalUnit";
-  var $namingAttr = "ou";
-
-  /* Headpage attributes */
-  var $last_dep_sorting = "invalid";
-  var $departments      = array();
-
-  /* attribute list for save action */
-  var $attributes = array("ou", "description", "businessCategory", "st", "l", "postalAddress",
-      "telephoneNumber", "facsimileTelephoneNumber", "manager");
+  static $namingAttr = 'ou';
 
   /* Do not append the structural object classes here, they are added dynamically in the constructor */
   var $objectclasses  = array("top", "gosaDepartment");
   var $structuralOC   = array("organizationalUnit");
+  var $mainTab        = TRUE;
 
-  var $orig_base  = "";
-  var $orig_ou    = "";
-  var $baseSelector;
+  static function plInfo()
+  {
+    return array(
+      "plShortName"   => _("Generic"),
+      "plDescription" => _("Departments"),
+      "plCategory"    => array("department" => array("objectClass" => "gosaDepartment", "description" => _("Departments"))),
+      "plObjectType"  =>
+        array(
+          "department" => array(
+            "name"    => _("Department"),
+            "filter"  => "objectClass=gosaDepartment"
+          )
+        ),
+
+      "plProvidedAcls" => parent::generatePlProvidedAcls(self::getAttributesInfo())
+    );
+  }
 
-  var $manager_name     = "";
-  var $manager          = "";
+  static function getAttributesInfo()
+  {
+    return self::getDepartmentAttributesInfo(_('department'), self::$namingAttr);
+  }
+  static function getDepartmentAttributesInfo($name, $namingAttr)
+  {
+    $attributesInfo = array(
+      'properties' => array(
+        'name'  => _('Properties'),
+        'icon'  => 'images/rightarrow.png',
+        'attrs' => array(
+          new BaseSelectorAttribute(''),
+          new HostNameAttribute(
+            sprintf(_('Name of %s'), $name), sprintf(_('A name for this %s'), $name),
+            $namingAttr, TRUE
+          ),
+          new TextAreaAttribute(
+            _('Description'), sprintf(_('Short description of this %s'), $name),
+            'description', TRUE
+          ),
+          new StringAttribute(
+            _('Category'), sprintf(_('Category of this %s'), $name),
+            'businessCategory', FALSE
+          ),
+          new UserAttribute(
+            _('Manager'), sprintf(_('Manager of this %s'), $name),
+            'manager', FALSE
+          )
+        )
+      ),
+      'location' => array(
+        'name'  => _('Location'),
+        'icon'  => 'plugins/departments/images/department.png',
+        'attrs' => array(
+          new StringAttribute(
+            _('State'), _('State'), 'st', FALSE
+          ),
+          new StringAttribute(
+            _('Location'), _('Location'), 'l', FALSE
+          ),
+          new TextAreaAttribute(
+            _('Address'), sprintf(_('A postal address for this %s'), $name),
+            'postalAddress', FALSE
+          ),
+          new PhoneNumberAttribute(
+            _('Phone'), _('Telephone number'),
+            'telephoneNumber', FALSE
+          ),
+          new PhoneNumberAttribute(
+            _('Fax'), _('Facsimile telephone number'),
+            'facsimileTelephoneNumber', FALSE
+          ),
+        )
+      ),
+    );
+    if ($namingAttr != 'ou') {
+      $attributesInfo['properties']['attrs'][] = new HiddenAttribute('ou');
+    }
+    return $attributesInfo;
+  }
 
-  function __construct (&$config, $dn)
+  function __construct (&$config, $dn = NULL, $object = NULL)
   {
     /* Add the default structural object class if this is a new entry */
     $ldap = $config->get_ldap_link();
@@ -78,320 +129,80 @@ class department extends plugin
     }
     $this->objectclasses = array_unique($this->objectclasses);
 
-    parent::__construct($config, $dn);
-    $this->is_account = TRUE;
-    $this->ui         = get_userinfo();
-    $this->dn         = $dn;
-    $this->orig_dn    = $dn;
+    parent::__construct($config, $dn, $object);
 
-    /* Save current naming attribute
-     */
-    $nA             = $this->namingAttr;
-    $orig_nA        = "orig_".$nA;
-    $this->$orig_nA = $this->$nA;
+    $this->attributesAccess[$this->getNamingAttr()]->setUnique(TRUE);
+  }
 
-    $this->config = $config;
+  function getNamingAttr()
+  {
+    $class = get_class($this);
+    return $class::$namingAttr;
+  }
 
-    /* Set base */
-    if ($this->dn == "new") {
-      $ui = get_userinfo();
-      if (session::is_set('CurrentMainBase')) {
-        $this->base = session::get('CurrentMainBase');
-      } else {
-        $this->base = dn2base($ui->dn);
-      }
-    } else {
-      $this->base = preg_replace ("/^[^,]+,/", "", $this->dn);
-    }
-    $this->orig_base = $this->base;
+  /* Check values */
+  function check()
+  {
+    /* Call common method to give check the hook */
+    $message = parent::check();
 
-    /* Instanciate base selector */
-    $this->baseSelector = new baseSelector($this->get_allowed_bases(), $this->base);
-    $this->baseSelector->setSubmitButton(FALSE);
-    $this->baseSelector->setHeight(300);
-    $this->baseSelector->update(TRUE);
+    $namingAttr = $this->getNamingAttr();
 
-    // Detect the managers name
-    $this->manager_name = "";
-    $ldap = $this->config->get_ldap_link();
-    if (!empty($this->manager)) {
-      $ldap->cat($this->manager, array('cn'));
-      if ($ldap->count()) {
-        $attrs = $ldap->fetch();
-        $this->manager_name = $attrs['cn'][0];
-      } else {
-        $this->manager_name = "("._("Unknown")."!): ".$this->manager;
-      }
+    if (tests::is_department_name_reserved($this->$namingAttr, $this->base)) {
+      $message[] = msgPool::reserved(_("Name"));
     }
+
+    return $message;
   }
 
   function execute()
   {
-    /* Call parent execute */
-    parent::execute();
-
-    /* Log view */
-    if ($this->is_account && !$this->view_logged) {
-      $this->view_logged = TRUE;
-      new log("view", "department/".get_class($this), $this->dn);
-    }
-
     /* Reload departments */
     $this->config->get_departments($this->dn);
     $this->config->make_idepartments();
-    $smarty = get_smarty();
-    $smarty->assign("usePrototype", "true");
-
-    // Clear manager attribute if requested
-    if (preg_match("/ removeManager/i", " ".implode(array_keys($_POST), ' ')." ")) {
-      $this->manager      = "";
-      $this->manager_name = "";
-    }
-
-    // Allow to manager manager attribute
-
-    // Allow to select a new inetOrgPersion:manager
-    if (preg_match("/ editManager/i", " ".implode(array_keys($_POST), ' ')." ")) {
-      $this->dialog = new singleUserSelect($this->config, get_userinfo());
-    }
-    if ($this->dialog && count($this->dialog->detectPostActions())) {
-      $users = $this->dialog->detectPostActions();
-      if (isset($users['targets']) && count($users['targets'])) {
-        $headpage = $this->dialog->getHeadpage();
-        $dn       = $users['targets'][0];
-        $attrs    = $headpage->getEntry($dn);
-
-        $this->manager      = $dn;
-        $this->manager_name = $attrs['cn'][0];
-        $this->dialog       = NULL;
-      }
-    }
-    if (isset($_POST['add_users_cancel'])) {
-      $this->dialog = NULL;
-    }
-    if ($this->dialog) {
-      return $this->dialog->execute();
-    }
-
-    $smarty->assign("manager", $this->manager);
-    $smarty->assign("manager_name", $this->manager_name);
 
-    $tmp = $this->plInfo();
-    foreach ($tmp['plProvidedAcls'] as $name => $translation) {
-      $smarty->assign($name."ACL", $this->getacl($name));
-    }
-
-    /* Hide base selector, if this object represents the base itself
-     */
-    $smarty->assign("is_root_dse", FALSE);
-    if ($this->dn == $this->config->current['BASE']) {
-      $smarty->assign("is_root_dse", TRUE);
-      $nA = $this->namingAttr."ACL";
-      $smarty->assign($nA, $this->getacl($this->namingAttr, TRUE));
-    }
-
-    $this->baseSelector->setBases($this->get_allowed_bases());
-
-    foreach ($this->attributes as $val) {
-      $smarty->assign("$val", htmlentities($this->$val, ENT_COMPAT, 'UTF-8'));
-    }
-    $smarty->assign("base", $this->baseSelector->render());
-
-    $smarty->assign("dep_type", $this->type);
-
-    $dep_types = departmentManagement::get_support_departments();
-    $tpl = "";
-    foreach ($dep_types as $data) {
-      if ($data['OC'] == $this->type) {
-        $tpl = $data['TPL'];
-        break;
-      }
-    }
-    if ($tpl == "") {
-      trigger_error("No template specified for container type '".$this->type."', please update departmentManagement::get_support_departments().");
-      $tpl = "generic.tpl";
-    }
-    return $smarty->fetch(get_template_path($tpl, TRUE));
+    /* Call parent execute */
+    return parent::execute();
   }
 
   function get_allowed_bases()
   {
     /* Hide all departments, that are subtrees of this department */
     $bases = parent::get_allowed_bases();
-    if (($this->dn == "new") || ($this->dn == "")) {
-      return $bases;
-    } else {
-      $tmp = array();
-      foreach ($bases as $dn => $base) {
-        /* Only attach departments which are not a subtree of this one */
-        if (!preg_match("/".preg_quote($this->dn)."/", $dn)) {
-          $tmp[$dn] = $base;
+    if (($this->dn != "new") && ($this->dn != "")) {
+      foreach (array_keys($bases) as $dn) {
+        if (preg_match("/".preg_quote($this->dn)."/", $dn)) {
+          unset($bases[$dn]);
         }
       }
-      return $tmp;
     }
+    return $bases;
   }
 
-  function remove_from_parent()
+  function compute_dn()
   {
-    $ldap = $this->config->get_ldap_link();
-    $ldap->cd ($this->dn);
-    $ldap->rmdir_recursive($this->dn);
-    new log("remove", "department/".get_class($this), $this->dn, array_keys($this->attrs), $ldap->get_error());
-    if (!$ldap->success()) {
-      msg_dialog::display(_("LDAP error"), msgPool::ldaperror($ldap->get_error(), $this->dn, LDAP_DEL, get_class()));
-    }
-
-    /* Optionally execute a command after we're done */
-    $this->handle_post_events('remove');
+    $namingAttr = $this->getNamingAttr();
+    $nAV  = preg_replace('/,/', '\,', $this->$namingAttr);
+    $nAV  = preg_replace('/"/', '\"', $nAV);
+    return @LDAP::convert(self::$namingAttr.'='.$nAV.','.$this->base);
   }
 
-  /* Save data to object */
-  function save_object()
+  function prepare_save()
   {
-    if (isset($_POST['dep_generic_posted'])) {
-
-      $nA     = $this->namingAttr;
-      $old_nA = $this->$nA;
-
-      /* Create a base backup and reset the
-         base directly after calling plugin::save_object();
-         Base will be set seperatly a few lines below */
-      $base_tmp = $this->base;
-      parent::save_object();
-      $this->base = $base_tmp;
-
-      /* Refresh base */
-      if ($this->acl_is_moveable($this->base)) {
-        if (!$this->baseSelector->update()) {
-          msg_dialog::display(_("Error"), msgPool::permMove(), ERROR_DIALOG);
-        }
-        if ($this->base != $this->baseSelector->getBase()) {
-          $this->base         = $this->baseSelector->getBase();
-          $this->is_modified  = TRUE;
-        }
-      }
-
-      /* If this is the root directory service entry then avoid
-         changing the naming attribute of this entry.
-       */
-      if ($this->dn == $this->config->current['BASE']) {
-        $this->$nA = $old_nA;
-      }
+    if ($this->getNamingAttr() != 'ou') {
+      $this->attributesAccess['ou']->setValue($this->attributesAccess[$this->getNamingAttr()]->getValue());
     }
+    return parent::prepare_save();
   }
+}
+    /* Hide base selector, if this object represents the base itself
 
-  /* Check values */
-  function check()
-  {
-    /* Call common method to give check the hook */
-    $message = plugin::check();
-
-    /* Check for presence of this department */
-    $ldap = $this->config->get_ldap_link();
-    $ldap->ls ("(&(ou=".$this->ou.")(objectClass=organizationalUnit))", $this->base, array('dn'));
-    if ($this->orig_dn == "new" && $ldap->count()) {
-      $message[] = msgPool::duplicated(_("Name"));
-    } elseif ($this->orig_dn != $this->dn && $ldap->count()) {
-      $message[] = msgPool::duplicated(_("Name"));
-    }
-
-    /* All required fields are set? */
-    if ($this->ou == "") {
-      $message[] = msgPool::required(_("Name"));
-    }
-    if ($this->description == "") {
-      $message[] = msgPool::required(_("Description"));
-    }
-
-    if (tests::is_department_name_reserved($this->ou, $this->base)) {
-      $message[] = msgPool::reserved(_("Name"));
-    }
-
-    if (preg_match ('/[#+:=>\\\\\/]/', $this->ou)) {
-      $message[] = msgPool::invalid(_("Name"), $this->ou, "/[^#+:=>\\\\\/]/");
-    }
-    if (!tests::is_phone_nr($this->telephoneNumber)) {
-      $message[] = msgPool::invalid(_("Phone"), $this->telephoneNumber, "/[\/0-9 ()+*-]/");
-    }
-    if (!tests::is_phone_nr($this->facsimileTelephoneNumber)) {
-      $message[] = msgPool::invalid(_("Fax"), $this->facsimileTelephoneNumber, "/[\/0-9 ()+*-]/");
-    }
-
-    // Check if a wrong base was supplied
-    if (!$this->baseSelector->checkLastBaseUpdate()) {
-      $message[] = msgPool::check_base();
-    }
-
-    /* Check if we are allowed to create or move this object
-     */
-    if ($this->orig_dn == "new" && !$this->acl_is_createable($this->base)) {
-      $message[] = msgPool::permCreate();
-    } elseif ($this->orig_dn != "new" && $this->base != $this->orig_base && !$this->acl_is_moveable($this->base)) {
-      $message[] = msgPool::permMove();
-    }
-
-    return $message;
-  }
-
-  /* Save to LDAP */
-  function save()
-  {
-    $ldap = $this->config->get_ldap_link();
-
-    /* Ensure that ou is saved too, it is required by objectClass gosaDepartment
-     */
-    $nA       = $this->namingAttr;
-    $this->ou = $this->$nA;
-
-    parent::save();
-
-    /* Write back to ldap */
-    $ldap->cat($this->dn, array('dn'));
-    $ldap->cd($this->dn);
-
-    if ($ldap->count()) {
-      $this->cleanup();
-      $ldap->modify ($this->attrs);
-      new log("modify", "department/".get_class($this), $this->dn, array_keys($this->attrs), $ldap->get_error());
-      $this->handle_post_events('modify');
-    } else {
-      $ldap->add($this->attrs);
-      $this->handle_post_events('add');
-      new log("create", "department/".get_class($this), $this->dn, array_keys($this->attrs), $ldap->get_error());
-    }
-    if (!$ldap->success()) {
-      msg_dialog::display(_("LDAP error"), msgPool::ldaperror($ldap->get_error(), $this->dn, 0, get_class()));
-    }
-
-    return FALSE;
-  }
-
-  /* Return plugin informations for acl handling */
-  static function plInfo()
-  {
-    return array(
-      "plShortName"   => _("Generic"),
-      "plDescription" => _("Departments"),
-      "plSelfModify"  => FALSE,
-      "plCategory"    => array("department" => array("objectClass" => "gosaDepartment", "description" => _("Departments"))),
-      "plObjectType"  => array("department" => array("name" => _("Department"), "filter" => "objectClass=gosaDepartment")),
-
-      "plProvidedAcls" => array(
-        "ou"                => _("Department name"),
-        "description"       => _("Description"),
-        "businessCategory"  => _("Category"),
-        "base"              => _("Base"),
+    $smarty->assign("is_root_dse", FALSE);
+    if ($this->dn == $this->config->current['BASE']) {
+      $smarty->assign("is_root_dse", TRUE);
+      $nA = $this->namingAttr."ACL";
+      $smarty->assign($nA, $this->getacl($this->namingAttr, TRUE));
+    }*/
 
-        "st"                        => _("State"),
-        "l"                         => _("Location"),
-        "postalAddress"             => _("Address"),
-        "telephoneNumber"           => _("Telephone"),
-        "facsimileTelephoneNumber"  => _("Fax"),
-        "manager"                   => _("Manager"),
-      )
-    );
-  }
-}
 
 ?>
diff --git a/plugins/admin/departments/class_departmentManagement.inc b/plugins/admin/departments/class_departmentManagement.inc
index edbc28303..59322cf4b 100644
--- a/plugins/admin/departments/class_departmentManagement.inc
+++ b/plugins/admin/departments/class_departmentManagement.inc
@@ -71,29 +71,6 @@ class departmentManagement extends management
     $this->registerAction("new_dcObject",           "newEntry");
     $this->registerAction("new_organization",       "newEntry");
     $this->registerAction("new_organizationalUnit", "newEntry");
-    $this->registerAction("performRecMove",         "performRecMove");
-    $this->registerAction("tagDepartment",          "tagDepartment");
-  }
-
-  // Inject additional actions here.
-  function detectPostActions()
-  {
-    $actions = management::detectPostActions();
-    if (isset($_GET['PerformRecMove'])) {
-      $actions['action'] = "performRecMove";
-    }
-    if (isset($_GET['TagDepartment'])) {
-      $actions['action'] = "tagDepartment";
-    }
-    return $actions;
-  }
-
-  // Action handler which allows department tagging - Creates the iframe contents.
-  function tagDepartment()
-  {
-    $plugname = $this->last_tabObject->base_name;
-    $this->last_tabObject->by_object[$plugname]->tag_objects();
-    exit();
   }
 
   // Overridden new handler - We've different types of departments to create!
diff --git a/plugins/admin/departments/class_domain.inc b/plugins/admin/departments/class_domain.inc
index f804b6111..5609a5d5a 100644
--- a/plugins/admin/departments/class_domain.inc
+++ b/plugins/admin/departments/class_domain.inc
@@ -1,9 +1,7 @@
 <?php
-
 /*
   This code is part of FusionDirectory (http://www.fusiondirectory.org/)
-  Copyright (C) 2003  Cajus Pollmeier
-  Copyright (C) 2011-2013  FusionDirectory
+  Copyright (C) 2013  FusionDirectory
 
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
@@ -22,66 +20,15 @@
 
 class domain extends department
 {
-  /* attribute list for save action */
-  var $attributes     = array( "dc", "ou", "description", "manager");
+  static $namingAttr  = "dc";
   var $objectclasses  = array("top", "domain", "gosaDepartment");
   var $structuralOC   = array("domain");
-  var $type           = "domain";
-  var $dc             = "";
-  var $orgi_dc        = "";
-  var $namingAttr     = "dc";
-
-  var $manager_name     = "";
-  var $manager          = "";
-
-
-  function check()
-  {
-    $message = plugin::check();
-
-    /* Check for presence of this department */
-    $ldap = $this->config->get_ldap_link();
-    $ldap->ls ("(&(dc=".$this->dc.")(objectClass=domain))", $this->base, array('dn'));
-    if ($this->orig_dc == "new" && $ldap->count()) {
-      $message[] = msgPool::duplicated(_("Name"));
-    } elseif ($this->orig_dn != $this->dn && $ldap->count()) {
-      $message[] = msgPool::duplicated(_("Name"));
-    }
-
-    /* All required fields are set? */
-    if ($this->dc == "") {
-      $message[] = msgPool::required(_("Name"));
-    } elseif (tests::is_department_name_reserved($this->dc, $this->base)) {
-      $message[] = msgPool::reserved(_("Name"));
-    } elseif (!preg_match ('/[a-z0-9 \.,\-_]/i', $this->dc)) {
-      $message[] = msgPool::invalid(_("Name"), $this->dc, "/[a-z0-9 \.,\-_]/");
-    }
-
-    /* Check description */
-    if ($this->description == "") {
-      $message[] = msgPool::required(_("Description"));
-    }
 
-    /* Check if we are allowed to create or move this object
-     */
-    if ($this->orig_dn == "new" && !$this->acl_is_createable($this->base)) {
-      $message[] = msgPool::permCreate();
-    } elseif ($this->orig_dn != "new" && $this->base != $this->orig_base && !$this->acl_is_moveable($this->base)) {
-      $message[] = msgPool::permMove();
-    }
-
-    return $message;
-  }
-
-
-  /* Return plugin informations for acl handling */
   static function plInfo()
   {
     return array(
       "plShortName"   => _("Domain"),
       "plDescription" => _("Domain"),
-      "plSelfModify"  => FALSE,
-      "plPriority"    => 4,
       "plCategory"    => array("department"),
       "plObjectType"  => array("domain" => array(
         "aclCategory" => "department",
@@ -89,13 +36,16 @@ class domain extends department
         "filter"      => "objectClass=domain")
       ),
 
-      "plProvidedAcls" => array(
-        "dc"                => _("Name"),
-        "description"       => _("Description"),
-        "base"              => _("Base"),
-        "manager"           => _("Manager"),
-      )
+      "plProvidedAcls" => parent::generatePlProvidedAcls(self::getAttributesInfo())
     );
   }
+
+  static function getAttributesInfo ()
+  {
+    $attributesInfo = parent::getDepartmentAttributesInfo(_('domain'), self::$namingAttr);
+    unset($attributesInfo['location']);
+    unset($attributesInfo['properties']['attrs'][3]); // category
+    return $attributesInfo;
+  }
 }
 ?>
diff --git a/plugins/admin/departments/class_locality.inc b/plugins/admin/departments/class_locality.inc
new file mode 100644
index 000000000..0dbfa06a5
--- /dev/null
+++ b/plugins/admin/departments/class_locality.inc
@@ -0,0 +1,51 @@
+<?php
+/*
+  This code is part of FusionDirectory (http://www.fusiondirectory.org/)
+  Copyright (C) 2013  FusionDirectory
+
+  This program is free software; you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation; either version 2 of the License, or
+  (at your option) any later version.
+
+  This program is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with this program; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
+*/
+
+class locality extends department
+{
+  static $namingAttr  = "l";
+  var $objectclasses  = array("top", "gosaDepartment");
+  var $structuralOC   = array("locality");
+
+  static function plInfo()
+  {
+    return array(
+      "plShortName"   => _("Locality"),
+      "plDescription" => _("Locality"),
+      "plCategory"    => array("department"),
+      "plObjectType"  => array("locality" => array(
+        "aclCategory" => "department",
+        "name"        => _("Locality"),
+        "filter"      => "objectClass=locality")
+      ),
+
+      "plProvidedAcls" => parent::generatePlProvidedAcls(self::getAttributesInfo())
+    );
+  }
+
+  static function getAttributesInfo ()
+  {
+    $attributesInfo = parent::getDepartmentAttributesInfo(_('locality'), self::$namingAttr);
+    unset($attributesInfo['location']);
+    unset($attributesInfo['properties']['attrs'][3]); // category
+    return $attributesInfo;
+  }
+}
+?>
diff --git a/plugins/admin/departments/class_localityGeneric.inc b/plugins/admin/departments/class_localityGeneric.inc
deleted file mode 100644
index 3d3d004a6..000000000
--- a/plugins/admin/departments/class_localityGeneric.inc
+++ /dev/null
@@ -1,100 +0,0 @@
-<?php
-/*
-  This code is part of FusionDirectory (http://www.fusiondirectory.org/)
-  Copyright (C) 2003  Cajus Pollmeier
-  Copyright (C) 2011-2013  FusionDirectory
-
-  This program is free software; you can redistribute it and/or modify
-  it under the terms of the GNU General Public License as published by
-  the Free Software Foundation; either version 2 of the License, or
-  (at your option) any later version.
-
-  This program is distributed in the hope that it will be useful,
-  but WITHOUT ANY WARRANTY; without even the implied warranty of
-  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-  GNU General Public License for more details.
-
-  You should have received a copy of the GNU General Public License
-  along with this program; if not, write to the Free Software
-  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
-*/
-
-class locality extends department
-{
-  /* attribute list for save action */
-  var $attributes     = array("l", "description", "ou", "manager");
-  var $objectclasses  = array("top", "gosaDepartment");
-  var $structuralOC   = array("locality");
-
-  var $description  = "";
-  var $type         = "locality";
-  var $l            = "";
-  var $orig_l       = "";
-  var $namingAttr   = "l";
-
-  var $manager_name     = "";
-  var $manager          = "";
-
-  function check()
-  {
-    $message = plugin::check();
-
-    /* Check for presence of this department */
-    $ldap = $this->config->get_ldap_link();
-    $ldap->ls ("(&(l=".$this->l.")(objectClass=locality))", $this->base, array('dn'));
-    if ($this->orig_l == "new" && $ldap->count()) {
-      $message[] = msgPool::duplicated(_("Name"));
-    } elseif ($this->orig_dn != $this->dn && $ldap->count()) {
-      $message[] = msgPool::duplicated(_("Name"));
-    }
-
-    /* All required fields are set? */
-    if ($this->l == "") {
-      $message[] = msgPool::required(_("Name"));
-    } elseif (tests::is_department_name_reserved($this->l, $this->base)) {
-      $message[] = msgPool::reserved(_("Name"));
-    } elseif (preg_match ('/[#+:=>\\\\\/]/', $this->l)) {
-      $message[] = msgPool::invalid(_("Name"), $this->l, "/[^#+:=>\\\\\/]/");
-    }
-
-    /* Check description */
-    if ($this->description == "") {
-      $message[] = msgPool::required(_("Description"));
-    }
-
-    /* Check if we are allowed to create or move this object
-     */
-    if ($this->orig_dn == "new" && !$this->acl_is_createable($this->base)) {
-      $message[] = msgPool::permCreate();
-    } elseif ($this->orig_dn != "new" && $this->base != $this->orig_base && !$this->acl_is_moveable($this->base)) {
-      $message[] = msgPool::permMove();
-    }
-
-    return $message;
-  }
-
-
-  /* Return plugin informations for acl handling */
-  static function plInfo()
-  {
-    return array(
-      "plShortName"   => _("Locality"),
-      "plDescription" => _("Locality"),
-      "plSelfModify"  => FALSE,
-      "plCategory"    => array("department"),
-      "plObjectType"  => array("locality" => array(
-        "aclCategory" => "department",
-        "name"        => _("Locality"),
-        "filter"      => "objectClass=locality")
-      ),
-
-      "plProvidedAcls" => array(
-        "l"                 => _("Location"),
-        "description"       => _("Description"),
-        "manager"           => _("Manager"),
-        "base"              => _("Base"),
-      )
-    );
-  }
-}
-?>
diff --git a/plugins/admin/departments/class_organization.inc b/plugins/admin/departments/class_organization.inc
new file mode 100644
index 000000000..e739b735c
--- /dev/null
+++ b/plugins/admin/departments/class_organization.inc
@@ -0,0 +1,48 @@
+<?php
+/*
+  This code is part of FusionDirectory (http://www.fusiondirectory.org/)
+  Copyright (C) 2013  FusionDirectory
+
+  This program is free software; you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation; either version 2 of the License, or
+  (at your option) any later version.
+
+  This program is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with this program; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
+*/
+
+class organization extends department
+{
+  static $namingAttr  = "o";
+  var $objectclasses  = array("top", "gosaDepartment");
+  var $structuralOC   = array("organization");
+
+  static function plInfo()
+  {
+    return array(
+      "plShortName"   => _("Organization"),
+      "plDescription" => _("Organization"),
+      "plCategory"    => array("department"),
+      "plObjectType"  => array("organization" => array(
+        "aclCategory" => "department",
+        "name"        => _("Organization"),
+        "filter"      => "objectClass=organization")
+      ),
+
+      "plProvidedAcls" => parent::generatePlProvidedAcls(self::getAttributesInfo())
+    );
+  }
+
+  static function getAttributesInfo ()
+  {
+    return parent::getDepartmentAttributesInfo(_('organization'), self::$namingAttr);
+  }
+}
+?>
diff --git a/plugins/admin/departments/class_organizationGeneric.inc b/plugins/admin/departments/class_organizationGeneric.inc
deleted file mode 100644
index 699685c1c..000000000
--- a/plugins/admin/departments/class_organizationGeneric.inc
+++ /dev/null
@@ -1,139 +0,0 @@
-<?php
-/*
-  This code is part of FusionDirectory (http://www.fusiondirectory.org/)
-  Copyright (C) 2003  Cajus Pollmeier
-  Copyright (C) 2011-2013  FusionDirectory
-
-  This program is free software; you can redistribute it and/or modify
-  it under the terms of the GNU General Public License as published by
-  the Free Software Foundation; either version 2 of the License, or
-  (at your option) any later version.
-
-  This program is distributed in the hope that it will be useful,
-  but WITHOUT ANY WARRANTY; without even the implied warranty of
-  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-  GNU General Public License for more details.
-
-  You should have received a copy of the GNU General Public License
-  along with this program; if not, write to the Free Software
-  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
-*/
-
-class organization extends department
-{
-  /* attribute list for save action */
-  var $attributes     = array( "o", "ou", "description","userPassword","searchGuide",
-      "seeAlso","businessCategory","x121Address","registeredAddress","manager",
-      "destinationIndicator","preferredDeliveryMethod","telexNumber",
-      "telephoneNumber","internationaliSDNNumber","facsimileTelephoneNumber","street",
-      "postOfficeBox","postalCode", "postalAddress","physicalDeliveryOfficeName",
-      "st","l","teletexTerminalIdentifier");
-
-  var $objectclasses  = array("top", "gosaDepartment");
-  var $structuralOC   = array("organization");
-
-  /* Attributes
-   */
-  var $st                         = "";
-  var $l                          = "";
-  var $description                = "";
-  var $userPassword               = "";
-  var $searchGuide                = "";
-  var $seeAlso                    = "";
-  var $businessCategory           = "";
-  var $x121Address                = "";
-  var $registeredAddress          = "";
-  var $destinationIndicator       = "";
-  var $preferredDeliveryMethod    = "";
-  var $telexNumber                = "";
-  var $telephoneNumber            = "";
-  var $internationaliSDNNumber    = "";
-  var $facsimileTelephoneNumber   = "";
-  var $street                     = "";
-  var $postOfficeBox              = "";
-  var $postalCode                 = "";
-  var $postalAddress              = "";
-  var $teletexTerminalIdentifier  = "";
-  var $physicalDeliveryOfficeName = "";
-
-  /* Naming attributes
-   */
-  var $o            = "";
-  var $type         = "organization";
-  var $orgi_o       = "";
-  var $namingAttr   = "o";
-
-  var $manager_name     = "";
-  var $manager          = "";
-
-  function check()
-  {
-    $message = plugin::check();
-
-    /* Check for presence of this department */
-    $ldap = $this->config->get_ldap_link();
-    $ldap->ls ("(&(o=".$this->o.")(objectClass=organization))", $this->base, array('dn'));
-    if ($this->orig_o == "new" && $ldap->count()) {
-      $message[] = msgPool::duplicated(_("Name"));
-    } elseif ($this->orig_dn != $this->dn && $ldap->count()) {
-      $message[] = msgPool::duplicated(_("Name"));
-    }
-
-    /* All required fields are set? */
-    if ($this->o == "") {
-      $message[] = msgPool::required(_("Name"));
-    } elseif (tests::is_department_name_reserved($this->o, $this->base)) {
-      $message[] = msgPool::reserved(_("Name"));
-    } elseif (preg_match ('/[#+:=>\\\\\/]/', $this->o)) {
-      $message[] = msgPool::invalid(_("Name"), $this->o, "/[^#+:=>\\\\\/]/");
-    }
-
-    /* Check description */
-    if ($this->description == "") {
-      $message[] = msgPool::required(_("Description"));
-    }
-
-    /* Check if we are allowed to create or move this object
-     */
-    if ($this->orig_dn == "new" && !$this->acl_is_createable($this->base)) {
-      $message[] = msgPool::permCreate();
-    } elseif ($this->orig_dn != "new" && $this->base != $this->orig_base && !$this->acl_is_moveable($this->base)) {
-      $message[] = msgPool::permMove();
-    }
-
-    return $message;
-  }
-
-
-  /* Return plugin informations for acl handling */
-  static function plInfo()
-  {
-    return array(
-      "plShortName"   => _("Organization"),
-      "plDescription" => _("Organization"),
-      "plSelfModify"  => FALSE,
-      "plCategory"    => array("department"),
-      "plObjectType"  => array("organization" => array(
-        "aclCategory" => "department",
-        "name" => _("Organization"),
-        "filter" => "objectClass=organization")
-      ),
-
-      "plProvidedAcls" => array(
-        "o"                       => _("Organization name"),
-        "description"             => _("Description"),
-        "businessCategory"        => _("Category"),
-        "base"                    => _("Base"),
-
-        "manager"                 => _("Manager"),
-
-        "st"                        => _("State"),
-        "l"                         => _("Location"),
-        "postalAddress"             => _("Postal address"),
-        "telephoneNumber"           => _("Phone number"),
-        "facsimileTelephoneNumber"  => _("Fax"),
-      )
-    );
-  }
-}
-?>
diff --git a/plugins/admin/departments/country.tpl b/plugins/admin/departments/country.tpl
deleted file mode 100644
index f6ff12c3a..000000000
--- a/plugins/admin/departments/country.tpl
+++ /dev/null
@@ -1,62 +0,0 @@
-<!--////////////////////
-  //  COUNTRY (c)
-    //////////////////// -->
-
-<table style="width:100%; vertical-align:top; text-align:left;" cellpadding=4>
- <tr>
-   <td style="vertical-align:top; width:50%">
-     <h2><img class="center" alt="" src="images/rightarrow.png"> {t}Properties{/t}</h2>
-     <table>
-      <tr>
-       <td><LABEL for="c">{t}Country name{/t}</LABEL>{$must}</td>
-       <td>
-{render acl=$cACL}
-      <input type='text' id="c" name="c" size=25 maxlength=60 value="{$c}" title="{t}Name of country to create{/t}">
-{/render}
-       </td>
-      </tr>
-      <tr>
-       <td><LABEL for="description">{t}Description{/t}</LABEL>{$must}</td>
-       <td>
-{render acl=$descriptionACL}
-        <input type='text' id="description" name="description" size=25 maxlength=80 value="{$description}" title="{t}Descriptive text for department{/t}">
-{/render}
-       </td>
-      </tr>
-  {if !$is_root_dse}
-      <tr>
-        <td><LABEL for="base">{t}Base{/t}</LABEL>{$must}</td>
-        <td>
-{render acl=$baseACL}
-          {$base}
-{/render}
-    </td>
-   </tr>
-  {/if}
-
-    <tr>
-     <td><label for="manager">{t}Manager{/t}</label></td>
-     <td>
-{render acl=$managerACL}
-        <input type='text' name='manager_name' id='manager_name' value='{$manager_name}' disabled
-          title='{$manager}'>
-{/render}
-{render acl=$managerACL}
-        <input type='image' src='images/lists/edit.png' name='editManager' class='center' alt="edit"/>
-{/render}
-        {if $manager!=""}
-{render acl=$managerACL}
-        <img src='images/info_small.png' title='{$manager}' class='center' alt="info"/>
-{/render}
-{render acl=$managerACL}
-        <input type='image' src='images/lists/trash.png' name='removeManager' class='center' alt="trash"/>
-{/render}
-        {/if}
-     </td>
-    </tr>
-  </table>
-  </td>
- </tr>
-</table>
-<p class='seperator'>&nbsp;</p>
-<input type='hidden' name='dep_generic_posted' value='1'>
diff --git a/plugins/admin/departments/dcObject.tpl b/plugins/admin/departments/dcObject.tpl
deleted file mode 100644
index 183117fe9..000000000
--- a/plugins/admin/departments/dcObject.tpl
+++ /dev/null
@@ -1,62 +0,0 @@
-<!--////////////////////
-  //  LOCALITY (l)
-    //////////////////// -->
-
-<table style="width:100%; vertical-align:top; text-align:left;" cellpadding=4>
- <tr>
-   <td style="vertical-align:top; width:50%">
-     <h2><img class="center" alt="" src="images/rightarrow.png"> {t}Properties{/t}</h2>
-     <table>
-      <tr>
-       <td><LABEL for="dc">{t}Locality name{/t}</LABEL>{$must}</td>
-       <td>
-{render acl=$dcACL}
-      <input type='text' id="dc" name="dc" size=25 maxlength=60 value="{$dc}" title="{t}Name of locality to create{/t}">
-{/render}
-       </td>
-      </tr>
-      <tr>
-       <td><LABEL for="description">{t}Description{/t}</LABEL>{$must}</td>
-       <td>
-{render acl=$descriptionACL}
-        <input type='text' id="description" name="description" size=25 maxlength=80 value="{$description}" title="{t}Descriptive text for department{/t}">
-{/render}
-       </td>
-      </tr>
-  {if !$is_root_dse}
-      <tr>
-        <td><LABEL for="base">{t}Base{/t}</LABEL>{$must}</td>
-        <td>
-{render acl=$baseACL}
-          {$base}
-{/render}
-    </td>
-   </tr>
-  {/if}
-
-    <tr>
-     <td><label for="manager">{t}Manager{/t}</label></td>
-     <td>
-{render acl=$managerACL}
-        <input type='text' name='manager_name' id='manager_name' value='{$manager_name}' disabled
-          title='{$manager}'>
-{/render}
-{render acl=$managerACL}
-        <input type='image' src='images/lists/edit.png' name='editManager' class='center' alt="edit"/>
-{/render}
-        {if $manager!=""}
-{render acl=$managerACL}
-        <img src='images/info_small.png' title='{$manager}' class='center' alt="info"/>
-{/render}
-{render acl=$managerACL}
-        <input type='image' src='images/lists/trash.png' name='removeManager' class='center' alt="trash"/>
-{/render}
-        {/if}
-     </td>
-    </tr>
-  </table>
-  </td>
- </tr>
-</table>
-<p class='seperator'>&nbsp;</p>
-<input type='hidden' name='dep_generic_posted' value='1'>
diff --git a/plugins/admin/departments/domain.tpl b/plugins/admin/departments/domain.tpl
deleted file mode 100644
index 3cf99895e..000000000
--- a/plugins/admin/departments/domain.tpl
+++ /dev/null
@@ -1,62 +0,0 @@
-<!--////////////////////
-  //  LOCALITY (l)
-    //////////////////// -->
-
-<table style="width:100%; vertical-align:top; text-align:left;" cellpadding=4>
- <tr>
-   <td style="vertical-align:top; width:50%">
-     <h2><img class="center" alt="" src="images/rightarrow.png"> {t}Properties{/t}</h2>
-     <table>
-      <tr>
-       <td><LABEL for="dc">{t}Domain name{/t}</LABEL>{$must}</td>
-       <td>
-{render acl=$dcACL}
-      <input type='text' id="dc" name="dc" size=25 maxlength=60 value="{$dc}" title="{t}Name of domain to create{/t}">
-{/render}
-       </td>
-      </tr>
-      <tr>
-       <td><LABEL for="description">{t}Description{/t}</LABEL>{$must}</td>
-       <td>
-{render acl=$descriptionACL}
-        <input type='text' id="description" name="description" size=25 maxlength=80 value="{$description}" title="{t}Descriptive text for department{/t}">
-{/render}
-       </td>
-      </tr>
-  {if !$is_root_dse}
-      <tr>
-        <td><LABEL for="base">{t}Base{/t}</LABEL>{$must}</td>
-        <td>
-{render acl=$baseACL}
-          {$base}
-{/render}
-    </td>
-   </tr>
-  {/if}
-
-    <tr>
-     <td><label for="manager">{t}Manager{/t}</label></td>
-     <td>
-{render acl=$managerACL}
-        <input type='text' name='manager_name' id='manager_name' value='{$manager_name}' disabled
-          title='{$manager}'>
-{/render}
-{render acl=$managerACL}
-        <input type='image' src='images/lists/edit.png' name='editManager' class='center' alt="edit">
-{/render}
-        {if $manager!=""}
-{render acl=$managerACL}
-        <img src='images/info_small.png' title='{$manager}' class='center' alt="info"/>
-{/render}
-{render acl=$managerACL}
-        <input type='image' src='images/lists/trash.png' name='removeManager' class='center' alt="trash"/>
-{/render}
-        {/if}
-     </td>
-    </tr>
-  </table>
-  </td>
- </tr>
-</table>
-<p class='seperator'>&nbsp;</p>
-<input type='hidden' name='dep_generic_posted' value='1'>
diff --git a/plugins/admin/departments/generic.tpl b/plugins/admin/departments/generic.tpl
deleted file mode 100644
index eb841fcdb..000000000
--- a/plugins/admin/departments/generic.tpl
+++ /dev/null
@@ -1,133 +0,0 @@
-<!--////////////////////
-  //  ORGANIZATIONAL UNIT (ou)
-    //////////////////// -->
-<table style="width:100%; vertical-align:top; text-align:left;" cellpadding=4>
- <tr>
-   <td style="vertical-align:top; width:50%">
-     <h2><img class="center" alt="" src="images/rightarrow.png"> {t}Properties{/t}</h2>
-
-     <table>
-      <tr>
-       <td><LABEL for="ou">{t}Name of department{/t}</LABEL>{$must}</td>
-       <td>
-{render acl=$ouACL}
-  <input type='text' id="ou" name="ou" size=25 maxlength=60 value="{$ou}" title="{t}Name of subtree to create{/t}">
-{/render}
-       </td>
-      </tr>
-      <tr>
-       <td style='vertical-align:top;'><LABEL for="description">{t}Description{/t}</LABEL>{$must}</td>
-       <td>
-{render acl=$descriptionACL}
-        <textarea id='description' name='description' style='width:220px' title="{t}Descriptive text for   department{/t}">{$description}</textarea>
-{/render}
-       </td>
-      </tr>
-      <tr>
-       <td><LABEL for="businessCategory">{t}Category{/t}</LABEL></td>
-       <td>
-{render acl=$businessCategoryACL}
-        <input type='text' id="businessCategory" name="businessCategory" size=25 maxlength=80 value="{$businessCategory}" title="{t}Category for this subtree{/t}">
-{/render}
-       </td>
-      </tr>
-      <tr>
-        <td colspan="2"><br></td>
-      </tr>
-  {if !$is_root_dse}
-      <tr>
-        <td><LABEL for="base">{t}Base{/t}</LABEL>{$must}</td>
-
-        <td>
-{render acl=$baseACL}
-          {$base}
-{/render}
-  </td>
-       </tr>
-  {/if}
-
-    <tr>
-     <td><label for="manager">{t}Manager{/t}</label></td>
-     <td>
-{render acl=$managerACL}
-        <input type='text' name='manager_name' id='manager_name' value='{$manager_name}' disabled
-          title='{$manager}'>
-{/render}
-{render acl=$managerACL}
-        <input type='image' src='images/lists/edit.png' name='editManager' class='center'>
-{/render}
-        {if $manager!=""}
-{render acl=$managerACL}
-        <img src='images/info_small.png' title='{$manager}' class='center'>
-{/render}
-{render acl=$managerACL}
-        <input type='image' src='images/lists/trash.png' name='removeManager' class='center'>
-{/render}
-        {/if}
-     </td>
-    </tr>
-
-     </table>
-
-   </td>
-   <td style="border-left:1px solid #A0A0A0">
-    &nbsp;
-   </td>
-   <td>
-     <h2><img class="center" alt="" src="plugins/departments/images/department.png"> {t}Location{/t}</h2>
-
-     <table style="width:100%">
-      <tr>
-       <td><LABEL for="st">{t}State{/t}</LABEL></td>
-       <td>
-{render acl=$stACL}
-  <input type='text' id="st" name="st" size=25 maxlength=60 value="{$st}" title="{t}State where this subtree is located{/t}">
-{/render}
-       </td>
-      </tr>
-      <tr>
-       <td><LABEL for="l">{t}Location{/t}</LABEL></td>
-       <td>
-{render acl=$lACL}
-  <input type='text' id="l" name="l" size=25 maxlength=60 value="{$l}" title="{t}Location of this subtree{/t}">
-{/render}
-       </td>
-      </tr>
-      <tr>
-       <td style="vertical-align:top;"><LABEL for="postalAddress">{t}Address{/t}</LABEL></td>
-       <td>
-{render acl=$postalAddressACL}
-  <textarea id="postalAddress" name="postalAddress" style="width:100%" rows=3 cols=22 title="{t}Postal address of this subtree{/t}">{$postalAddress}</textarea>
-{/render}
-      </tr>
-      <tr>
-       <td><LABEL for="telephoneNumber">{t}Phone{/t}</LABEL></td>
-       <td>
-{render acl=$telephoneNumberACL}
-  <input type='text' id="telephoneNumber" name="telephoneNumber" size=25 maxlength=60 value="{$telephoneNumber}" title="{t}Base telephone number of this subtree{/t}">
-{/render}
-       </td>
-      </tr>
-      <tr>
-       <td><LABEL for="facsimileTelephoneNumber">{t}Fax{/t}</LABEL></td>
-       <td>
-{render acl=$facsimileTelephoneNumberACL}
-  <input type='text' id="facsimileTelephoneNumber" name="facsimileTelephoneNumber" size=25 maxlength=60 value="{$facsimileTelephoneNumber}" title="{t}Base facsimile telephone number of this subtree{/t}">
-{/render}
-       </td>
-      </tr>
-     </table>
-
-   </td>
- </tr>
-</table>
-
-<p class='seperator'>&nbsp;</p>
-
-<!-- Place cursor -->
-<input type='hidden' name='dep_generic_posted' value='1'>
-<script type="text/javascript">
-  <!-- // First input field on page
-  focus_field('ou');
-  -->
-</script>
diff --git a/plugins/admin/departments/locality.tpl b/plugins/admin/departments/locality.tpl
deleted file mode 100644
index 4effefeae..000000000
--- a/plugins/admin/departments/locality.tpl
+++ /dev/null
@@ -1,61 +0,0 @@
-<!--////////////////////
-  //  LOCALITY (l)
-    //////////////////// -->
-
-<table style="width:100%; vertical-align:top; text-align:left;" cellpadding=4>
- <tr>
-   <td style="vertical-align:top; width:50%">
-     <h2><img class="center" alt="" src="images/rightarrow.png"> {t}Properties{/t}</h2>
-     <table>
-      <tr>
-       <td><LABEL for="l">{t}Locality name{/t}</LABEL>{$must}</td>
-       <td>
-{render acl=$lACL}
-      <input type='text' id="l" name="l" size=25 maxlength=60 value="{$l}" title="{t}Name of locality to create{/t}">
-{/render}
-       </td>
-      </tr>
-      <tr>
-       <td><LABEL for="description">{t}Description{/t}</LABEL>{$must}</td>
-       <td>
-{render acl=$descriptionACL}
-        <input type='text' id="description" name="description" size=25 maxlength=80 value="{$description}" title="{t}Descriptive text for department{/t}">
-{/render}
-       </td>
-      </tr>
-  {if !$is_root_dse}
-      <tr>
-        <td><LABEL for="base">{t}Base{/t}</LABEL>{$must}</td>
-        <td>
-{render acl=$baseACL}
-          {$base}
-{/render}
-    </td>
-   </tr>
-  {/if}
-
-    <tr>
-     <td><label for="manager">{t}Manager{/t}</label></td>
-     <td>
-{render acl=$managerACL}
-        <input type='text' name='manager_name' id='manager_name' value='{$manager_name}' disabled
-          title='{$manager}'>
-{/render}
-{render acl=$managerACL}
-        <input type='image' src='images/lists/edit.png' name='editManager' class='center'>
-{/render}
-        {if $manager!=""}
-{render acl=$managerACL}
-        <img src='images/info_small.png' title='{$manager}' class='center'>
-{/render}
-{render acl=$managerACL}
-        <input type='image' src='images/lists/trash.png' name='removeManager' class='center'>
-{/render}
-        {/if}
-     </td>
-    </tr>
-  </table>
-  </td>
- </tr>
-</table>
-<input type='hidden' name='dep_generic_posted' value='1'>
diff --git a/plugins/admin/departments/organization.tpl b/plugins/admin/departments/organization.tpl
deleted file mode 100644
index 16f057a09..000000000
--- a/plugins/admin/departments/organization.tpl
+++ /dev/null
@@ -1,133 +0,0 @@
-<!--////////////////////
-  //  ORGANIZATION (o)
-    //////////////////// -->
-<table style="width:100%; vertical-align:top; text-align:left;" cellpadding=4>
- <tr>
-   <td style="vertical-align:top; width:50%">
-     <h2><img class="center" alt="" src="images/rightarrow.png"> {t}Properties{/t}</h2>
-
-     <table>
-      <tr>
-       <td><LABEL for="o">{t}Name of organization{/t}</LABEL>{$must}</td>
-       <td>
-{render acl=$oACL}
-  <input type='text' id="o" name="o" size=25 maxlength=60 value="{$o}" title="{t}Name of organization to create{/t}">
-{/render}
-       </td>
-      </tr>
-      <tr>
-       <td><LABEL for="description">{t}Description{/t}</LABEL>{$must}</td>
-       <td>
-{render acl=$descriptionACL}
-        <input type='text' id="description" name="description" size=25 maxlength=80 value="{$description}" title="{t}Descriptive text for department{/t}">
-{/render}
-       </td>
-      </tr>
-      <tr>
-       <td><LABEL for="businessCategory">{t}Category{/t}</LABEL></td>
-       <td>
-{render acl=$businessCategoryACL}
-        <input type='text' id="businessCategory" name="businessCategory" size=25 maxlength=80 value="{$businessCategory}" title="{t}Category for this subtree{/t}">
-{/render}
-       </td>
-      </tr>
-      <tr>
-        <td colspan="2"><br></td>
-      </tr>
-  {if !$is_root_dse}
-      <tr>
-        <td><LABEL for="base">{t}Base{/t}</LABEL>{$must}</td>
-
-        <td>
-{render acl=$baseACL}
-          {$base}
-{/render}
-  </td>
-       </tr>
-  {/if}
-
-    <tr>
-     <td><label for="manager">{t}Manager{/t}</label></td>
-     <td>
-{render acl=$managerACL}
-        <input type='text' name='manager_name' id='manager_name' value='{$manager_name}' disabled
-          title='{$manager}'>
-{/render}
-{render acl=$managerACL}
-        <input type='image' src='images/lists/edit.png' name='editManager' class='center'>
-{/render}
-        {if $manager!=""}
-{render acl=$managerACL}
-        <img src='images/info_small.png' title='{$manager}' class='center'>
-{/render}
-{render acl=$managerACL}
-        <input type='image' src='images/lists/trash.png' name='removeManager' class='center'>
-{/render}
-        {/if}
-     </td>
-    </tr>
-  </table>
-
-   </td>
-   <td style="border-left:1px solid #A0A0A0">
-    &nbsp;
-   </td>
-   <td>
-     <h2><img class="center" alt="" src="plugins/departments/images/department.png"> {t}Location{/t}</h2>
-
-     <table style="width:100%">
-      <tr>
-       <td><LABEL for="st">{t}State{/t}</LABEL></td>
-       <td>
-{render acl=$stACL}
-  <input type='text' id="st" name="st" size=25 maxlength=60 value="{$st}" title="{t}State where this subtree is located{/t}">
-{/render}
-       </td>
-      </tr>
-      <tr>
-       <td><LABEL for="l">{t}Location{/t}</LABEL></td>
-       <td>
-{render acl=$lACL}
-  <input type='text' id="l" name="l" size=25 maxlength=60 value="{$l}" title="{t}Location of this subtree{/t}">
-{/render}
-       </td>
-      </tr>
-      <tr>
-       <td style="vertical-align:top;"><LABEL for="postalAddress">{t}Address{/t}</LABEL></td>
-       <td>
-{render acl=$postalAddressACL}
-  <textarea id="postalAddress" name="postalAddress" style="width:100%" rows=3 cols=22 title="{t}Postal address of this subtree{/t}">{$postalAddress}</textarea>
-{/render}
-      </tr>
-      <tr>
-       <td><LABEL for="telephoneNumber">{t}Phone{/t}</LABEL></td>
-       <td>
-{render acl=$telephoneNumberACL}
-  <input type='text' id="telephoneNumber" name="telephoneNumber" size=25 maxlength=60 value="{$telephoneNumber}" title="{t}Base telephone number of this subtree{/t}">
-{/render}
-       </td>
-      </tr>
-      <tr>
-       <td><LABEL for="facsimileTelephoneNumber">{t}Fax{/t}</LABEL></td>
-       <td>
-{render acl=$facsimileTelephoneNumberACL}
-  <input type='text' id="facsimileTelephoneNumber" name="facsimileTelephoneNumber" size=25 maxlength=60 value="{$facsimileTelephoneNumber}" title="{t}Base facsimile telephone number of this subtree{/t}">
-{/render}
-       </td>
-      </tr>
-     </table>
-
-   </td>
- </tr>
-</table>
-
-<p class='seperator'>&nbsp;</p>
-
-<!-- Place cursor -->
-<input type='hidden' name='dep_generic_posted' value='1'>
-<script type="text/javascript">
-  <!-- // First input field on page
-  focus_field('o');
-  -->
-</script>
-<input type='hidden' name='dep_generic_posted' value='1'>
diff --git a/plugins/admin/departments/tabs_department.inc b/plugins/admin/departments/tabs_department.inc
index 5053bb7d2..243d4573c 100644
--- a/plugins/admin/departments/tabs_department.inc
+++ b/plugins/admin/departments/tabs_department.inc
@@ -1,5 +1,4 @@
 <?php
-
 /*
   This code is part of FusionDirectory (http://www.fusiondirectory.org/)
   Copyright (C) 2003  Cajus Pollmeier
@@ -20,61 +19,29 @@
   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
 */
 
-class deptabs extends tabs
+class deptabs extends simpleTabs
 {
-  var $base       = "";
-  var $moved      = FALSE;
-  var $base_name  = "department";
-
-  function __construct($config, $data, $dn, $category, $copied_object = NULL)
-  {
-    parent::__construct($config, $data, $dn, $category, $copied_object);
-
-    /* Detect the base class  (The classs which extends from department)
-     */
-    foreach ($this->by_object as $name => $object) {
-      if ($object instanceOf department) {
-        $this->base_name = get_class($object);
-        break;
-      }
-    }
-
-
-    /* Add references/acls/snapshots */
-    $this->addSpecialTabs();
-    if (isset($this->by_object['acl'])) {
-      $this->by_object['acl']->skipTagging = TRUE;
-    }
-  }
-
-  function check($ignore_account = FALSE)
-  {
-    return parent::check(TRUE);
-  }
-
   function save()
   {
-    $baseobject = &$this->by_object[$this->base_name];
-    $namingAttr = $baseobject->namingAttr;
-    $nAV        = preg_replace('/,/', '\,', $baseobject->$namingAttr);
-    $nAV        = preg_replace('/"/', '\"', $nAV);
-    $new_dn     = @LDAP::convert($namingAttr.'='.$nAV.','.$baseobject->base);
+    $baseobject = $this->getBaseObject();
+    $new_dn     = $baseobject->compute_dn();
+    @DEBUG (DEBUG_TRACE, __LINE__, __FUNCTION__, __FILE__, $new_dn, "Saving");
 
-    /* Move group? */
-    if ($this->dn != $new_dn && $this->dn != "new") {
-      $baseobject->move($this->dn, $new_dn);
-    }
-
-    /* Update department cache.
-     */
+    /* Move ? */
     if ($this->dn != $new_dn) {
+      /* Write entry on new 'dn' */
+      if ($this->dn != 'new') {
+        $baseobject->move($this->dn, $new_dn);
+      }
+      /* Happen to use the new one */
+      $this->dn = $new_dn;
+
+      /* Update department cache */
       global $config;
       $config->get_departments();
     }
 
-    $this->dn       = $new_dn;
-    $baseobject->dn = $this->dn;
-    parent::save();
+    tabs::save();
   }
 }
 ?>
-- 
GitLab