Browse Source

Merge branch 'ressource' of andre/whmcsZimbraEmail into thurdata

andre 1 year ago
parent
commit
83e139cc8c
77 changed files with 3778 additions and 275 deletions
  1. 7 4
      app/Config/sidebars.yml
  2. 1 0
      app/Enums/ControllerEnums.php
  3. 2 0
      app/Enums/Zimbra.php
  4. 2 0
      app/Http/Actions/UsageUpdate.php
  5. 43 0
      app/Http/Client/Ressource.php
  6. 1 0
      app/Libs/Migrations/Drivers/Version1To2/Settings.php
  7. 3 0
      app/Libs/Product/ProductManager.php
  8. 1 0
      app/Libs/Zimbra/Components/Api/Soap/Actions/Account.php
  9. 243 0
      app/Libs/Zimbra/Components/Api/Soap/Actions/Ressource.php
  10. 6 2
      app/Libs/Zimbra/Components/Api/Soap/Connection.php
  11. 36 0
      app/Libs/Zimbra/Components/Api/Soap/Helpers/RessourceHelper.php
  12. 140 0
      app/Libs/Zimbra/Components/Api/Soap/Models/Ressource.php
  13. 43 3
      app/Libs/Zimbra/Components/Api/Soap/MySoapClient.php
  14. 9 0
      app/Libs/Zimbra/Components/Api/Soap/Repository.php
  15. 136 0
      app/Libs/Zimbra/Components/Api/Soap/Repository/Ressources.php
  16. 55 0
      app/Libs/Zimbra/Components/Api/Soap/Services.php
  17. 137 0
      app/Libs/Zimbra/Components/Api/Soap/Services/Create/CreateRessource.php
  18. 43 0
      app/Libs/Zimbra/Components/Api/Soap/Services/Delete/DeleteRessource.php
  19. 84 0
      app/Libs/Zimbra/Components/Api/Soap/Services/Update/UpdateRessource.php
  20. 56 0
      app/Libs/Zimbra/Components/Api/Soap/Services/Update/UpdateRessourcePassword.php
  21. 39 0
      app/Libs/Zimbra/Components/Api/Soap/Services/Update/UpdateRessourceStatus.php
  22. 3 0
      app/UI/Admin/ProductConfiguration/Pages/Sections/ClientAreaFeatures.php
  23. 2 1
      app/UI/Admin/ProductConfiguration/Providers/ProductConfigurationDataProvider.php
  24. 1 1
      app/UI/Client/EmailAccount/Pages/Accounts.php
  25. 2 2
      app/UI/Client/EmailAlias/Pages/Aliases.php
  26. 11 0
      app/UI/Client/Home/Pages/Dashboard.php
  27. 26 0
      app/UI/Client/Ressource/Buttons/AddRessourceButton.php
  28. 30 0
      app/UI/Client/Ressource/Buttons/ChangePasswordButton.php
  29. 31 0
      app/UI/Client/Ressource/Buttons/ChangeStatusButton.php
  30. 31 0
      app/UI/Client/Ressource/Buttons/DeleteRessourceButton.php
  31. 32 0
      app/UI/Client/Ressource/Buttons/EditRessourceButton.php
  32. 103 0
      app/UI/Client/Ressource/Buttons/LoginToPanelButton.php
  33. 28 0
      app/UI/Client/Ressource/Buttons/MassChangeStatusButton.php
  34. 28 0
      app/UI/Client/Ressource/Buttons/MassDeleteRessourceButton.php
  35. 19 0
      app/UI/Client/Ressource/Buttons/SpanDropdownButton.php
  36. 58 0
      app/UI/Client/Ressource/Forms/AddRessourceForm.php
  37. 58 0
      app/UI/Client/Ressource/Forms/ChangePasswordForm.php
  38. 47 0
      app/UI/Client/Ressource/Forms/ChangeStatusForm.php
  39. 40 0
      app/UI/Client/Ressource/Forms/DeleteRessourceForm.php
  40. 55 0
      app/UI/Client/Ressource/Forms/EditRessourceForm.php
  41. 38 0
      app/UI/Client/Ressource/Forms/MassChangeStatusForm.php
  42. 42 0
      app/UI/Client/Ressource/Forms/MassDeleteRessourceForm.php
  43. 26 0
      app/UI/Client/Ressource/Modals/AddRessourceModal.php
  44. 29 0
      app/UI/Client/Ressource/Modals/ChangePasswordModal.php
  45. 29 0
      app/UI/Client/Ressource/Modals/ChangeStatusModal.php
  46. 34 0
      app/UI/Client/Ressource/Modals/DeleteRessourceModal.php
  47. 30 0
      app/UI/Client/Ressource/Modals/EditRessourceModal.php
  48. 30 0
      app/UI/Client/Ressource/Modals/MassChangeStatusModal.php
  49. 31 0
      app/UI/Client/Ressource/Modals/MassDeleteRessourceModal.php
  50. 200 0
      app/UI/Client/Ressource/Pages/Ressources.php
  51. 116 0
      app/UI/Client/Ressource/Providers/DeleteRessourceDataProvider.php
  52. 274 0
      app/UI/Client/Ressource/Providers/EditRessourceDataProvider.php
  53. 185 0
      app/UI/Client/Ressource/Providers/RessourceDataProvider.php
  54. 43 0
      app/UI/Client/Ressource/Sections/AdditionalSection.php
  55. 41 0
      app/UI/Client/Ressource/Sections/EditAdditionalSection.php
  56. 76 0
      app/UI/Client/Ressource/Sections/EditGeneralSection.php
  57. 81 0
      app/UI/Client/Ressource/Sections/GeneralSection.php
  58. BIN
      app/UI/Client/Templates/assets/icons/ressource.png
  59. 18 0
      app/UI/Client/Templates/assets/js/ressource/index.js
  60. 5 0
      app/UI/Client/Templates/ressource/buttons/spanDropdownButton.tpl
  61. 30 0
      app/UI/Client/Templates/ressource/buttons/spanDropdownButton_components.tpl
  62. 1 1
      core/DependencyInjection/Container.php
  63. 126 4
      langs/english.php
  64. 130 10
      langs/german.php
  65. 0 17
      vendor/mso/idna-convert/.gitattributes
  66. 0 4
      vendor/mso/idna-convert/.gitignore
  67. 0 5
      vendor/piwik/ini/.gitattributes
  68. 0 3
      vendor/piwik/ini/.gitignore
  69. 0 3
      vendor/psr/container/.gitignore
  70. 0 1
      vendor/psr/log/.gitignore
  71. 0 5
      vendor/rappasoft/laravel-helpers/.gitignore
  72. 0 3
      vendor/symfony/cache/.gitignore
  73. 0 3
      vendor/symfony/dependency-injection/.gitignore
  74. 0 3
      vendor/symfony/http-foundation/.gitignore
  75. 0 3
      vendor/symfony/yaml/.gitignore
  76. 326 121
      zimbraEmail_help_mx.tpl
  77. 145 76
      zimbraEmail_mx.php

+ 7 - 4
app/Config/sidebars.yml

@@ -6,11 +6,14 @@ management:
     order: 720
     uri: 'clientarea.php?action=productdetails&id={$hostingId}&modop=custom&a=management&mg-page=emailAlias'
   distributionList:
-      order: 730
-      uri: 'clientarea.php?action=productdetails&id={$hostingId}&modop=custom&a=management&mg-page=distributionList'
-  domainAlias:
+    order: 730
+    uri: 'clientarea.php?action=productdetails&id={$hostingId}&modop=custom&a=management&mg-page=distributionList'
+  ressource:
     order: 740
+    uri: 'clientarea.php?action=productdetails&id={$hostingId}&modop=custom&a=management&mg-page=ressource'
+  domainAlias:
+    order: 750
     uri: 'clientarea.php?action=productdetails&id={$hostingId}&modop=custom&a=management&mg-page=domainAlias'
   goWebmail:
-    order: 750
+    order: 760
     uri: 'clientarea.php?action=productdetails&id={$hostingId}&modop=custom&a=management&mg-page=webmail" target="_blank'

+ 1 - 0
app/Enums/ControllerEnums.php

@@ -18,5 +18,6 @@ class ControllerEnums
     const DOMAIN_ALIAS_PAGE         = 'ca_domainAliasesPage';
     const WEBMAIL_PAGE              = 'ca_goToWebmailPage';
     const DISTRIBUTION_MAIL_PAGE    = 'ca_distributionListPage';
+    const RESSOURCE_PAGE            = 'ca_ressourcePage';
 
 }

+ 2 - 0
app/Enums/Zimbra.php

@@ -46,6 +46,8 @@ class Zimbra
     const ACC_STATUS_PENDING = 'pending';
     const ACC_STATUS_SUSPEND = 'suspended';
 
+    const RES_TYPE_LOCATION  = 'Location';
+    const RES_TYPE_EQUIPMENT = 'Equipment';
 
     const DEFAULT_LOGIN_LINK = 'https://zimbra-server';
 

+ 2 - 0
app/Http/Actions/UsageUpdate.php

@@ -7,6 +7,7 @@ namespace ModulesGarden\Servers\ZimbraEmail\App\Http\Actions;
 use ModulesGarden\Servers\ZimbraEmail\App\Helpers\ZimbraManager;
 use ModulesGarden\Servers\ZimbraEmail\Core\App\Controllers\Instances\AddonController;
 use ModulesGarden\Servers\ZimbraEmail\Core\Models\Whmcs;
+use WHMCS\Database\Capsule;
 
 class UsageUpdate extends AddonController
 {
@@ -35,6 +36,7 @@ class UsageUpdate extends AddonController
 
                 Whmcs\Hosting::where('server', $serverId)->where('domain', $domainName)->update(['bwusage' => $mailboxes]);
                 Whmcs\Hosting::where('server', $serverId)->where('domain', $domainName)->update(['diskusage' => $storage]);
+                Whmcs\Hosting::where('server', $serverId)->where('domain', $domainName)->update(['lastupdate' => Capsule::raw('now()')]);
 
                 usleep(5000);
             }

+ 43 - 0
app/Http/Client/Ressource.php

@@ -0,0 +1,43 @@
+<?php
+
+namespace ModulesGarden\Servers\ZimbraEmail\App\Http\Client;
+
+use ModulesGarden\Servers\ZimbraEmail\App\Enums\ControllerEnums;
+use ModulesGarden\Servers\ZimbraEmail\App\Enums\ProductParams;
+use ModulesGarden\Servers\ZimbraEmail\App\Helpers\BuildUrlExtended;
+use ModulesGarden\Servers\ZimbraEmail\App\Libs\Product\ProductManager;
+use ModulesGarden\Servers\ZimbraEmail\App\UI\Admin\Custom\Pages\Description;
+use ModulesGarden\Servers\ZimbraEmail\App\UI\Client\Ressource\Pages\Ressources;
+use ModulesGarden\Servers\ZimbraEmail\Core\Http\AbstractClientController;
+use ModulesGarden\Servers\ZimbraEmail\Core\UI\Traits\WhmcsParams;
+use ModulesGarden\Servers\ZimbraEmail\Core\Helper;
+
+/**
+ *
+ * Created by PhpStorm.
+ * User: Tomasz Bielecki ( tomasz.bi@modulesgarden.com )
+ * Date: 10.09.19
+ * Time: 10:12
+ * Class Ressource
+ */
+class Ressource extends AbstractClientController
+{
+    use WhmcsParams;
+
+    public function index()
+    {
+        $productManager = new ProductManager();
+        $productManager->loadByHostingId($this->request->get('id'));
+
+        if ($this->getWhmcsParamByKey('status') !== 'Active' || !$productManager->isControllerAccessible(ControllerEnums::RESSOURCE_PAGE))
+        {
+            return Helper\redirectByUrl(BuildUrlExtended::getProvisioningUrl('',false,false));
+        }
+
+        return Helper\view()
+            ->addElement(new Description('ressource'))
+            ->addElement(Ressources::class)
+            ;
+
+    }
+}

+ 1 - 0
app/Libs/Migrations/Drivers/Version1To2/Settings.php

@@ -177,6 +177,7 @@ class Settings
         return [
             'clientAreaFeaturesLeft'    => 'on',
             'ca_emailAccountPage'       => 'on',
+            'ca_ressourcePage'          => 'on',
             'ca_distributionListPage'   => 'on',
             'ca_goToWebmailPage'        => 'on',
             'clientAreaFeaturesRight'   => 'on',

+ 3 - 0
app/Libs/Product/ProductManager.php

@@ -260,6 +260,9 @@ class ProductManager
             case 'emailAlias':
                 $controller = ControllerEnums::EMAIL_ALIAS_PAGE;
                 break;
+            case 'ressource':
+                $controller = ControllerEnums::RESSOURCE_PAGE;
+                break;
             case 'distributionList':
                 $controller = ControllerEnums::DISTRIBUTION_MAIL_PAGE;
                 break;

+ 1 - 0
app/Libs/Zimbra/Components/Api/Soap/Actions/Account.php

@@ -49,6 +49,7 @@ class Account extends AbstractAction
          * run request
          */
         $result = $this->connection->request("CreateAccountRequest", $params);
+
         $this->setLastResult($result);
 
         /**

+ 243 - 0
app/Libs/Zimbra/Components/Api/Soap/Actions/Ressource.php

@@ -0,0 +1,243 @@
+<?php
+namespace ModulesGarden\Servers\ZimbraEmail\App\Libs\Zimbra\Components\Api\Soap\Actions;
+use ModulesGarden\Servers\ZimbraEmail\App\Libs\Zimbra\Components\Api\Soap\Interfaces\AbstractAction;
+use SoapFault;
+use SoapParam;
+use SoapVar;
+use ModulesGarden\Servers\ZimbraEmail\App\Libs\Zimbra\Components\Api\Soap\Helpers\XmlParser;
+
+/**
+ *
+ * Created by PhpStorm.
+ * User: Tomasz Bielecki ( tomasz.bi@modulesgarden.com )
+ * Date: 28.08.19
+ * Time: 13:46
+ * Class Account
+ */
+class Ressource extends AbstractAction
+{
+
+    public function read()
+    {
+
+    }
+
+    /**
+     * @description create ressource in Zimbra API
+     * @param \ModulesGarden\Servers\ZimbraEmail\App\Libs\Zimbra\Components\Api\Soap\Models\Ressource $ressource
+     * @return bool|void
+     */
+    public function create(\ModulesGarden\Servers\ZimbraEmail\App\Libs\Zimbra\Components\Api\Soap\Models\Ressource $ressource)
+    {
+        /**
+         *
+         */
+        $params = [
+            new SoapParam($ressource->getName(), "name"),
+            new SoapParam($ressource->getPassword(), "password"),
+        ];
+
+        /**
+         * add ressource params
+         */
+        foreach ($ressource->getAttrs() as $key => $value)
+        {
+            $params[] = new SoapVar('<ns1:a n="' . $key . '">' . $value . '</ns1:a>', XSD_ANYXML);
+        }
+
+        /**
+         * run request
+         */
+        $result = $this->connection->request("CreateCalendarResourceRequest", $params);
+
+        $this->setLastResult($result);
+
+        /**
+         * load response to model
+         */
+        if($ressourceData = $result->getResponseBody()['CREATECALENDARRESOURCERESPONSE']['CALRESOURCE'])
+        {
+            $ressource->fill($ressourceData);
+            return $ressource;
+        }
+
+        $this->setError($result->getLastError());
+        return false;
+    }
+
+    /**
+     * @param \ModulesGarden\Servers\ZimbraEmail\App\Libs\Zimbra\Components\Api\Soap\Models\Ressource $ressource
+     * @return bool|\ModulesGarden\Servers\ZimbraEmail\App\Libs\Zimbra\Components\Api\Soap\Models\Ressource
+     */
+    public function update(\ModulesGarden\Servers\ZimbraEmail\App\Libs\Zimbra\Components\Api\Soap\Models\Ressource $ressource)
+    {
+        $params = [
+            new SoapParam($ressource->getId(), "id"),
+        ];
+
+        /**
+         * add ressource params
+         */
+        foreach ($ressource->getAttrs() as $key => $value)
+        {
+            $params[] = new SoapVar('<ns1:a n="' . $key . '">' . $value . '</ns1:a>', XSD_ANYXML);
+        }
+
+        $result = $this->connection->request("ModifyCalendarResourceRequest", $params);
+        $this->setLastResult($result);
+
+        if($ressourceData = $result->getResponseBody()['MODIFYCALENDARRESOURCERESPONSE']['CALRESOURCE'])
+        {
+            $ressource->fill($ressourceData);
+            return $ressource;
+        }
+
+        $this->setError($result->getLastError());
+        return false;
+    }
+
+    public function setPassword(\ModulesGarden\Servers\ZimbraEmail\App\Libs\Zimbra\Components\Api\Soap\Models\Ressource $ressource)
+    {
+        $params = [
+            new SoapParam($ressource->getId(), "id"),
+            new SoapParam($ressource->getPassword(), "newPassword"),
+        ];
+
+        $result = $this->connection->request("SetPasswordRequest", $params);
+        $this->setLastResult($result);
+
+        if($result->getLastError())
+        {
+            $this->setError($result->getLastError());
+            return false;
+        }
+
+        return true;
+
+    }
+
+    /**
+     * @param \ModulesGarden\Servers\ZimbraEmail\App\Libs\Zimbra\Components\Api\Soap\Models\Ressource $ressource
+     * @return bool
+     */
+    public function delete(\ModulesGarden\Servers\ZimbraEmail\App\Libs\Zimbra\Components\Api\Soap\Models\Ressource $ressource)
+    {
+        $params = [
+            new SoapParam($ressource->getId(), "id"),
+        ];
+
+        $result = $this->connection->request("DeleteCalendarResourceRequest", $params);
+        $this->setLastResult($result);
+
+        if($result->getLastError())
+        {
+            $this->setError($result->getLastError());
+            return false;
+        }
+
+        return true;
+    }
+
+    /**
+     * @param $name
+     * @return \ModulesGarden\Servers\ZimbraEmail\App\Libs\Zimbra\Components\Api\Soap\Response
+     */
+    public function getRessourceId($name)
+    {
+        $params = [
+            new SoapVar('<ns1:calresource by="name">' . $name . '</ns1:calresource>', XSD_ANYXML),
+        ];
+
+        return $this->connection->cleanResponse()->request("GetCalendarResourceRequest", $params);
+
+    }
+
+    /**
+     * @param \ModulesGarden\Servers\ZimbraEmail\App\Libs\Zimbra\Components\Api\Soap\Models\Ressource $ressource
+     * @return \ModulesGarden\Servers\ZimbraEmail\App\Libs\Zimbra\Components\Api\Soap\Response
+     */
+    public function getRessourceInfo(\ModulesGarden\Servers\ZimbraEmail\App\Libs\Zimbra\Components\Api\Soap\Models\Ressource $ressource)
+    {
+        if($value = $ressource->getId())
+        {
+            $type = 'id';
+        }elseif($value =$ressource->getName())
+        {
+            $type = 'name';
+        }
+
+        $result = null;
+
+        $params = [
+            new SoapVar('<ns1:calresource by="' . $type . '">' . $value . '</ns1:calresource>', XSD_ANYXML),
+        ];
+
+        return $this->connection->request("GetCalendarResourceRequest", $params);
+    }
+
+    /**
+     * @param \ModulesGarden\Servers\ZimbraEmail\App\Libs\Zimbra\Components\Api\Soap\Models\Ressource $ressource
+     * @return \ModulesGarden\Servers\ZimbraEmail\App\Libs\Zimbra\Components\Api\Soap\Response
+     */
+    public function getRessourceOptions(\ModulesGarden\Servers\ZimbraEmail\App\Libs\Zimbra\Components\Api\Soap\Models\Ressource $ressource)
+    {
+        if($value = $ressource->getId())
+        {
+            $type = 'id';
+        }elseif($value =$ressource->getName())
+        {
+            $type = 'name';
+        }
+
+        $params = [
+            new SoapVar('<ns1:calresource by="' . $type . '">' . $value . '</ns1:calresource>', XSD_ANYXML),
+        ];
+
+        return  $this->connection
+            ->cleanResponse()
+            ->request("GetCalendarResourceRequest", $params);
+    }
+
+    /**
+     * @param \ModulesGarden\Servers\ZimbraEmail\App\Libs\Zimbra\Components\Api\Soap\Models\Domain $domain
+     * @return \ModulesGarden\Servers\ZimbraEmail\App\Libs\Zimbra\Components\Api\Soap\Response
+     */
+    public function getAllByDomain(\ModulesGarden\Servers\ZimbraEmail\App\Libs\Zimbra\Components\Api\Soap\Models\Domain $domain)
+    {
+        if($value = $domain->getId())
+        {
+            $type = 'id';
+        }elseif($value =$domain->getName())
+        {
+            $type = 'name';
+        }
+
+        $params = [
+            new SoapVar('<ns1:domain by="' . $type . '">' . $value . '</ns1:domain>', XSD_ANYXML),
+        ];
+        $result = $this->connection->request("GetAllCalendarResourcesRequest", $params);
+        return $result;
+    }
+
+    public function getAllRessources($idOrNameDomain, $type = "auto")
+    {
+        if ($type == "auto")
+        {
+            //$realType = getDomainType($idOrNameDomain);
+        }
+        else
+        {
+            $realType = $type;
+        }
+
+        $result = null;
+
+        $params = [
+            new SoapVar('<ns1:domain by="' . $realType . '">' . $idOrNameDomain . '</ns1:domain>', XSD_ANYXML),
+        ];
+
+        return  $this->connection->request("GetAllCalendarResourcesRequest", $params);
+
+    }
+
+}

+ 6 - 2
app/Libs/Zimbra/Components/Api/Soap/Connection.php

@@ -113,8 +113,10 @@ class Connection implements ConnectionInterface
             [
                 'location'       => $location,
                 'uri'            => $uri,
+                'default_socket_timeout' => 10,
                 'trace'          => 1,
                 'exceptions'     => 1,
+                'keep_alive'     => false,
                 'soap_version'   => SOAP_1_2,
                 'style'          => SOAP_RPC,
                 'use'            => SOAP_LITERAL,
@@ -272,6 +274,7 @@ class Connection implements ConnectionInterface
      */
     public function request($request, $params = [], $options = [])
     {
+
         /**
          * headers
          */
@@ -284,6 +287,7 @@ class Connection implements ConnectionInterface
         /**
          * main request
          */
+    
         try
         {
 
@@ -307,7 +311,7 @@ class Connection implements ConnectionInterface
         {
             $response->setLastError($ex->getMessage());
         }
-
+        
         /**
          * Zimbra api response
          */
@@ -324,7 +328,7 @@ class Connection implements ConnectionInterface
             ->setHeaders($soapHeader)
             ->setXmlResponse($soapRes)
             ->response();
-
+    
         return $response;
     }
 

+ 36 - 0
app/Libs/Zimbra/Components/Api/Soap/Helpers/RessourceHelper.php

@@ -0,0 +1,36 @@
+<?php
+
+namespace ModulesGarden\Servers\ZimbraEmail\App\Libs\Zimbra\Components\Api\Soap\Helpers;
+
+
+use ModulesGarden\Servers\ZimbraEmail\App\Enums\ProductParams;
+use ModulesGarden\Servers\ZimbraEmail\App\Enums\Size;
+
+/**
+ *
+ * Created by PhpStorm.
+ * User: Tomasz Bielecki ( tomasz.bi@modulesgarden.com )
+ * Date: 18.09.19
+ * Time: 09:22
+ * Class RessourceHelper
+ */
+class RessourceHelper
+{
+
+    /**
+     * @description return formatted data per API data
+     * @param $date
+     * @return false|string|null
+     */
+    public static function getFormattedData($date, $format = 'd/m/Y')
+    {
+        if(!$date)
+        {
+            return null;
+        }
+        $tmpDate = strstr($date, '.', true);
+        $tmpDate = $tmpDate ? $tmpDate : $date;
+
+        return date($format, strtotime($tmpDate));
+    }
+}

+ 140 - 0
app/Libs/Zimbra/Components/Api/Soap/Models/Ressource.php

@@ -0,0 +1,140 @@
+<?php
+
+namespace ModulesGarden\Servers\ZimbraEmail\App\Libs\Zimbra\Components\Api\Soap\Models;
+
+
+use ModulesGarden\Servers\ZimbraEmail\App\Libs\Zimbra\Components\Api\Soap\Interfaces\AbstractModel;
+
+/**
+ *
+ * Created by PhpStorm.
+ * User: Tomasz Bielecki ( tomasz.bi@modulesgarden.com )
+ * Date: 10.09.19
+ * Time: 08:43
+ * Class Ressource
+ */
+class Ressource extends AbstractModel
+{
+    /**
+     * Ressource Attributes
+     */
+    const ATTR_NAME         = 'name';
+    const ATTR_STATUS       = 'zimbraAccountStatus';
+    const ATTR_TYPE         = 'zimbraCalResType';
+    const ATTR_DISPLAY_NAME = 'displayName';
+    const ATTR_DESC         = 'description';
+    const ATTR_NOTE         = 'zimbraNotes';
+    const ATTR_CONT         = 'zimbraCalResContactName';
+    const ATTR_CONT_EMAIL   = 'zimbraCalResContactEmail';
+    const ATTR_CONT_PHONE   = 'zimbraCalResContactPhone';
+    const ATTR_SITE         = 'zimbraCalResSite';
+    const ATTR_BUILDING     = 'zimbraCalResBuilding';
+    const ATTR_FLOOR        = 'zimbraCalResFloor';
+    const ATTR_ROOM         = 'zimbraCalResRoom';
+    const ATTR_CAPACITY     = 'zimbraCalResCapacity';
+    const ATTR_STREET       = 'street';
+    const ATTR_TOWN         = 'l';
+    const ATTR_POSTAL_CODE  = 'postalCode';
+    const ATTR_COUNTY       = 'st';
+    const ATTR_STATE        = 'co';
+    const ATTR_AUTO         = 'zimbraCalResAutoAcceptDecline';
+    const ATTR_BUSY         = 'zimbraCalResAutoDeclineIfBusy';
+
+    protected $id;
+    protected $name;
+    protected $password;
+    protected $attrs;
+
+    /**
+     * @return mixed
+     */
+    public function getName()
+    {
+        return $this->name;
+    }
+
+    /**
+     * @param $name
+     * @return $this
+     */
+    public function setName($name)
+    {
+        $this->name = $name;
+        return $this;
+    }
+
+    /**
+     * @return mixed
+     */
+    public function getPassword()
+    {
+        return $this->password;
+    }
+
+    /**
+     * @param $password
+     * @return $this
+     */
+    public function setPassword($password)
+    {
+        $this->password = $password;
+        return $this;
+    }
+
+    /**
+     * @return mixed
+     */
+    public function getId()
+    {
+        return $this->id;
+    }
+
+    /**
+     * @param $id
+     * @return $this
+     */
+    public function setId($id)
+    {
+        $this->id = $id;
+        return $this;
+    }
+
+    /**
+     * @return mixed
+     */
+    public function getAttrs()
+    {
+        return $this->attrs;
+    }
+
+    /**
+     * @param $key
+     * @param null $value
+     * @return $this
+     */
+    public function setAttr($key, $value = null)
+    {
+        $this->attrs[$key] = $value;
+        return $this;
+    }
+
+    /**
+     * @param $key
+     * @return mixed
+     */
+    public function getAttr($key)
+    {
+        return $this->attrs[$key];
+    }
+
+    /**
+     * @param $attrs
+     * @return $this
+     */
+    public function setAttrs($attrs = [])
+    {
+        $this->attrs = $attrs;
+        return $this;
+    }
+
+}

+ 43 - 3
app/Libs/Zimbra/Components/Api/Soap/MySoapClient.php

@@ -31,7 +31,46 @@ class MySoapClient extends SoapClient
             $request = str_replace(array('ns1:DistributionListActionRequest', 'xmlns:ns2="urn:zimbra"'), array('ns2:DistributionListActionRequest', 'xmlns:ns2="urn:zimbraAccount"'), $request);
         }
 
-        return parent::__doRequest($request, $location, $action, $version);
+        $exception = null;
+
+        try {
+        
+            $response = parent::__doRequest($request, $location, $action, $version);
+        
+        }
+        
+        catch (SoapFault $sf) {
+        
+            //this code was not reached    
+        
+            $exception = $sf;
+        
+        }
+        
+        catch (Exception $e) {
+        
+            //nor was this code reached either
+        
+            $exception = $e;
+        
+        }
+        
+        if((isset($this->__soap_fault)) && ($this->__soap_fault != null)) {
+        
+            //this is where the exception from __doRequest is stored
+        
+            $exception = $this->__soap_fault;
+
+            logModuleCall(
+                'zimbraEmail',
+                __FUNCTION__,
+                $exception,
+                "Debug: response",
+                $result
+            );
+        }
+        
+        return $response;
     }
 
     /**
@@ -44,8 +83,9 @@ class MySoapClient extends SoapClient
      */
     public function __soapCall($function_name, array $arguments, array $options = null, $input_headers = null, array &$output_headers = null)
     {
-        //todo logg
-        return parent::__soapCall($function_name, $arguments, $options, $input_headers, $output_headers); // TODO: Change the autogenerated stub
+        $response = parent::__soapCall($function_name, $arguments, $options, $input_headers, $output_headers);
+
+        return $response;
     }
 
 

+ 9 - 0
app/Libs/Zimbra/Components/Api/Soap/Repository.php

@@ -6,6 +6,7 @@ namespace ModulesGarden\Servers\ZimbraEmail\App\Libs\Zimbra\Components\Api\Soap;
 use ModulesGarden\Servers\ZimbraEmail\App\Libs\Zimbra\Components\Api\Soap\Interfaces\AbstractApiClient;
 use ModulesGarden\Servers\ZimbraEmail\App\Libs\Zimbra\Components\Api\Soap\Interfaces\AbstractConnection;
 use ModulesGarden\Servers\ZimbraEmail\App\Libs\Zimbra\Components\Api\Soap\Repository\Accounts;
+use ModulesGarden\Servers\ZimbraEmail\App\Libs\Zimbra\Components\Api\Soap\Repository\Ressources;
 use ModulesGarden\Servers\ZimbraEmail\App\Libs\Zimbra\Components\Api\Soap\Repository\ClassOfServices;
 use ModulesGarden\Servers\ZimbraEmail\App\Libs\Zimbra\Components\Api\Soap\Repository\Server;
 use ModulesGarden\Servers\ZimbraEmail\App\Libs\Zimbra\Components\Api\Soap\Repository\DistributionLists;
@@ -83,6 +84,14 @@ class Repository extends AbstractApiClient
         return new Accounts($this->getClient());
     }
 
+    /**
+     * @return Ressources
+     */
+    public function ressources()
+    {
+        return new Ressources($this->getClient());
+    }
+
     /**
      *
      */

+ 136 - 0
app/Libs/Zimbra/Components/Api/Soap/Repository/Ressources.php

@@ -0,0 +1,136 @@
+<?php
+
+namespace ModulesGarden\Servers\ZimbraEmail\App\Libs\Zimbra\Components\Api\Soap\Repository;
+
+
+use ModulesGarden\Servers\ZimbraEmail\App\Enums\Size;
+use ModulesGarden\Servers\ZimbraEmail\App\Libs\Zimbra\Components\Api\Soap\Interfaces\AbstractApiClient;
+use ModulesGarden\Servers\ZimbraEmail\App\Libs\Zimbra\Components\Api\Soap\Interfaces\AbstractRepository;
+use ModulesGarden\Servers\ZimbraEmail\App\Libs\Zimbra\Components\Api\Soap\Models\Ressource;
+use ModulesGarden\Servers\ZimbraEmail\App\Libs\Zimbra\Components\Api\Soap\Models\RessourceAlias;
+use ModulesGarden\Servers\ZimbraEmail\App\Libs\Zimbra\Components\Api\Soap\Models\Domain;
+
+/**
+ *
+ * Created by PhpStorm.
+ * User: Tomasz Bielecki ( tomasz.bi@modulesgarden.com )
+ * Date: 10.09.19
+ * Time: 08:28
+ * Class Ressources
+ */
+class Ressources extends AbstractRepository
+{
+    /**
+     * get all ressource for domain
+     * @param $name
+     * @return mixed
+     */
+    public function getByDomainName($name)
+    {
+        $domain = new Domain();
+        $domain->setName($name);
+
+        $result = $this->getClient()->ressource->getAllByDomain($domain);
+        $ressources = $result->getResponseBody()['GETALLCALENDARRESOURCESRESPONSE']['CALRESOURCE'];
+        /**
+         * API return one or araay with ressources
+         */
+        $tmp = [];
+        if(isset($ressources['NAME']))
+        {
+            $tmpRessource =  new Ressource($ressources);
+
+            /**
+             * skip ZiImbra default ressource
+             */
+            if (strpos($tmpRessource->getName(), 'galsync@') !== false)
+            {
+                return [];
+            }
+            $tmp[$tmpRessource->getId()] = $tmpRessource;
+        }else{
+            foreach($ressources as $ressource)
+            {
+                $tmpRessource =  new Ressource($ressource);
+
+                /**
+                 * skip ZiImbra default ressource
+                 */
+                if (strpos($tmpRessource->getName(), 'galsync@') !== false)
+                {
+                    continue;
+                }
+
+
+                $tmp[$tmpRessource->getId()] = $tmpRessource;
+            }
+        }
+
+       return $tmp;
+    }
+
+    /**
+     * @param $name
+     * @return mixed
+     */
+    public function getRessources($name)
+    {
+        $ressources = $this->getByDomainName($name);
+
+        foreach($ressources as $key => $ressource)
+        {
+            /* @var $ressource Ressource*/
+            if (strpos($ressource->getName(), 'galsync@') !== false)
+            {
+                unset($ressources[$key]);
+                continue;
+            }
+
+        }
+
+        return $ressources;
+    }
+
+    /**
+     * @param $id
+     * @return Ressource
+     */
+    public function getRessourceInfoById($id)
+    {
+        $ressource = new Ressource();
+        $ressource->setId($id);
+
+        $result = $this->getClient()->ressource->getRessourceInfo($ressource);
+
+        if(!$result->getLastError())
+        {
+            $body = $result->getResponseBody();
+            $result =  $ressource->fill($body['GETCALENDARRESOURCERESPONSE']);
+            $result->setName($body['GETCALENDARRESOURCERESPONSE']['NAME']['DATA']);
+            return $result;
+        }
+
+        return $result;
+    }
+
+    /**
+     * @param $id
+     * @return Ressource
+     */
+    public function getRessourceOptionsById($id)
+    {
+        $ressource = new Ressource();
+        $ressource->setId($id);
+
+        $result = $this->getClient()->ressource->getRessourceOptions($ressource);
+
+        if(!$result->getLastError())
+        {
+            $body = $result->getResponseBody();
+            return $ressource->fill($body['GETCALENDARRESOURCERESPONSE']['CALRESOURCE']);
+        }
+
+        return $result;
+    }
+
+}

+ 55 - 0
app/Libs/Zimbra/Components/Api/Soap/Services.php

@@ -10,11 +10,13 @@ use ModulesGarden\Servers\ZimbraEmail\App\Libs\Zimbra\Components\Api\Soap\Servic
 use ModulesGarden\Servers\ZimbraEmail\App\Libs\Zimbra\Components\Api\Soap\Services\Create\CreateDistributionList;
 use ModulesGarden\Servers\ZimbraEmail\App\Libs\Zimbra\Components\Api\Soap\Services\Create\CreateDomain;
 use ModulesGarden\Servers\ZimbraEmail\App\Libs\Zimbra\Components\Api\Soap\Services\Create\CreateDomainAlias;
+use ModulesGarden\Servers\ZimbraEmail\App\Libs\Zimbra\Components\Api\Soap\Services\Create\CreateRessource;
 use ModulesGarden\Servers\ZimbraEmail\App\Libs\Zimbra\Components\Api\Soap\Services\Delete\DeleteAccount;
 use ModulesGarden\Servers\ZimbraEmail\App\Libs\Zimbra\Components\Api\Soap\Services\Delete\DeleteAccountAlias;
 use ModulesGarden\Servers\ZimbraEmail\App\Libs\Zimbra\Components\Api\Soap\Services\Delete\DeleteDistributionList;
 use ModulesGarden\Servers\ZimbraEmail\App\Libs\Zimbra\Components\Api\Soap\Services\Delete\DeleteDomain;
 use ModulesGarden\Servers\ZimbraEmail\App\Libs\Zimbra\Components\Api\Soap\Services\Delete\DeleteDomainAlias;
+use ModulesGarden\Servers\ZimbraEmail\App\Libs\Zimbra\Components\Api\Soap\Services\Delete\DeleteRessource;
 use ModulesGarden\Servers\ZimbraEmail\App\Libs\Zimbra\Components\Api\Soap\Services\Sso\ClientSingleSignOn;
 use ModulesGarden\Servers\ZimbraEmail\App\Libs\Zimbra\Components\Api\Soap\Services\Sso\ClientSingleSignOnToken;
 use ModulesGarden\Servers\ZimbraEmail\App\Libs\Zimbra\Components\Api\Soap\Services\Update\ChangePackage;
@@ -29,6 +31,9 @@ use ModulesGarden\Servers\ZimbraEmail\App\Libs\Zimbra\Components\Api\Soap\Servic
 use ModulesGarden\Servers\ZimbraEmail\App\Libs\Zimbra\Components\Api\Soap\Services\Update\UpdateAccountPassword;
 use ModulesGarden\Servers\ZimbraEmail\App\Libs\Zimbra\Components\Api\Soap\Services\Update\UpdateAccountStatus;
 use ModulesGarden\Servers\ZimbraEmail\App\Libs\Zimbra\Components\Api\Soap\Services\Update\UpdateDistributionList;
+use ModulesGarden\Servers\ZimbraEmail\App\Libs\Zimbra\Components\Api\Soap\Services\Update\UpdateRessource;
+use ModulesGarden\Servers\ZimbraEmail\App\Libs\Zimbra\Components\Api\Soap\Services\Update\UpdateRessourceStatus;
+use ModulesGarden\Servers\ZimbraEmail\App\Libs\Zimbra\Components\Api\Soap\Services\Update\UpdateRessourcePassword;
 use ModulesGarden\Servers\ZimbraEmail\App\Libs\Zimbra\Components\Api\Soap\Traits\ApiClientHandler;
 
 /**
@@ -125,6 +130,16 @@ class Services
         return new CreateDomainAlias($this->getApi());
     }
 
+    /**
+     * create ressource for account
+     *
+     * @return CreateRessource
+     */
+    public function createRessource()
+    {
+        return new CreateRessource($this->getApi());
+    }
+
     /**
      *
      * change product package
@@ -189,6 +204,26 @@ class Services
         return new UpdateAccountStatus($this->getApi());
     }
 
+    /**
+     * update ressource
+     *
+     * @return UpdateRessource
+     */
+    public function updateRessource()
+    {
+        return new UpdateRessource($this->getApi());
+    }
+
+    /**
+     * update ressource status
+     *
+     * @return UpdateRessourceStatus
+     */
+    public function updateRessourceStatus()
+    {
+        return new UpdateRessourceStatus($this->getApi());
+    }
+
     /**
      * change password service
      *
@@ -199,6 +234,16 @@ class Services
         return new UpdateAccountPassword($this->getApi());
     }
 
+    /**
+     * change password service
+     *
+     * @return UpdateRessourcePassword
+     */
+    public function updateRessourcePassword()
+    {
+        return new UpdateRessourcePassword($this->getApi());
+    }
+
     /**
      * distribution (mailing) list update service
      *
@@ -239,6 +284,16 @@ class Services
         return new DeleteAccount($this->getApi());
     }
 
+    /**
+     * delete ressource in panel
+     *
+     * @return DeleteRessource
+     */
+    public function deleteRessource()
+    {
+        return new DeleteRessource($this->getApi());
+    }
+
     /**
      * delete domain & each related things
      *

+ 137 - 0
app/Libs/Zimbra/Components/Api/Soap/Services/Create/CreateRessource.php

@@ -0,0 +1,137 @@
+<?php
+/**
+ * Class CreateRessource
+ * User: Nessandro
+ * Date: 2019-10-07
+ * Time: 10:41
+ * @package ModulesGarden\Servers\ZimbraEmail\App\Libs\Zimbra\Components\Api\Soap\Services\Create
+ */
+
+namespace ModulesGarden\Servers\ZimbraEmail\App\Libs\Zimbra\Components\Api\Soap\Services\Create;
+
+
+use ModulesGarden\Servers\ZimbraEmail\App\Enums\ProductParams;
+use ModulesGarden\Servers\ZimbraEmail\App\Enums\Size;
+use ModulesGarden\Servers\ZimbraEmail\App\Enums\Zimbra;
+use ModulesGarden\Servers\ZimbraEmail\App\Libs\Product\ProductManager;
+use ModulesGarden\Servers\ZimbraEmail\App\Libs\Zimbra\Components\Api\Soap\Interfaces\ApiService;
+use ModulesGarden\Servers\ZimbraEmail\App\Libs\Zimbra\Components\Api\Soap\Models\Ressource;
+use ModulesGarden\Servers\ZimbraEmail\App\Libs\Zimbra\Components\Api\Soap\Traits\ProductManagerHandler;
+use ModulesGarden\Servers\ZimbraEmail\Core\Helper\ConfigOptionsHelper;
+
+class CreateRessource extends ApiService
+{
+    use ProductManagerHandler;
+    use \ModulesGarden\Servers\ZimbraEmail\Core\UI\Traits\RequestObjectHandler;
+
+    /**
+     * added more conditions
+     * @return bool
+     */
+    protected function isValid()
+    {
+        /**
+         * check if product manager is set
+         */
+        if(!$this->productManager)
+        {
+            $this->setError('Product Manager Not Found');
+            return false;
+        }
+
+        /**
+         * domain name
+         */
+        if(!$this->formData['domain'])
+        {
+            $this->setError('Domain name can not be found.');
+            return false;
+        }
+
+        /**
+         *
+         */
+        return parent::isValid();
+    }
+
+    /**
+     * @return mixed
+     */
+    protected function getRessources()
+    {
+        $ressources = $this->api->repository()->ressources->getRessources($this->formData['domain']);
+        return $ressources;
+    }
+
+    /**
+     * @return Ressource
+     */
+    protected function getModel()
+    {
+        /**
+         * create new ressource in zimbra
+         */
+        $ressource = new Ressource();
+
+        $ressource->setName($this->formData['username'].'@'.$this->formData['domain']);
+        $ressource->setPassword(html_entity_decode($this->formData['password']), ENT_QUOTES);
+        /**
+         *  set ressource attributes
+         */
+        $ressource->setAttr(Ressource::ATTR_STATUS, $this->formData['status']);
+        $ressource->setAttr(Ressource::ATTR_TYPE, $this->formData['type']);
+        $ressource->setAttr(Ressource::ATTR_DISPLAY_NAME, $this->formData['display_name']);
+        $ressource->setAttr(Ressource::ATTR_DESC, $this->formData['description']);
+        $ressource->setAttr(Ressource::ATTR_NOTE, $this->formData['notes']);
+        $ressource->setAttr(Ressource::ATTR_CONT, $this->formData['contact']);
+        $ressource->setAttr(Ressource::ATTR_CONT_EMAIL, $this->formData['contact_mail']);
+        $ressource->setAttr(Ressource::ATTR_CONT_PHONE, $this->formData['contact_phone']);
+        $ressource->setAttr(Ressource::ATTR_SITE, $this->formData['site']);
+        $ressource->setAttr(Ressource::ATTR_BUILDING, $this->formData['building']);
+        $ressource->setAttr(Ressource::ATTR_FLOOR, $this->formData['floor']);
+        $ressource->setAttr(Ressource::ATTR_ROOM, $this->formData['room']);
+        $ressource->setAttr(Ressource::ATTR_CAPACITY, $this->formData['capacity']);
+        $ressource->setAttr(Ressource::ATTR_STREET, $this->formData['street']);
+        $ressource->setAttr(Ressource::ATTR_TOWN, $this->formData['town']);
+        $ressource->setAttr(Ressource::ATTR_POSTAL_CODE, $this->formData['post_code']);
+        $ressource->setAttr(Ressource::ATTR_COUNTY, $this->formData['county']);
+        $ressource->setAttr(Ressource::ATTR_STATE, $this->formData['state']);
+        $ressource->setAttr(Ressource::ATTR_AUTO, $this->formData['auto_accept'] == 'on' ? 'TRUE' : 'FALSE' );
+        $ressource->setAttr(Ressource::ATTR_BUSY, $this->formData['auto_busy'] == 'on' ? 'TRUE' : 'FALSE' );
+
+        foreach($this->productManager->getZimbraConfiguration() as $key => $value)
+        {
+            $value = $value === ProductParams::SWITCHER_ENABLED ? Zimbra::ATTR_ENABLED : Zimbra::ATTR_DISABLED;
+            $ressource->setAttr($key, $value);
+        }
+
+        return $ressource;
+    }
+
+    /**
+     * @return bool|mixed|Ressource|void
+     */
+    protected function process()
+    {
+        /**
+         *
+         */
+        $model = $this->getModel();
+
+        /**
+         * create ressource in ZIMBRA
+         */
+        $result = $this->api->ressource->create($model);
+
+        /**
+         * problem with create ressource
+         */
+        if(!$result)
+        {
+            $this->setError($this->api->ressource->getLastResult()->getLastErrorCode());
+            return false;
+        }
+
+        return $result;
+    }
+}

+ 43 - 0
app/Libs/Zimbra/Components/Api/Soap/Services/Delete/DeleteRessource.php

@@ -0,0 +1,43 @@
+<?php
+/**
+ * Class DeleteRessource
+ * User: Nessandro
+ * Date: 2019-09-17
+ * Time: 17:12
+ * @package ModulesGarden\Servers\ZimbraEmail\App\Libs\Zimbra\Components\Api\Soap\Services\Create
+ */
+
+namespace ModulesGarden\Servers\ZimbraEmail\App\Libs\Zimbra\Components\Api\Soap\Services\Delete;
+
+
+use ModulesGarden\Servers\ZimbraEmail\App\Libs\Zimbra\Components\Api\Soap\Interfaces\ApiService;
+use ModulesGarden\Servers\ZimbraEmail\App\Libs\Zimbra\Components\Api\Soap\Models\Ressource;
+
+class DeleteRessource extends ApiService
+{
+
+    /**
+     * remove ressource in APi
+     *
+     * @return bool|mixed
+     */
+    public function process()
+    {
+        $ressource = new Ressource();
+        $ressource->setId($this->formData['id']);
+
+        $result = $this->api->ressource->delete($ressource);
+
+        /**
+         * problem with remove ressource
+         */
+        if(!$result)
+        {
+            $this->setError($this->api->ressource->getLastResult()->getLastErrorCode());
+            return false;
+        }
+
+        return $result;
+    }
+
+}

+ 84 - 0
app/Libs/Zimbra/Components/Api/Soap/Services/Update/UpdateRessource.php

@@ -0,0 +1,84 @@
+<?php
+namespace ModulesGarden\Servers\ZimbraEmail\App\Libs\Zimbra\Components\Api\Soap\Services\Update;
+use ModulesGarden\Servers\ZimbraEmail\App\Enums\Size;
+use ModulesGarden\Servers\ZimbraEmail\App\Enums\ProductParams;
+use ModulesGarden\Servers\ZimbraEmail\App\Enums\Zimbra;
+use ModulesGarden\Servers\ZimbraEmail\App\Libs\Zimbra\Components\Api\Soap\Interfaces\ApiService;
+use ModulesGarden\Servers\ZimbraEmail\App\Libs\Zimbra\Components\Api\Soap\Models\Ressource;
+use ModulesGarden\Servers\ZimbraEmail\App\Libs\Zimbra\Components\Api\Soap\Services\Create\CreateRessource;
+
+/**
+ *
+ * Created by PhpStorm.
+ * User: Tomasz Bielecki ( tomasz.bi@modulesgarden.com )
+ * Date: 18.09.19
+ * Time: 11:09
+ * Class UpdateRessource
+ */
+class UpdateRessource extends CreateRessource
+{
+
+    /**
+     * @return bool|mixed|Ressource|void
+     */
+    protected function process()
+    {
+        /**
+         *
+         */
+        $model = $this->getModel();
+
+        /**
+         * update ressource in ZIMBRA
+         */
+        $result = $this->api->ressource->update($model);
+
+        /**
+         * problem with create ressource
+         */
+        if(!$result)
+        {
+            $this->setError($this->api->ressource->getLastResult()->getLastErrorCode());
+            return false;
+        }
+
+        return $result;
+    }
+
+    /**
+     * @return Ressource
+     */
+    public function getModel()
+    {
+        $ressource = new Ressource();
+        /**
+         *  set ressource attributes
+         */
+        $ressource->setId($this->formData['id']);
+
+        $ressource->setAttr(Ressource::ATTR_NAME, $this->formData['name']);
+        $ressource->setAttr(Ressource::ATTR_STATUS, $this->formData['status']);
+        $ressource->setAttr(Ressource::ATTR_TYPE, $this->formData['type']);
+        $ressource->setAttr(Ressource::ATTR_DISPLAY_NAME, $this->formData['display_name']);
+        $ressource->setAttr(Ressource::ATTR_DESC, $this->formData['description']);
+        $ressource->setAttr(Ressource::ATTR_NOTE, $this->formData['notes']);
+        $ressource->setAttr(Ressource::ATTR_CONT, $this->formData['contact']);
+        $ressource->setAttr(Ressource::ATTR_CONT_EMAIL, $this->formData['contact_mail']);
+        $ressource->setAttr(Ressource::ATTR_CONT_PHONE, $this->formData['contact_phone']);
+        $ressource->setAttr(Ressource::ATTR_SITE, $this->formData['site']);
+        $ressource->setAttr(Ressource::ATTR_BUILDING, $this->formData['building']);
+        $ressource->setAttr(Ressource::ATTR_FLOOR, $this->formData['floor']);
+        $ressource->setAttr(Ressource::ATTR_ROOM, $this->formData['room']);
+        $ressource->setAttr(Ressource::ATTR_CAPACITY, $this->formData['capacity']);
+        $ressource->setAttr(Ressource::ATTR_STREET, $this->formData['street']);
+        $ressource->setAttr(Ressource::ATTR_TOWN, $this->formData['town']);
+        $ressource->setAttr(Ressource::ATTR_POSTAL_CODE, $this->formData['post_code']);
+        $ressource->setAttr(Ressource::ATTR_COUNTY, $this->formData['county']);
+        $ressource->setAttr(Ressource::ATTR_STATE, $this->formData['state']);
+        $ressource->setAttr(Ressource::ATTR_AUTO, $this->formData['auto_accept'] == 'on' ? 'TRUE' : 'FALSE' );
+        $ressource->setAttr(Ressource::ATTR_BUSY, $this->formData['auto_busy'] == 'on' ? 'TRUE' : 'FALSE' );
+
+        return $ressource;
+
+    }
+}

+ 56 - 0
app/Libs/Zimbra/Components/Api/Soap/Services/Update/UpdateRessourcePassword.php

@@ -0,0 +1,56 @@
+<?php
+
+namespace ModulesGarden\Servers\ZimbraEmail\App\Libs\Zimbra\Components\Api\Soap\Services\Update;
+
+
+use ModulesGarden\Servers\ZimbraEmail\App\Libs\Zimbra\Components\Api\Soap\Interfaces\ApiService;
+use ModulesGarden\Servers\ZimbraEmail\App\Libs\Zimbra\Components\Api\Soap\Models\Ressource;
+use ModulesGarden\Servers\ZimbraEmail\App\Libs\Zimbra\Components\Api\Soap\Services\Create\CreateRessourceCosQuota;
+use ModulesGarden\Servers\ZimbraEmail\App\Libs\Zimbra\Components\Api\Soap\Traits\ProductManagerHandler;
+
+/**
+ *
+ * Created by PhpStorm.
+ * User: Tomasz Bielecki ( tomasz.bi@modulesgarden.com )
+ * Date: 08.11.19
+ * Time: 12:15
+ * Class UpdateRessourcePassword
+ */
+class UpdateRessourcePassword extends ApiService
+{
+    use ProductManagerHandler;
+
+    /**
+     * @return bool
+     */
+    public function isValid()
+    {
+        if(!$this->formData['id'])
+        {
+            $this->setError('Ressource Id name can not be found.');
+            return false;
+        }
+
+        return parent::isValid(); // TODO: Change the autogenerated stub
+    }
+
+    /**
+     * @return bool|mixed
+     */
+    public function process()
+    {
+        $ressource = new Ressource();
+        $ressource->setId($this->formData['id']);
+        $ressource->setPassword($this->formData['password']);
+
+        $result = $this->api->ressource->setPassword($ressource);
+
+        if(!$result)
+        {
+            $this->setError($this->api->ressource->getLastResult()->getLastErrorCode());
+            return false;
+        }
+
+        return true;
+    }
+}

+ 39 - 0
app/Libs/Zimbra/Components/Api/Soap/Services/Update/UpdateRessourceStatus.php

@@ -0,0 +1,39 @@
+<?php
+
+namespace ModulesGarden\Servers\ZimbraEmail\App\Libs\Zimbra\Components\Api\Soap\Services\Update;
+
+
+use ModulesGarden\Servers\ZimbraEmail\App\Libs\Zimbra\Components\Api\Soap\Interfaces\ApiService;
+use ModulesGarden\Servers\ZimbraEmail\App\Libs\Zimbra\Components\Api\Soap\Models\Ressource;
+use ModulesGarden\Servers\ZimbraEmail\App\Libs\Zimbra\Components\Api\Soap\Traits\ProductManagerHandler;
+
+/**
+ *
+ * Created by PhpStorm.
+ * User: Tomasz Bielecki ( tomasz.bi@modulesgarden.com )
+ * Date: 09.10.19
+ * Time: 09:00
+ * Class UpdateRessourceStatus
+ */
+class UpdateRessourceStatus extends ApiService
+{
+    use ProductManagerHandler;
+
+    public function process()
+    {
+        $model = new Ressource();
+        $model->setId($this->formData['id']);
+        $model->setAttr(Ressource::ATTR_STATUS, $this->formData['status']);
+
+        $result = $this->api->ressource->update($model);
+
+        if(!$result)
+        {
+            $this->setError($this->api->ressource->getLastResult()->getLastErrorCode());
+            return false;
+        }
+
+        return true;
+    }
+
+}

+ 3 - 0
app/UI/Admin/ProductConfiguration/Pages/Sections/ClientAreaFeatures.php

@@ -45,6 +45,9 @@ class ClientAreaFeatures extends BoxSectionExtended implements AdminArea
         $field = new Switcher('ca_goToWebmailPage');
         $leftSection->addField($field);
 
+        $field = new Switcher('ca_ressourcePage');
+        $leftSection->addField($field);
+
         return $leftSection;
 
     }

+ 2 - 1
app/UI/Admin/ProductConfiguration/Providers/ProductConfigurationDataProvider.php

@@ -43,6 +43,7 @@ class ProductConfigurationDataProvider extends BaseDataProvider implements Admin
             'domainBaseSize',
             'cos',
             'ca_emailAccountPage',
+            'ca_ressourcePage',
             'ca_distributionListPage',
             'ca_goToWebmailPage',
             'ca_emailAliasesPage',
@@ -120,7 +121,7 @@ class ProductConfigurationDataProvider extends BaseDataProvider implements Admin
 
         $manager    = new ZimbraManager();
         $repository = $manager->getApiByProduct($this->getRequestValue('id'))->soap->repository();
-        $cosList        = $repository->cos->all();
+        $cosList    = $repository->cos->all();
 
         /**
          * class of services from API

+ 1 - 1
app/UI/Client/EmailAccount/Pages/Accounts.php

@@ -47,7 +47,7 @@ class Accounts extends DataTable implements ClientArea
         'active'        => 'success',
         'locked'        => 'default',
         'maintenance'   => 'warning',
-        'closed'        =>'default',
+        'closed'        => 'default',
         'lockout'       => 'info',
         'pending'       => 'warning',
         'default'       => 'default'

+ 2 - 2
app/UI/Client/EmailAlias/Pages/Aliases.php

@@ -92,7 +92,7 @@ class Aliases extends DataTable implements ClientArea
         }
 
         $dataProv = new ArrayDataProvider();
-        $dataProv->setDefaultSorting('account', 'ASC')->setData($data);
+        $dataProv->setDefaultSorting('email_alias', 'ASC')->setData($data);
 
         $this->setDataProvider($dataProv);
     }
@@ -120,4 +120,4 @@ class Aliases extends DataTable implements ClientArea
 
         return !(count($accounts) > 0);
     }
-}
+}

+ 11 - 0
app/UI/Client/Home/Pages/Dashboard.php

@@ -63,6 +63,17 @@ class Dashboard extends BaseContainer implements ClientArea
             $this->addFeature($feature);
         }
 
+        /**
+         *
+         * check if ressource page is enabled
+         */
+        if($productManager->isControllerAccessible(ControllerEnums::RESSOURCE_PAGE))
+        {
+            $feature = new FeatureField('ressource');
+            $feature->setUrl(BuildUrlExtended::getProvisioningUrl('ressource'));
+            $this->addFeature($feature);
+        }
+
         /**
          *
          * check if distribution list page is enabled

+ 26 - 0
app/UI/Client/Ressource/Buttons/AddRessourceButton.php

@@ -0,0 +1,26 @@
+<?php
+namespace ModulesGarden\Servers\ZimbraEmail\App\UI\Client\Ressource\Buttons;
+use ModulesGarden\Servers\ZimbraEmail\App\UI\Client\Ressource\Modals\AddRessourceModal;
+use ModulesGarden\Servers\ZimbraEmail\Core\UI\Interfaces\ClientArea;
+use ModulesGarden\Servers\ZimbraEmail\Core\UI\Widget\Buttons\ButtonCreate;
+
+/**
+ *
+ * Created by PhpStorm.
+ * User: Tomasz Bielecki ( tomasz.bi@modulesgarden.com )
+ * Date: 10.09.19
+ * Time: 13:06
+ * Class AddRessourceButton
+ */
+class AddRessourceButton extends ButtonCreate implements ClientArea
+{
+    protected $id    = 'addRessourceButton';
+    protected $title = 'addRessourceButton';
+
+    public function initContent()
+    {
+        $this->initLoadModalAction(new AddRessourceModal());
+    }
+
+
+}

+ 30 - 0
app/UI/Client/Ressource/Buttons/ChangePasswordButton.php

@@ -0,0 +1,30 @@
+<?php
+
+namespace ModulesGarden\Servers\ZimbraEmail\App\UI\Client\Ressource\Buttons;
+
+
+use ModulesGarden\Servers\ZimbraEmail\App\UI\Client\Ressource\Modals\ChangePasswordModal;
+use ModulesGarden\Servers\ZimbraEmail\Core\UI\Interfaces\ClientArea;
+use ModulesGarden\Servers\ZimbraEmail\Core\UI\Widget\Buttons\ButtonDataTableModalAction;
+use ModulesGarden\Servers\ZimbraEmail\Core\UI\Widget\Buttons\DropdawnButtonWrappers\ButtonDropdownItem;
+
+/**
+ *
+ * Created by PhpStorm.
+ * User: Tomasz Bielecki ( tomasz.bi@modulesgarden.com )
+ * Date: 08.11.19
+ * Time: 12:07
+ * Class ChangePassword
+ */
+class ChangePasswordButton extends ButtonDropdownItem implements ClientArea
+{
+    protected $id    = 'changePassword';
+    protected $title = 'changePassword';
+    protected $icon  = 'lu-dropdown__link-icon lu-btn__icon lu-zmdi lu-zmdi-lock';
+
+    public function initContent()
+    {
+        $this->initLoadModalAction(new ChangePasswordModal());
+    }
+
+}

+ 31 - 0
app/UI/Client/Ressource/Buttons/ChangeStatusButton.php

@@ -0,0 +1,31 @@
+<?php
+/**
+ * Class ChangeStatusButton
+ * User: Nessandro
+ * Date: 2019-10-11
+ * Time: 11:29
+ * @package ModulesGarden\Servers\ZimbraEmail\App\UI\Client\Ressource\Buttons
+ */
+
+namespace ModulesGarden\Servers\ZimbraEmail\App\UI\Client\Ressource\Buttons;
+
+
+use ModulesGarden\Servers\ZimbraEmail\App\UI\Client\Ressource\Modals\AddRessourceModal;
+use ModulesGarden\Servers\ZimbraEmail\App\UI\Client\Ressource\Modals\ChangeStatusModal;
+use ModulesGarden\Servers\ZimbraEmail\Core\UI\Interfaces\ClientArea;
+use ModulesGarden\Servers\ZimbraEmail\Core\UI\Widget\Buttons\ButtonCreate;
+use ModulesGarden\Servers\ZimbraEmail\Core\UI\Widget\Buttons\ButtonDataTableModalAction;
+use ModulesGarden\Servers\ZimbraEmail\Core\UI\Widget\Buttons\DropdawnButtonWrappers\ButtonDropdownItem;
+
+class ChangeStatusButton extends ButtonDropdownItem implements ClientArea
+{
+    protected $id    = 'changeStatusButton';
+    protected $title = 'changeStatusButton';
+    protected $icon  = 'lu-dropdown__link-icon lu-btn__icon lu-zmdi lu-zmdi-refresh-sync';
+
+    public function initContent()
+    {
+        $this->initLoadModalAction(new ChangeStatusModal());
+    }
+
+}

+ 31 - 0
app/UI/Client/Ressource/Buttons/DeleteRessourceButton.php

@@ -0,0 +1,31 @@
+<?php
+
+namespace ModulesGarden\Servers\ZimbraEmail\App\UI\Client\Ressource\Buttons;
+
+
+use ModulesGarden\Servers\ZimbraEmail\App\UI\Client\Ressource\Modals\DeleteRessourceModal;
+use ModulesGarden\Servers\ZimbraEmail\Core\UI\Interfaces\ClientArea;
+use ModulesGarden\Servers\ZimbraEmail\Core\UI\Widget\Buttons\ButtonDataTableModalAction;
+use ModulesGarden\Servers\ZimbraEmail\Core\UI\Widget\Buttons\ButtonModal;
+use ModulesGarden\Servers\ZimbraEmail\Core\UI\Widget\Buttons\DropdawnButtonWrappers\ButtonDropdownItem;
+
+/**
+ *
+ * Created by PhpStorm.
+ * User: Tomasz Bielecki ( tomasz.bi@modulesgarden.com )
+ * Date: 18.09.19
+ * Time: 11:27
+ * Class DeleteRessourceButton
+ */
+class DeleteRessourceButton extends ButtonDataTableModalAction implements ClientArea
+{
+    protected $id    = 'deleteRessourceButton';
+    protected $title = 'deleteRessourceButton';
+
+    public function initContent()
+    {
+        $this->switchToRemoveBtn();
+        $this->initLoadModalAction(new DeleteRessourceModal());
+    }
+
+}

+ 32 - 0
app/UI/Client/Ressource/Buttons/EditRessourceButton.php

@@ -0,0 +1,32 @@
+<?php
+
+namespace ModulesGarden\Servers\ZimbraEmail\App\UI\Client\Ressource\Buttons;
+
+
+use ModulesGarden\Servers\ZimbraEmail\App\UI\Client\Ressource\Modals\EditRessourceModal;
+use \ModulesGarden\Servers\ZimbraEmail\Core\UI\Widget\Buttons\ButtonDataTableModalAction;
+use ModulesGarden\Servers\ZimbraEmail\App\UI\Client\Ressource\Modals\AddRessourceModal;
+use ModulesGarden\Servers\ZimbraEmail\Core\UI\Interfaces\ClientArea;
+use ModulesGarden\Servers\ZimbraEmail\Core\UI\Widget\Buttons\ButtonCustomAction;
+use ModulesGarden\Servers\ZimbraEmail\Core\UI\Widget\Buttons\ButtonModal;
+use ModulesGarden\Servers\ZimbraEmail\Core\UI\Widget\Buttons\DropdawnButtonWrappers\ButtonDropdownItem;
+
+/**
+ *
+ * Created by PhpStorm.
+ * User: Tomasz Bielecki ( tomasz.bi@modulesgarden.com )
+ * Date: 18.09.19
+ * Time: 09:29
+ * Class EditRessourceButton
+ */
+class EditRessourceButton extends ButtonDataTableModalAction implements ClientArea
+{
+    protected $id    = 'editRessourceButton';
+    protected $title = 'editRessourceButton';
+
+    public function initContent()
+    {
+        $this->initLoadModalAction(new EditRessourceModal());
+    }
+
+}

+ 103 - 0
app/UI/Client/Ressource/Buttons/LoginToPanelButton.php

@@ -0,0 +1,103 @@
+<?php
+
+namespace ModulesGarden\Servers\ZimbraEmail\App\UI\Client\Ressource\Buttons;
+
+
+use ModulesGarden\Servers\ZimbraEmail\Core\Helper\BuildUrl;
+use ModulesGarden\Servers\ZimbraEmail\Core\UI\Interfaces\ClientArea;
+use ModulesGarden\Servers\ZimbraEmail\Core\UI\Widget\Buttons\ButtonDataTableModalAction;
+use ModulesGarden\Servers\ZimbraEmail\Core\UI\Widget\Buttons\ButtonRedirect;
+use ModulesGarden\Servers\ZimbraEmail\Core\UI\Widget\Buttons\DropdawnButtonWrappers\ButtonDropdownItem;
+
+/**
+ *
+ * Created by PhpStorm.
+ * User: Tomasz Bielecki ( tomasz.bi@modulesgarden.com )
+ * Date: 12.11.19
+ * Time: 16:44
+ * Class LoginToPanel
+ */
+class LoginToPanelButton extends ButtonDropdownItem implements ClientArea
+{
+    protected $icon           = 'lu-dropdown__link-icon lu-btn__icon lu-zmdi lu-zmdi-email';
+
+    protected $rawUrl = null;
+    protected $redirectParams = [];
+
+    public function initContent()
+    {
+        $this->htmlAttributes['@click.middle'] = 'redirect($event, ' . $this->parseCustomParams() . ', true)';
+        $this->htmlAttributes['@click'] = 'redirect($event, ' . $this->parseCustomParams() . ', true)';
+
+    }
+
+    protected function parseCustomParams()
+    {
+        if (count($this->redirectParams) === 0 && $this->rawUrl === null)
+        {
+            return '{}';
+        }
+
+        return $this->parseListTOJsString($this->redirectParams);
+    }
+
+    protected function parseListTOJsString($params)
+    {
+        $jsString = '{';
+
+        if ($this->rawUrl !== null)
+        {
+            $params['rawUrl'] = $this->rawUrl;
+        }
+
+        foreach ($params as $key => $value)
+        {
+            $jsString .= ' ' . str_replace('-', '__', $key) . ': ' . (is_array($value) ? ($this->parseListTOJsString($value) . ',') : ("'" . (string) $value) . "',");
+        }
+
+        $jsString = trim($jsString, ',') . ' } ';
+
+        return $jsString;
+    }
+
+    public function setRawUrl($url)
+    {
+        $this->rawUrl = $url;
+
+        return $this;
+    }
+
+    public function addRedirectParam($key, $value)
+    {
+        $this->redirectParams[$key] = $value;
+
+        $this->updateHtmlAttributesByRedirectParams();
+
+        return $this;
+    }
+
+    public function setRedirectParams($paramsList)
+    {
+        $this->redirectParams = $paramsList;
+
+        $this->updateHtmlAttributesByRedirectParams();
+
+        return $this;
+    }
+
+    protected function updateHtmlAttributesByRedirectParams()
+    {
+        foreach ($this->redirectParams as $key => $value)
+        {
+            $this->updateHtmlAttribute($key, $value);
+        }
+    }
+
+    protected function updateHtmlAttribute($key, $value)
+    {
+        if (strpos($value, ':') === 0)
+        {
+            $this->addHtmlAttribute(':data-' . $key , 'dataRow.' . trim($value, ':'));
+        }
+    }
+}

+ 28 - 0
app/UI/Client/Ressource/Buttons/MassChangeStatusButton.php

@@ -0,0 +1,28 @@
+<?php
+/**
+ * Class MassChangeStatusButton
+ * User: Nessandro
+ * Date: 2019-10-11
+ * Time: 11:29
+ * @package ModulesGarden\Servers\ZimbraEmail\App\UI\Client\Ressource\Buttons
+ */
+
+namespace ModulesGarden\Servers\ZimbraEmail\App\UI\Client\Ressource\Buttons;
+
+
+use ModulesGarden\Servers\ZimbraEmail\App\UI\Client\Ressource\Modals\MassChangeStatusModal;
+use ModulesGarden\Servers\ZimbraEmail\Core\UI\Interfaces\ClientArea;
+use ModulesGarden\Servers\ZimbraEmail\Core\UI\Widget\Buttons\ButtonMassAction;
+
+class MassChangeStatusButton extends ButtonMassAction implements ClientArea
+{
+    protected $id    = 'massChangeStatusButton';
+    protected $title = 'massChangeStatusButton';
+    protected $icon  = 'lu-btn__icon lu-zmdi lu-zmdi-refresh-sync';
+
+    public function initContent()
+    {
+        $this->initLoadModalAction(new MassChangeStatusModal());
+    }
+
+}

+ 28 - 0
app/UI/Client/Ressource/Buttons/MassDeleteRessourceButton.php

@@ -0,0 +1,28 @@
+<?php
+/**
+ * Class MassDeleteRessourceButton
+ * User: Nessandro
+ * Date: 2019-10-11
+ * Time: 11:29
+ * @package ModulesGarden\Servers\ZimbraEmail\App\UI\Client\Ressource\Buttons
+ */
+
+namespace ModulesGarden\Servers\ZimbraEmail\App\UI\Client\Ressource\Buttons;
+
+
+use ModulesGarden\Servers\ZimbraEmail\App\UI\Client\Ressource\Modals\MassDeleteRessourceModal;
+use ModulesGarden\Servers\ZimbraEmail\Core\UI\Interfaces\ClientArea;
+use ModulesGarden\Servers\ZimbraEmail\Core\UI\Widget\Buttons\ButtonMassAction;
+
+class MassDeleteRessourceButton extends ButtonMassAction implements ClientArea
+{
+
+    protected $id    = 'massDeleteRessourceButton';
+    protected $title = 'massDeleteRessourceButton';
+
+    public function initContent()
+    {
+        $this->switchToRemoveBtn(); 
+        $this->initLoadModalAction(new MassDeleteRessourceModal());
+    }
+}

+ 19 - 0
app/UI/Client/Ressource/Buttons/SpanDropdownButton.php

@@ -0,0 +1,19 @@
+<?php
+
+namespace ModulesGarden\Servers\ZimbraEmail\App\UI\Client\Ressource\Buttons;
+
+
+use ModulesGarden\Servers\ZimbraEmail\Core\UI\Widget\Buttons\DropdawnButtonWrappers\ButtonDropdown;
+
+/**
+ *
+ * Created by PhpStorm.
+ * User: Tomasz Bielecki ( tomasz.bi@modulesgarden.com )
+ * Date: 13.11.19
+ * Time: 08:53
+ * Class SpanDropdownButton
+ */
+class SpanDropdownButton extends ButtonDropdown
+{
+    protected $id = 'spanDropdownButton';
+}

+ 58 - 0
app/UI/Client/Ressource/Forms/AddRessourceForm.php

@@ -0,0 +1,58 @@
+<?php
+namespace ModulesGarden\Servers\ZimbraEmail\App\UI\Client\Ressource\Forms;
+use ModulesGarden\Servers\ZimbraEmail\App\Libs\Product\ProductManager;
+use ModulesGarden\Servers\ZimbraEmail\App\Libs\Zimbra\Components\Api\Soap\Models\ClassOfService;
+use ModulesGarden\Servers\ZimbraEmail\App\Libs\Zimbra\Components\Api\Soap\Repository\ClassOfServices;
+use ModulesGarden\Servers\ZimbraEmail\App\Traits\FormExtendedTrait;
+use ModulesGarden\Servers\ZimbraEmail\App\UI\Admin\Custom\Forms\SortedFieldForm;
+use ModulesGarden\Servers\ZimbraEmail\App\UI\Admin\Custom\Sections\RowSection;
+use ModulesGarden\Servers\ZimbraEmail\App\UI\Client\Ressource\Providers\RessourceDataProvider;
+use ModulesGarden\Servers\ZimbraEmail\App\UI\Client\Ressource\Sections\AdditionalSection;
+use ModulesGarden\Servers\ZimbraEmail\App\UI\Client\Ressource\Sections\GeneralSection;
+use ModulesGarden\Servers\ZimbraEmail\App\Validators\PasswordsValidator;
+use ModulesGarden\Servers\ZimbraEmail\App\Validators\RepeatPasswordValidator;
+use function ModulesGarden\Servers\ZimbraEmail\Core\Helper\di;
+use ModulesGarden\Servers\ZimbraEmail\Core\UI\Interfaces\ClientArea;
+use ModulesGarden\Servers\ZimbraEmail\Core\UI\Widget\Forms\BaseForm;
+use ModulesGarden\Servers\ZimbraEmail\Core\UI\Widget\Forms\Fields\Hidden;
+use ModulesGarden\Servers\ZimbraEmail\Core\UI\Widget\Forms\Fields\Password;
+use ModulesGarden\Servers\ZimbraEmail\Core\UI\Widget\Forms\Fields\Select;
+use ModulesGarden\Servers\ZimbraEmail\Core\UI\Widget\Forms\Fields\Text;
+use ModulesGarden\Servers\ZimbraEmail\Core\UI\Widget\Forms\FormConstants;
+use ModulesGarden\Servers\ZimbraEmail\Core\UI\Widget\Forms\Sections\HalfPageSection;
+use ModulesGarden\Servers\ZimbraEmail\Core\UI\Widget\Forms\Sections\InputGroup;
+use ModulesGarden\Servers\ZimbraEmail\Core\UI\Widget\Forms\Fields\InputGroupElements;
+use ModulesGarden\Servers\ZimbraEmail\Core\UI\Widget\Forms\Sections\RawSection;
+
+/**
+ *
+ * Created by PhpStorm.
+ * User: Tomasz Bielecki ( tomasz.bi@modulesgarden.com )
+ * Date: 10.09.19
+ * Time: 13:06
+ * Class AddRessourceForm
+ */
+class AddRessourceForm extends SortedFieldForm implements ClientArea
+{
+    use FormExtendedTrait;
+
+    protected $id    = 'addRessourceForm';
+    protected $name  = 'addRessourceForm';
+    protected $title = 'addRessourceForm';
+
+    public function initContent()
+    {
+        $this->setFormType(FormConstants::CREATE);
+        $this->setProvider(new RessourceDataProvider());
+        $this->initFields();
+        $this->loadDataToForm();
+    }
+
+    public function initFields()
+    {
+        $this->addSection(new GeneralSection());
+        $this->addSection(new AdditionalSection());
+
+
+    }
+}

+ 58 - 0
app/UI/Client/Ressource/Forms/ChangePasswordForm.php

@@ -0,0 +1,58 @@
+<?php
+
+namespace ModulesGarden\Servers\ZimbraEmail\App\UI\Client\Ressource\Forms;
+
+
+use ModulesGarden\Servers\ZimbraEmail\App\UI\Client\Ressource\Providers\EditRessourceDataProvider;
+use ModulesGarden\Servers\ZimbraEmail\App\Validators\PasswordsValidator;
+use ModulesGarden\Servers\ZimbraEmail\App\Validators\RepeatPasswordValidator;
+use ModulesGarden\Servers\ZimbraEmail\Core\UI\Interfaces\ClientArea;
+use ModulesGarden\Servers\ZimbraEmail\Core\UI\Widget\Forms\BaseForm;
+use ModulesGarden\Servers\ZimbraEmail\Core\UI\Widget\Forms\Fields\Hidden;
+use ModulesGarden\Servers\ZimbraEmail\Core\UI\Widget\Forms\Fields\Password;
+use ModulesGarden\Servers\ZimbraEmail\Core\UI\Widget\Forms\Fields\Select;
+
+/**
+ *
+ * Created by PhpStorm.
+ * User: Tomasz Bielecki ( tomasz.bi@modulesgarden.com )
+ * Date: 08.11.19
+ * Time: 12:07
+ * Class ChangePasswordForm
+ */
+class ChangePasswordForm extends BaseForm implements ClientArea
+{
+
+
+    protected $id    = 'changePasswordForm';
+    protected $name  = 'changePasswordForm';
+    protected $title = 'changePasswordForm';
+
+    protected function getDefaultActions()
+    {
+        return ['changePassword'];
+    }
+
+    public function initContent()
+    {
+        $this->setFormType('changePassword');
+        $this->dataProvider = new EditRessourceDataProvider();
+
+        $field = new Hidden('id');
+        $this->addField($field);
+
+        /**end**/
+        $field = new Password('password');
+        $field->setDescription('description');
+        $field->addValidator(new PasswordsValidator());
+        $field->notEmpty();
+        $this->addField($field);
+
+        $field = (new Password('repeat_password'))->addValidator(new RepeatPasswordValidator());
+        $field->notEmpty();
+        $this->addField($field);
+
+        $this->loadDataToForm();
+    }
+
+}

+ 47 - 0
app/UI/Client/Ressource/Forms/ChangeStatusForm.php

@@ -0,0 +1,47 @@
+<?php
+
+namespace ModulesGarden\Servers\ZimbraEmail\App\UI\Client\Ressource\Forms;
+
+
+use ModulesGarden\Servers\ZimbraEmail\App\UI\Client\Ressource\Providers\RessourceDataProvider;
+use ModulesGarden\Servers\ZimbraEmail\App\UI\Client\Ressource\Providers\EditRessourceDataProvider;
+use ModulesGarden\Servers\ZimbraEmail\Core\UI\Interfaces\ClientArea;
+use ModulesGarden\Servers\ZimbraEmail\Core\UI\Widget\Forms\BaseForm;
+use ModulesGarden\Servers\ZimbraEmail\Core\UI\Widget\Forms\Fields\Hidden;
+use ModulesGarden\Servers\ZimbraEmail\Core\UI\Widget\Forms\Fields\Select;
+use ModulesGarden\Servers\ZimbraEmail\Core\UI\Widget\Forms\FormConstants;
+
+/**
+ *
+ * Created by PhpStorm.
+ * User: Tomasz Bielecki ( tomasz.bi@modulesgarden.com )
+ * Date: 16.10.19
+ * Time: 13:20
+ * Class ChangeStatusForm
+ */
+class ChangeStatusForm extends BaseForm implements ClientArea
+{
+    protected $id    = 'changeStatusForm';
+    protected $name  = 'changeStatusForm';
+    protected $title = 'changeStatusForm';
+
+    protected function getDefaultActions()
+    {
+        return ['updateStatus'];
+    }
+
+    public function initContent()
+    {
+        $this->setFormType('updateStatus');
+        $this->dataProvider = new EditRessourceDataProvider();
+
+        $field = new Hidden('id');
+        $this->addField($field);
+
+        $field = new Select('status');
+        $this->addField($field);
+
+        $this->loadDataToForm();
+    }
+
+}

+ 40 - 0
app/UI/Client/Ressource/Forms/DeleteRessourceForm.php

@@ -0,0 +1,40 @@
+<?php
+
+namespace ModulesGarden\Servers\ZimbraEmail\App\UI\Client\Ressource\Forms;
+
+
+use ModulesGarden\Servers\ZimbraEmail\App\UI\Client\Ressource\Providers\DeleteRessourceDataProvider;
+use ModulesGarden\Servers\ZimbraEmail\Core\UI\Interfaces\ClientArea;
+use ModulesGarden\Servers\ZimbraEmail\Core\UI\Widget\Forms\BaseForm;
+use ModulesGarden\Servers\ZimbraEmail\Core\UI\Widget\Forms\Fields\Hidden;
+use ModulesGarden\Servers\ZimbraEmail\Core\UI\Widget\Forms\FormConstants;
+
+/**
+ *
+ * Created by PhpStorm.
+ * User: Tomasz Bielecki ( tomasz.bi@modulesgarden.com )
+ * Date: 18.09.19
+ * Time: 11:28
+ * Class DeleteRessourceForm
+ */
+class DeleteRessourceForm extends BaseForm implements ClientArea
+{
+    protected $id    = 'deleteRessourceForm';
+    protected $name  = 'deleteRessourceForm';
+    protected $title = 'deleteRessourceForm';
+
+    public function initContent()
+    {
+        $this->setFormType(FormConstants::DELETE);
+        $this->dataProvider = new DeleteRessourceDataProvider();
+
+        $this->setConfirmMessage('confirmRemoveRessource');
+
+        $field = new Hidden();
+        $field->setId('id');
+        $field->setName('id');
+        $this->addField($field);
+
+        $this->loadDataToForm();
+    }
+}

+ 55 - 0
app/UI/Client/Ressource/Forms/EditRessourceForm.php

@@ -0,0 +1,55 @@
+<?php
+
+namespace ModulesGarden\Servers\ZimbraEmail\App\UI\Client\Ressource\Forms;
+
+
+use ModulesGarden\Servers\ZimbraEmail\App\Libs\Product\ProductManager;
+use ModulesGarden\Servers\ZimbraEmail\App\Libs\Zimbra\Components\Api\Soap\Repository\ClassOfServices;
+use ModulesGarden\Servers\ZimbraEmail\App\Traits\FormExtendedTrait;
+use ModulesGarden\Servers\ZimbraEmail\App\UI\Admin\Custom\Forms\SortedFieldForm;
+use ModulesGarden\Servers\ZimbraEmail\App\UI\Admin\Custom\Sections\RowSection;
+use ModulesGarden\Servers\ZimbraEmail\App\UI\Client\Ressource\Providers\RessourceDataProvider;
+use ModulesGarden\Servers\ZimbraEmail\App\UI\Client\Ressource\Providers\EditRessourceDataProvider;
+use ModulesGarden\Servers\ZimbraEmail\App\UI\Client\Ressource\Sections\EditAdditionalSection;
+use ModulesGarden\Servers\ZimbraEmail\App\UI\Client\Ressource\Sections\EditGeneralSection;
+use ModulesGarden\Servers\ZimbraEmail\Core\UI\Interfaces\ClientArea;
+use ModulesGarden\Servers\ZimbraEmail\Core\UI\Widget\Forms\Fields\Hidden;
+use ModulesGarden\Servers\ZimbraEmail\Core\UI\Widget\Forms\Fields\Select;
+use ModulesGarden\Servers\ZimbraEmail\Core\UI\Widget\Forms\Fields\Text;
+use ModulesGarden\Servers\ZimbraEmail\Core\UI\Widget\Forms\FormConstants;
+use ModulesGarden\Servers\ZimbraEmail\Core\UI\Widget\Forms\Sections\HalfPageSection;
+use ModulesGarden\Servers\ZimbraEmail\Core\UI\Widget\Forms\Sections\InputGroup;
+use ModulesGarden\Servers\ZimbraEmail\Core\UI\Widget\Modals\BaseEditModal;
+use ModulesGarden\Servers\ZimbraEmail\Core\UI\Widget\Forms\Fields\InputGroupElements;
+
+/**
+ *
+ * Created by PhpStorm.
+ * User: Tomasz Bielecki ( tomasz.bi@modulesgarden.com )
+ * Date: 18.09.19
+ * Time: 09:29
+ * Class EditRessourceForm
+ */
+class EditRessourceForm extends SortedFieldForm implements ClientArea
+{
+    use FormExtendedTrait;
+
+    protected $id    = 'editRessourceForm';
+    protected $name  = 'editRessourceForm';
+    protected $title = 'editRessourceForm';
+
+    public function initContent()
+    {
+        $this->setFormType(FormConstants::UPDATE);
+        $this->setProvider(new EditRessourceDataProvider());
+        $this->initFields();
+        $this->loadDataToForm();
+    }
+
+    public function initFields()
+    {
+        $this->addSection(new EditGeneralSection());
+
+        $this->addSection(new EditAdditionalSection());
+    }
+}

+ 38 - 0
app/UI/Client/Ressource/Forms/MassChangeStatusForm.php

@@ -0,0 +1,38 @@
+<?php
+/**
+ * Class MassChangeStatusForm
+ * User: Nessandro
+ * Date: 2019-10-11
+ * Time: 12:26
+ * @package ModulesGarden\Servers\ZimbraEmail\App\UI\Client\Ressource\Forms
+ */
+
+namespace ModulesGarden\Servers\ZimbraEmail\App\UI\Client\Ressource\Forms;
+
+
+use ModulesGarden\Servers\ZimbraEmail\App\UI\Client\DistributionList\Providers\DeleteListDataProvider;
+use ModulesGarden\Servers\ZimbraEmail\App\UI\Client\Ressource\Providers\RessourceDataProvider;
+use ModulesGarden\Servers\ZimbraEmail\Core\UI\Interfaces\ClientArea;
+use ModulesGarden\Servers\ZimbraEmail\Core\UI\Widget\Forms\BaseForm;
+use ModulesGarden\Servers\ZimbraEmail\Core\UI\Widget\Forms\Fields\Hidden;
+use ModulesGarden\Servers\ZimbraEmail\Core\UI\Widget\Forms\Fields\Select;
+use ModulesGarden\Servers\ZimbraEmail\Core\UI\Widget\Forms\FormConstants;
+
+class MassChangeStatusForm extends BaseForm implements ClientArea
+{
+    protected $id    = 'massChangeStatusForm';
+    protected $name  = 'massChangeStatusForm';
+    protected $title = 'massChangeStatusForm';
+
+    public function initContent()
+    {
+        $this->setFormType(FormConstants::UPDATE);
+        $this->dataProvider = new RessourceDataProvider();
+
+        $field = new Select('status');
+        $this->addField($field);
+
+        $this->loadDataToForm();
+    }
+
+}

+ 42 - 0
app/UI/Client/Ressource/Forms/MassDeleteRessourceForm.php

@@ -0,0 +1,42 @@
+<?php
+/**
+ * Class MassDeleteRessourceForm
+ * User: Nessandro
+ * Date: 2019-10-11
+ * Time: 11:29
+ * @package ModulesGarden\Servers\ZimbraEmail\App\UI\Client\Ressource\Forms
+ */
+
+namespace ModulesGarden\Servers\ZimbraEmail\App\UI\Client\Ressource\Forms;
+
+
+use ModulesGarden\Servers\ZimbraEmail\App\UI\Client\DistributionList\Providers\DeleteListDataProvider;
+use ModulesGarden\Servers\ZimbraEmail\App\UI\Client\Ressource\Providers\DeleteRessourceDataProvider;
+use ModulesGarden\Servers\ZimbraEmail\Core\UI\Interfaces\ClientArea;
+use ModulesGarden\Servers\ZimbraEmail\Core\UI\Widget\Forms\BaseForm;
+use ModulesGarden\Servers\ZimbraEmail\Core\UI\Widget\Forms\Fields\Hidden;
+use ModulesGarden\Servers\ZimbraEmail\Core\UI\Widget\Forms\FormConstants;
+
+class MassDeleteRessourceForm extends BaseForm implements ClientArea
+{
+    protected $id    = 'massDeleteRessourceForm';
+    protected $name  = 'massDeleteRessourceForm';
+    protected $title = 'massDeleteRessourceForm';
+
+    protected function getDefaultActions()
+    {
+        return ['massDelete'];
+    }
+
+    public function initContent()
+    {
+        $this->setFormType('massDelete');
+        $this->dataProvider = new DeleteRessourceDataProvider();
+
+        $this->setConfirmMessage('massDeleteRessourceFormConfirm');
+
+
+        $this->loadDataToForm();
+    }
+
+}

+ 26 - 0
app/UI/Client/Ressource/Modals/AddRessourceModal.php

@@ -0,0 +1,26 @@
+<?php
+namespace ModulesGarden\Servers\ZimbraEmail\App\UI\Client\Ressource\Modals;
+use ModulesGarden\Servers\ZimbraEmail\App\UI\Admin\Custom\Modals\ModalExtendedTabsEdit;
+use ModulesGarden\Servers\ZimbraEmail\App\UI\Client\Ressource\Forms\AddRessourceForm;
+use ModulesGarden\Servers\ZimbraEmail\Core\UI\Interfaces\ClientArea;
+use ModulesGarden\Servers\ZimbraEmail\Core\UI\Widget\Modals\BaseEditModal;
+
+/**
+ *
+ * Created by PhpStorm.
+ * User: Tomasz Bielecki ( tomasz.bi@modulesgarden.com )
+ * Date: 10.09.19
+ * Time: 13:06
+ * Class AddRessourceModal
+ */
+class AddRessourceModal extends ModalExtendedTabsEdit implements ClientArea
+{
+    protected $id    = 'addRessourceModal';
+    protected $name  = 'addRessourceModal';
+    protected $title = 'addRessourceModal';
+
+    public function initContent()
+    {
+        $this->addForm(new AddRessourceForm());
+    }
+}

+ 29 - 0
app/UI/Client/Ressource/Modals/ChangePasswordModal.php

@@ -0,0 +1,29 @@
+<?php
+
+namespace ModulesGarden\Servers\ZimbraEmail\App\UI\Client\Ressource\Modals;
+
+
+use ModulesGarden\Servers\ZimbraEmail\App\UI\Client\Ressource\Forms\ChangePasswordForm;
+use ModulesGarden\Servers\ZimbraEmail\App\UI\Client\Ressource\Forms\EditRessourceForm;
+use ModulesGarden\Servers\ZimbraEmail\Core\UI\Interfaces\ClientArea;
+use ModulesGarden\Servers\ZimbraEmail\Core\UI\Widget\Modals\BaseEditModal;
+
+/**
+ *
+ * Created by PhpStorm.
+ * User: Tomasz Bielecki ( tomasz.bi@modulesgarden.com )
+ * Date: 08.11.19
+ * Time: 12:07
+ * Class ChangePasswordModal
+ */
+class ChangePasswordModal extends BaseEditModal implements ClientArea
+{
+    protected $id    = 'changePasswordModal';
+    protected $name  = 'changePasswordModal';
+    protected $title = 'changePasswordModal';
+
+    public function initContent()
+    {
+        $this->addForm(new ChangePasswordForm());
+    }
+}

+ 29 - 0
app/UI/Client/Ressource/Modals/ChangeStatusModal.php

@@ -0,0 +1,29 @@
+<?php
+/**
+ * Class ChangeStatusModal
+ * User: Nessandro
+ * Date: 2019-10-11
+ * Time: 11:29
+ * @package ModulesGarden\Servers\ZimbraEmail\App\UI\Client\Ressource\Modals
+ */
+
+namespace ModulesGarden\Servers\ZimbraEmail\App\UI\Client\Ressource\Modals;
+
+
+use ModulesGarden\Servers\ZimbraEmail\App\UI\Client\Ressource\Forms\ChangeStatusForm;
+use ModulesGarden\Servers\ZimbraEmail\App\UI\Client\Ressource\Forms\EditRessourceForm;
+use ModulesGarden\Servers\ZimbraEmail\Core\UI\Interfaces\ClientArea;
+use ModulesGarden\Servers\ZimbraEmail\Core\UI\Widget\Buttons\ButtonDataTableModalAction;
+use ModulesGarden\Servers\ZimbraEmail\Core\UI\Widget\Modals\BaseEditModal;
+
+class ChangeStatusModal extends BaseEditModal implements ClientArea
+{
+    protected $id    = 'changeStatusModal';
+    protected $name  = 'changeStatusModal';
+    protected $title = 'changeStatusModal';
+
+    public function initContent()
+    {
+        $this->addForm(new ChangeStatusForm());
+    }
+}

+ 34 - 0
app/UI/Client/Ressource/Modals/DeleteRessourceModal.php

@@ -0,0 +1,34 @@
+<?php
+
+namespace ModulesGarden\Servers\ZimbraEmail\App\UI\Client\Ressource\Modals;
+
+
+use ModulesGarden\Servers\ZimbraEmail\App\UI\Client\Ressource\Forms\DeleteRessourceForm;
+use ModulesGarden\Servers\ZimbraEmail\App\UI\Client\Ressource\Forms\EditRessourceForm;
+use ModulesGarden\Servers\ZimbraEmail\Core\UI\Interfaces\ClientArea;
+use ModulesGarden\Servers\ZimbraEmail\Core\UI\Widget\Modals\BaseModal;
+
+/**
+ *
+ * Created by PhpStorm.
+ * User: Tomasz Bielecki ( tomasz.bi@modulesgarden.com )
+ * Date: 18.09.19
+ * Time: 11:28
+ * Class DeleteRessourceModal
+ */
+class DeleteRessourceModal extends BaseModal implements ClientArea
+{
+
+    protected $id    = 'deleteRessourceModal';
+    protected $name  = 'deleteRessourceModal';
+    protected $title = 'deleteRessourceModal';
+
+    public function initContent()
+    {
+        $this->setSubmitButtonClassesDanger();
+        $this->setModalTitleTypeDanger();
+
+        $this->addForm(new DeleteRessourceForm());
+    }
+
+}

+ 30 - 0
app/UI/Client/Ressource/Modals/EditRessourceModal.php

@@ -0,0 +1,30 @@
+<?php
+
+namespace ModulesGarden\Servers\ZimbraEmail\App\UI\Client\Ressource\Modals;
+
+
+use ModulesGarden\Servers\ZimbraEmail\App\UI\Admin\Custom\Modals\ModalExtendedTabsEdit;
+use ModulesGarden\Servers\ZimbraEmail\App\UI\Client\Ressource\Forms\AddRessourceForm;
+use ModulesGarden\Servers\ZimbraEmail\App\UI\Client\Ressource\Forms\EditRessourceForm;
+use ModulesGarden\Servers\ZimbraEmail\Core\UI\Interfaces\ClientArea;
+use ModulesGarden\Servers\ZimbraEmail\Core\UI\Widget\Modals\BaseEditModal;
+
+/**
+ *
+ * Created by PhpStorm.
+ * User: Tomasz Bielecki ( tomasz.bi@modulesgarden.com )
+ * Date: 18.09.19
+ * Time: 09:30
+ * Class EditRessourceModal
+ */
+class EditRessourceModal extends ModalExtendedTabsEdit implements ClientArea
+{
+    protected $id    = 'editRessourceModal';
+    protected $name  = 'editRessourceModal';
+    protected $title = 'editRessourceModal';
+
+    public function initContent()
+    {
+        $this->addForm(new EditRessourceForm());
+    }
+}

+ 30 - 0
app/UI/Client/Ressource/Modals/MassChangeStatusModal.php

@@ -0,0 +1,30 @@
+<?php
+/**
+ * Class MassChangeStatusModal
+ * User: Nessandro
+ * Date: 2019-10-11
+ * Time: 11:30
+ * @package ModulesGarden\Servers\ZimbraEmail\App\UI\Client\Ressource\Modals
+ */
+
+namespace ModulesGarden\Servers\ZimbraEmail\App\UI\Client\Ressource\Modals;
+
+
+use ModulesGarden\Servers\ZimbraEmail\App\UI\Client\Ressource\Forms\MassChangeStatusForm;
+use ModulesGarden\Servers\ZimbraEmail\Core\UI\Interfaces\ClientArea;
+use ModulesGarden\Servers\ZimbraEmail\Core\UI\Widget\Modals\BaseEditModal;
+use ModulesGarden\Servers\ZimbraEmail\Core\UI\Widget\Modals\BaseModal;
+
+class MassChangeStatusModal extends BaseEditModal implements ClientArea
+{
+
+    protected $id    = 'massChangeStatusModal';
+    protected $name  = 'massChangeStatusModal';
+    protected $title = 'massChangeStatusModal';
+
+    public function initContent()
+    {
+        $this->addForm(new MassChangeStatusForm());
+    }
+
+}

+ 31 - 0
app/UI/Client/Ressource/Modals/MassDeleteRessourceModal.php

@@ -0,0 +1,31 @@
+<?php
+/**
+ * Class MassDeleteRessourceModal
+ * User: Nessandro
+ * Date: 2019-10-11
+ * Time: 11:29
+ * @package ModulesGarden\Servers\ZimbraEmail\App\UI\Client\Ressource\Modals
+ */
+
+namespace ModulesGarden\Servers\ZimbraEmail\App\UI\Client\Ressource\Modals;
+
+
+use ModulesGarden\Servers\ZimbraEmail\App\UI\Client\Ressource\Forms\MassDeleteRessourceForm;
+use ModulesGarden\Servers\ZimbraEmail\Core\UI\Interfaces\ClientArea;
+use ModulesGarden\Servers\ZimbraEmail\Core\UI\Widget\Modals\BaseModal;
+
+class MassDeleteRessourceModal extends BaseModal implements ClientArea
+{
+
+    protected $id    = 'massDeleteRessourceModal';
+    protected $name  = 'massDeleteRessourceModal';
+    protected $title = 'massDeleteRessourceModal';
+
+    public function initContent()
+    {
+        $this->setSubmitButtonClassesDanger();
+        $this->setModalTitleTypeDanger();
+        $this->addForm(new MassDeleteRessourceForm());
+    }
+
+}

+ 200 - 0
app/UI/Client/Ressource/Pages/Ressources.php

@@ -0,0 +1,200 @@
+<?php
+
+namespace ModulesGarden\Servers\ZimbraEmail\App\UI\Client\Ressource\Pages;
+
+use ModulesGarden\Servers\ZimbraEmail\App\Helpers\BuildUrlExtended;
+use ModulesGarden\Servers\ZimbraEmail\App\Helpers\ZimbraManager;
+use ModulesGarden\Servers\ZimbraEmail\App\Libs\Product\ProductManager;
+use ModulesGarden\Servers\ZimbraEmail\App\Libs\Zimbra\Components\Api\Soap\Connection;
+use ModulesGarden\Servers\ZimbraEmail\App\Libs\Zimbra\Components\Api\Soap\Helpers\RessourceHelper;
+use ModulesGarden\Servers\ZimbraEmail\App\Libs\Zimbra\Components\Api\Soap\Models\Ressource;
+use ModulesGarden\Servers\ZimbraEmail\App\Libs\Zimbra\Components\Api\Soap\Repository\ClassOfServices;
+use ModulesGarden\Servers\ZimbraEmail\App\Libs\Zimbra\Components\Filters\Ressources\FilterByCosId;
+use ModulesGarden\Servers\ZimbraEmail\App\UI\Admin\Custom\Fields\EnabledField;
+use ModulesGarden\Servers\ZimbraEmail\App\UI\Client\Ressource\Buttons\AddRessourceButton;
+use ModulesGarden\Servers\ZimbraEmail\App\UI\Client\Ressource\Buttons\ChangePasswordButton;
+use ModulesGarden\Servers\ZimbraEmail\App\UI\Client\Ressource\Buttons\ChangeStatusButton;
+use ModulesGarden\Servers\ZimbraEmail\App\UI\Client\Ressource\Buttons\DeleteRessourceButton;
+use ModulesGarden\Servers\ZimbraEmail\App\UI\Client\Ressource\Buttons\EditRessourceButton;
+use ModulesGarden\Servers\ZimbraEmail\App\UI\Client\Ressource\Buttons\LoginToPanelButton;
+use ModulesGarden\Servers\ZimbraEmail\App\UI\Client\Ressource\Buttons\MassChangeStatusButton;
+use ModulesGarden\Servers\ZimbraEmail\App\UI\Client\Ressource\Buttons\MassDeleteRessourceButton;
+use ModulesGarden\Servers\ZimbraEmail\App\UI\Client\Ressource\Buttons\SpanDropdownButton;
+use function ModulesGarden\Servers\ZimbraEmail\Core\Helper\di;
+use ModulesGarden\Servers\ZimbraEmail\Core\Models\Whmcs\Hosting;
+use ModulesGarden\Servers\ZimbraEmail\Core\UI\Widget\Buttons\DropdawnButtonWrappers\ButtonDropdown;
+use ModulesGarden\Servers\ZimbraEmail\Core\UI\Widget\DataTable\Column;
+use ModulesGarden\Servers\ZimbraEmail\Core\UI\Widget\DataTable\DataProviders\DataProvider;
+use ModulesGarden\Servers\ZimbraEmail\Core\UI\Interfaces\ClientArea;
+use ModulesGarden\Servers\ZimbraEmail\Core\UI\Widget\DataTable\DataProviders\Providers\ArrayDataProvider;
+use ModulesGarden\Servers\ZimbraEmail\Core\UI\Widget\DataTable\DataTable;
+
+/**
+ *
+ * Created by PhpStorm.
+ * User: Tomasz Bielecki ( tomasz.bi@modulesgarden.com )
+ * Date: 10.09.19
+ * Time: 10:51
+ * Class Ressources
+ */
+class Ressources extends DataTable implements ClientArea
+{
+
+    /**
+     * labels for statuses
+     */
+    const STATUS_LABEL = [
+        'active'        => 'success',
+        'locked'        => 'default',
+        'maintenance'   => 'warning',
+        'closed'        => 'default',
+        'lockout'       => 'info',
+        'pending'       => 'warning',
+        'default'       => 'default'
+    ];
+
+    protected $id    = 'ressources';
+    protected $name  = 'ressources';
+    protected $title = null;
+
+    /**
+     * load columns
+     */
+    protected function loadHtml()
+    {
+        $this
+            ->addColumn((new Column('ressource'))
+                ->setOrderable(DataProvider::SORT_ASC)
+                ->setSearchable(true, Column::TYPE_STRING))
+            ->addColumn((new Column('date_created'))
+                ->setOrderable()
+                ->setSearchable(true))
+            ->addColumn((new Column('capacity'))
+                ->setOrderable()
+                ->setSearchable(true))
+            ->addColumn((new Column('type'))
+                ->setOrderable()
+                ->setSearchable(true, Column::TYPE_INT))
+            ->addColumn((new Column('status'))
+                ->setOrderable()
+                ->setSearchable(true));
+    }
+
+    /**
+     * @param $key
+     * @param $row
+     * @return mixed
+     */
+    public function replaceFieldStatus($key, $row)
+    {
+        $status = self::STATUS_LABEL[$row[$key]] ? self::STATUS_LABEL[$row[$key]] : self::STATUS_LABEL['default'];
+        $label = di('lang')->absoluteT('zimbra','account','status',$row[$key]);
+
+        $field = new EnabledField();
+        $field->setRawType($status);
+        $field->setRawTitle($label);
+
+        return $field->getHtml();
+    }
+
+    /**
+     * @param $key
+     * @param $row
+     * @return mixed
+     */
+    public function replaceFieldLast_login($key, $row)
+    {
+        return $row[$key] ? $row[$key] : '-';
+    }
+
+    /**
+     * @param $key
+     * @param $row
+     * @return mixed
+     */
+    public function replaceFieldType($key, $row)
+    {
+        return $row[$key] == 'Location' ? di('lang')->absoluteT('zimbra','ressource','type','location') : di('lang')->absoluteT('zimbra','ressource','type','equipment');
+    }
+
+    /**
+     * load buttons
+     */
+    public function initContent()
+    {
+        $productManager = new ProductManager();
+        $productManager->loadByHostingId($this->getRequestValue('id'));
+
+        $this->addMassActionButton(new MassChangeStatusButton());
+        $this->addMassActionButton(new MassDeleteRessourceButton());
+
+        $this->addButton(new AddRessourceButton());
+
+
+        $this->addActionButton(new EditRessourceButton());
+        $this->addActionButton(new DeleteRessourceButton());
+
+        $mailBox = new LoginToPanelButton();
+        $mailBox
+            ->setRawUrl(BuildUrlExtended::getProvisioningUrl('webmail', true, true,'clientSso'))
+            ->setRedirectParams(['actionElementId' => 'true']);
+
+        $actions = new SpanDropdownButton('actions');
+        $actions->addButton(new ChangeStatusButton());
+        $actions->addButton(new ChangePasswordButton());
+
+        if ($productManager->get('ca_logInToMailboxButton') === 'on')
+        {
+            $actions->addButton($mailBox);
+        }
+
+        $this->addActionButton($actions);
+
+    }
+
+    /**
+     * load data
+     */
+    public function loadData()
+    {
+        /**
+         * load hosting
+         */
+        $hosting = Hosting::where('id', $this->getRequestValue('id'))->first();
+
+
+        $ressources = (new ZimbraManager())
+            ->getApiByServer($hosting->server)
+            ->soap
+            ->repository()
+            ->ressources
+            ->getByDomainName($hosting->domain);
+
+        /**
+         * format model to array
+         */
+        $data = [];
+        foreach ($ressources as $ressource)
+        {
+            /* @var $account Ressource */
+
+            $ressourceArray = [
+                'id'           => $ressource->getId(),
+                'ressource'    => $ressource->getDataResourceA('displayName'),
+                'date_created' => RessourceHelper::getFormattedData($ressource->getDataResourceA('zimbraCreateTimestamp')),
+//                'last_login'   => RessourceHelper::getFormattedData($ressource->getDataResourceA('zimbraLastLogonTimestamp'), 'd/m/Y H:i'),
+                'capacity'     => $ressource->getDataResourceA('zimbraCalResCapacity'),
+                'type'         => $ressource->getDataResourceA('zimbraCalResType'),
+                'status'       => $ressource->getDataResourceA('zimbraAccountStatus')
+            ];
+
+            $data[] = $ressourceArray;
+        }
+
+        $dataProv = new ArrayDataProvider();
+        $dataProv->setDefaultSorting('ressource', 'ASC')->setData($data);
+
+        $this->setDataProvider($dataProv);
+    }
+
+}

+ 116 - 0
app/UI/Client/Ressource/Providers/DeleteRessourceDataProvider.php

@@ -0,0 +1,116 @@
+<?php
+
+namespace ModulesGarden\Servers\ZimbraEmail\App\UI\Client\Ressource\Providers;
+
+
+use ModulesGarden\Servers\ZimbraEmail\App\Helpers\ZimbraManager;
+use ModulesGarden\Servers\ZimbraEmail\App\Libs\Product\ProductManager;
+use ModulesGarden\Servers\ZimbraEmail\App\Libs\Zimbra\Components\Api\Soap\Services\Delete\DeleteRessource;
+use ModulesGarden\Servers\ZimbraEmail\Core\UI\ResponseTemplates\HtmlDataJsonResponse;
+use ModulesGarden\Servers\ZimbraEmail\Core\UI\Widget\Forms\DataProviders\BaseDataProvider;
+
+/**
+ *
+ * Created by PhpStorm.
+ * User: Tomasz Bielecki ( tomasz.bi@modulesgarden.com )
+ * Date: 18.09.19
+ * Time: 11:28
+ * Class DeleteRessourceDataProvider
+ */
+class DeleteRessourceDataProvider extends BaseDataProvider
+{
+
+    public function read()
+    {
+        $this->data['id'] = $this->actionElementId;
+    }
+
+    public function update()
+    {
+        // TODO: Implement update() method.
+    }
+
+    public function delete()
+    {
+
+        /**
+         * hosting id
+         */
+        $hid = $this->request->get('id');
+
+        /**
+         * product manager allow to check product settings
+         */
+        $productManager = new ProductManager();
+        $productManager->loadByHostingId($hid);
+
+        /**
+         *
+         * get soap create domain  service
+         */
+        $service =(new ZimbraManager())
+            ->getApiByHosting($hid)
+            ->soap
+            ->service()
+            ->deleteRessource();
+        /**
+         *
+         * set product manager & form data to service
+         */
+        $service
+            ->setFormData($this->formData);
+
+        /**
+         *
+         * run service
+         */
+        $result = $service->run();
+
+        /**
+         *
+         * return success or error response
+         */
+        if(!$result)
+        {
+            return (new HtmlDataJsonResponse())->setMessageAndTranslate($service->getError())->setStatusError();
+        }
+
+        return (new HtmlDataJsonResponse())->setMessageAndTranslate('ressourceHasBeenDeleted')->setStatusSuccess();
+
+    }
+
+    public function massDelete()
+    {
+        /**
+         * hosting id
+         */
+        $hid = $this->request->get('id');
+
+        /**
+         * product manager allow to check product settings
+         */
+        $productManager = new ProductManager();
+        $productManager->loadByHostingId($hid);
+
+        /**
+         *
+         * get soap create domain  service
+         */
+        $service =(new ZimbraManager())
+            ->getApiByHosting($hid)
+            ->soap
+            ->service()
+            ->deleteRessource();
+
+        /**
+         *
+         */
+        foreach($this->request->get('massActions') as $id)
+        {
+            $service->setFormData(['id' => $id]);
+            $result = $service->run();
+        }
+
+        return (new HtmlDataJsonResponse())->setMessageAndTranslate('massRessourceHasBeenDeleted')->setStatusSuccess();
+    }
+}

+ 274 - 0
app/UI/Client/Ressource/Providers/EditRessourceDataProvider.php

@@ -0,0 +1,274 @@
+<?php
+
+namespace ModulesGarden\Servers\ZimbraEmail\App\UI\Client\Ressource\Providers;
+
+
+use ModulesGarden\Servers\ZimbraEmail\App\Enums\Zimbra;
+use ModulesGarden\Servers\ZimbraEmail\App\Helpers\ZimbraManager;
+use ModulesGarden\Servers\ZimbraEmail\App\Libs\Product\ProductManager;
+use ModulesGarden\Servers\ZimbraEmail\App\Libs\Zimbra\Components\Api\Soap\Models\Ressource;
+use ModulesGarden\Servers\ZimbraEmail\App\Libs\Zimbra\Components\Api\Soap\Models\ClassOfService;
+use ModulesGarden\Servers\ZimbraEmail\App\Libs\Zimbra\Components\Api\Soap\Repository;
+use ModulesGarden\Servers\ZimbraEmail\App\Libs\Zimbra\Components\Api\Soap\Repository\ClassOfServices;
+use ModulesGarden\Servers\ZimbraEmail\App\Libs\Zimbra\Components\Api\Soap\Response;
+use ModulesGarden\Servers\ZimbraEmail\App\Libs\Zimbra\Components\Api\Soap\Services\Update\UpdateRessource;
+use ModulesGarden\Servers\ZimbraEmail\App\Services\ConfigurableOptions\Strategy\Types\ClassOfServicesOptions;
+use function ModulesGarden\Servers\ZimbraEmail\Core\Helper\di;
+use ModulesGarden\Servers\ZimbraEmail\Core\Models\Whmcs\Hosting;
+use ModulesGarden\Servers\ZimbraEmail\Core\UI\ResponseTemplates\HtmlDataJsonResponse;
+use ModulesGarden\Servers\ZimbraEmail\Core\UI\Widget\Forms\DataProviders\BaseDataProvider;
+
+/**
+ *
+ * Created by PhpStorm.
+ * User: Tomasz Bielecki ( tomasz.bi@modulesgarden.com )
+ * Date: 18.09.19
+ * Time: 09:35
+ * Class EditRessourceDataProvider
+ */
+class EditRessourceDataProvider extends BaseDataProvider
+{
+
+    /**
+     *
+     */
+    public function read()
+    {
+        /**
+         * hosting id
+         */
+        $hid = $this->getRequestValue('id');
+        /**
+         * load hosting
+         */
+        $hosting = Hosting::where('id', $hid)->first();
+
+        /**
+         * load api
+         */
+        $api = (new ZimbraManager())->getApiByServer($hosting->server);
+
+        $repository = new Repository($api->soap);
+
+        $result = $repository->ressources->getRessourceOptionsById($this->actionElementId);
+
+        if($result instanceof Response && $result->getLastError())
+        {
+            throw new \Exception($result->getLastError());
+        }
+
+        $mailBoxParams               = explode('@', $result->getName());
+        $this->data['id']            = $result->getId();
+        $this->data['username']      = $mailBoxParams[0];
+        $this->data['domain']        = $mailBoxParams[1];
+        $this->data['status']        = $result->getDataResourceA(Ressource::ATTR_STATUS);
+        $this->data['type']          = $result->getDataResourceA(Ressource::ATTR_TYPE);
+        $this->data['display_name']  = $result->getDataResourceA(Ressource::ATTR_DISPLAY_NAME);
+        $this->data['description']   = $result->getDataResourceA(Ressource::ATTR_DESC);
+        $this->data['capacity']      = $result->getDataResourceA(Ressource::ATTR_CAPACITY);
+        $this->data['notes']         = $result->getDataResourceA(Ressource::ATTR_NOTE);
+        $this->data['contact']       = $result->getDataResourceA(Ressource::ATTR_CONT);
+        $this->data['site']          = $result->getDataResourceA(Ressource::ATTR_SITE);
+        $this->data['contact_mail']  = $result->getDataResourceA(Ressource::ATTR_CONT_EMAIL);
+        $this->data['contact_phone'] = $result->getDataResourceA(Ressource::ATTR_CONT_PHONE);
+        $this->data['street']        = $result->getDataResourceA(Ressource::ATTR_STREET);
+        $this->data['building']      = $result->getDataResourceA(Ressource::ATTR_BUILDING);
+        $this->data['floor']         = $result->getDataResourceA(Ressource::ATTR_FLOOR);
+        $this->data['room']          = $result->getDataResourceA(Ressource::ATTR_ROOM);
+        $this->data['post_code']     = $result->getDataResourceA(Ressource::ATTR_POSTAL_CODE);
+        $this->data['town']          = $result->getDataResourceA(Ressource::ATTR_TOWN);
+        $this->data['state']         = $result->getDataResourceA(Ressource::ATTR_STATE);
+        $this->data['county']        = $result->getDataResourceA(Ressource::ATTR_COUNTY);
+        $this->data['auto_accept']   = $result->getDataResourceA(Ressource::ATTR_AUTO) == 'TRUE' ? 'on' : 'off';
+        $this->data['auto_busy']     = $result->getDataResourceA(Ressource::ATTR_BUSY) == 'TRUE' ? 'on' : 'off';
+
+        $lang = di('lang');
+        $this->availableValues['status'] = [
+            Zimbra::ACC_STATUS_ACTIVE        => $lang->absoluteT('zimbra','account','status','active'),
+            Zimbra::ACC_STATUS_LOCKED        => $lang->absoluteT('zimbra','account','status','locked'),
+            Zimbra::ACC_STATUS_MAINTENANCE   => $lang->absoluteT('zimbra','account','status','maintenance'),
+            Zimbra::ACC_STATUS_CLOSED        => $lang->absoluteT('zimbra','account','status','closed'),
+            Zimbra::ACC_STATUS_LOCKOUT       => $lang->absoluteT('zimbra','account','status','lockout'),
+            Zimbra::ACC_STATUS_PENDING       => $lang->absoluteT('zimbra','account','status','pending')
+        ];
+
+        $this->availableValues['type'] = [
+            Zimbra::RES_TYPE_LOCATION        => $lang->absoluteT('zimbra','ressource','type','location'),
+            Zimbra::RES_TYPE_EQUIPMENT       => $lang->absoluteT('zimbra','ressource','type','equipment')
+        ];
+
+    }
+
+    /**
+     * @return HtmlDataJsonResponse
+     */
+    public function update()
+    {
+        /**
+         * hosting id
+         */
+        $hid = $this->request->get('id');
+
+        $fieldToProtection = [
+            'display_name',
+            'status',
+            'type',
+            'capacity',
+            'description',
+            'notes',
+            'contact',
+            'site',
+            'contact_mail',
+            'contact_phone',
+            'street',
+            'building',
+            'floor',
+            'room',
+            'post_code',
+            'town',
+            'state',
+            'county',
+            'auto_accept',
+            'auto_busy'
+        ];
+
+        foreach ($this->formData as $field => &$value)
+        {
+            $value = in_array($field, $fieldToProtection) ? htmlentities($value) : $value;
+        }
+
+        /**
+         * product manager allow to check product settings
+         */
+        $productManager = new ProductManager();
+        $productManager->loadByHostingId($hid);
+
+        /**
+         *
+         * get soap create domain  service
+         */
+        $service =(new ZimbraManager())
+            ->getApiByHosting($hid)
+            ->soap
+            ->service()
+            ->updateRessource();
+        /**
+         *
+         * set product manager & form data to service
+         */
+        $service
+            ->setProductManager($productManager)
+            ->setFormData($this->formData);
+
+        /**
+         * run service
+         */
+        $result = $service->run();
+
+        /**
+         * return success or error response
+         */
+        if(!$result)
+        {
+            return (new HtmlDataJsonResponse())->setMessageAndTranslate($service->getError())->setStatusError();
+        }
+
+        return (new HtmlDataJsonResponse())->setMessageAndTranslate('ressourceHasBeenUpdated')->setStatusSuccess();
+    }
+
+    /**
+     * @return HtmlDataJsonResponse
+     */
+    public function updateStatus()
+    {
+        /**
+         * hosting id
+         */
+        $hid = $this->request->get('id');
+
+        /**
+         * product manager allow to check product settings
+         */
+        $productManager = new ProductManager();
+        $productManager->loadByHostingId($hid);
+
+        /**
+         *
+         * get soap create domain  service
+         */
+        $service =(new ZimbraManager())
+            ->getApiByHosting($hid)
+            ->soap
+            ->service()
+            ->updateRessourceStatus()
+            ->setProductManager($productManager)
+        ;
+        /**
+         *
+         * set product manager & form data to service
+         */
+
+        /**
+         * run service for each id
+         */
+        $service->setFormData($this->formData);
+        $result = $service->run();
+
+        if(!$result)
+        {
+            return (new HtmlDataJsonResponse())->setMessageAndTranslate($service->getError())->setStatusError();
+        }
+
+        /**
+         * return success
+         */
+        return (new HtmlDataJsonResponse())->setMessageAndTranslate('ressourceStatusHasBeenUpdated')->setStatusSuccess();
+
+    }
+
+    /**
+     * @return HtmlDataJsonResponse
+     */
+    public function changePassword()
+    {
+        /**
+         * hosting id
+         */
+        $hid = $this->request->get('id');
+
+        /**
+         * product manager allow to check product settings
+         */
+        $productManager = new ProductManager();
+        $productManager->loadByHostingId($hid);
+
+        /**
+         *
+         * get soap create domain  service
+         */
+        $service =(new ZimbraManager())
+            ->getApiByHosting($hid)
+            ->soap
+            ->service()
+            ->updateRessourcePassword()
+            ->setProductManager($productManager)
+        ;
+        /**
+         *
+         * set product manager & form data to service
+         */
+
+        /**
+         * run service for each id
+         */
+        $service->setFormData($this->formData);
+        $result = $service->run();
+
+        if(!$result)
+        {
+            return (new HtmlDataJsonResponse())->setMessageAndTranslate($service->getError())->setStatusError();
+        }
+
+        return (new HtmlDataJsonResponse())->setMessageAndTranslate('passwordChangedSuccessfully')->setStatusSuccess();
+    }
+}

+ 185 - 0
app/UI/Client/Ressource/Providers/RessourceDataProvider.php

@@ -0,0 +1,185 @@
+<?php
+namespace ModulesGarden\Servers\ZimbraEmail\App\UI\Client\Ressource\Providers;
+use ModulesGarden\Servers\ZimbraEmail\App\Enums\ProductParams;
+use ModulesGarden\Servers\ZimbraEmail\App\Enums\Size;
+use ModulesGarden\Servers\ZimbraEmail\App\Enums\Zimbra;
+use ModulesGarden\Servers\ZimbraEmail\App\Helpers\ZimbraManager;
+use ModulesGarden\Servers\ZimbraEmail\App\Http\Admin\ProductConfiguration;
+use ModulesGarden\Servers\ZimbraEmail\App\Libs\Product\ProductManager;
+use ModulesGarden\Servers\ZimbraEmail\App\Libs\Zimbra\Components\Api\Soap\Helpers\ServiceFactory;
+use ModulesGarden\Servers\ZimbraEmail\App\Libs\Zimbra\Components\Api\Soap\Models\Ressource;
+use ModulesGarden\Servers\ZimbraEmail\App\Libs\Zimbra\Components\Api\Soap\Models\ClassOfService;
+use ModulesGarden\Servers\ZimbraEmail\App\Libs\Zimbra\Components\Api\Soap\Repository\ClassOfServices;
+use ModulesGarden\Servers\ZimbraEmail\App\Services\ConfigurableOptions\Strategy\Types\ClassOfServicesOptions;
+use function ModulesGarden\Servers\ZimbraEmail\Core\Helper\di;
+use ModulesGarden\Servers\ZimbraEmail\Core\Http\JsonResponse;
+use ModulesGarden\Servers\ZimbraEmail\Core\Models\Whmcs\Hosting;
+use ModulesGarden\Servers\ZimbraEmail\Core\UI\ResponseTemplates\HtmlDataJsonResponse;
+use ModulesGarden\Servers\ZimbraEmail\Core\UI\Widget\Forms\DataProviders\BaseDataProvider;
+
+/**
+ *
+ * Created by PhpStorm.
+ * User: Tomasz Bielecki ( tomasz.bi@modulesgarden.com )
+ * Date: 10.09.19
+ * Time: 13:06
+ * Class RessourceDataProvider
+ */
+class RessourceDataProvider extends BaseDataProvider
+{
+
+    public function read()
+    {
+        /**
+         * hosting id
+         */
+        $hid = $this->request->get('id');
+
+        $hosting = Hosting::where('id', $hid)->first();
+        //todo refactor
+        $this->data['domain'] = $hosting->domain;
+
+        $lang = di('lang');
+        $this->availableValues['status'] = [
+            Zimbra::ACC_STATUS_ACTIVE        => $lang->absoluteT('zimbra','account','status','active'),
+            Zimbra::ACC_STATUS_LOCKED        => $lang->absoluteT('zimbra','account','status','locked'),
+            Zimbra::ACC_STATUS_MAINTENANCE   => $lang->absoluteT('zimbra','account','status','maintenance'),
+            Zimbra::ACC_STATUS_CLOSED        => $lang->absoluteT('zimbra','account','status','closed'),
+            Zimbra::ACC_STATUS_LOCKOUT       => $lang->absoluteT('zimbra','account','status','lockout'),
+            Zimbra::ACC_STATUS_PENDING       => $lang->absoluteT('zimbra','account','status','pending')
+        ];
+
+        $this->availableValues['type'] = [
+            Zimbra::RES_TYPE_LOCATION        => $lang->absoluteT('zimbra','ressource','type','location'),
+            Zimbra::RES_TYPE_EQUIPMENT       => $lang->absoluteT('zimbra','ressource','type','equipment')
+        ];
+
+    }
+
+    public function create()
+    {
+        /**
+         * hosting id
+         */
+        $hid = $this->request->get('id');
+
+        $fieldToProtection = [
+            'display_name',
+            'status',
+            'type',
+            'capacity',
+            'description',
+            'notes',
+            'contact',
+            'site',
+            'contact_mail',
+            'contact_phone',
+            'street',
+            'building',
+            'floor',
+            'room',
+            'post_code',
+            'town',
+            'state',
+            'county',
+            'auto_accept',
+            'auto_busy'
+        ];
+
+        foreach ($this->formData as $field => &$value)
+        {
+            $value = in_array($field, $fieldToProtection) ? htmlentities($value) : $value;
+        }
+
+        /**
+         * product manager allow to check product settings
+         */
+        $productManager = new ProductManager();
+        $productManager->loadByHostingId($hid);
+
+        /**
+         *
+         * get soap create domain  service
+         */
+        $service =(new ZimbraManager())
+            ->getApiByHosting($hid)
+            ->soap
+            ->service()
+            ->createRessource();
+        /**
+         *
+         * set product manager & form data to service
+         */
+        $service
+            ->setProductManager($productManager)
+            ->setFormData($this->formData);
+
+        /**
+         *
+         * run service
+         */
+        $result = $service->run();
+
+        /**
+         *
+         * return success or error response
+         */
+        if(!$result)
+        {
+            return (new HtmlDataJsonResponse())->setMessageAndTranslate($service->getError())->setStatusError();
+        }
+
+        return (new HtmlDataJsonResponse())->setMessageAndTranslate('ressourceHasBeenAdded')->setStatusSuccess();
+
+    }
+
+    public function updateStatus()
+    {
+
+
+    }
+
+    public function update()
+    {
+        /**
+         * hosting id
+         */
+        $hid = $this->request->get('id');
+
+        /**
+         * product manager allow to check product settings
+         */
+        $productManager = new ProductManager();
+        $productManager->loadByHostingId($hid);
+
+        /**
+         *
+         * get soap create domain  service
+         */
+        $service =(new ZimbraManager())
+            ->getApiByHosting($hid)
+            ->soap
+            ->service()
+            ->updateRessourceStatus()
+            ->setProductManager($productManager)
+        ;
+        /**
+         *
+         * set product manager & form data to service
+         */
+
+        /**
+         * run service for each id
+         */
+        foreach($this->request->get('massActions') as $id)
+        {
+            $service->setFormData(['status' => $this->formData['status'], 'id' => $id]);
+            $result = $service->run();
+        }
+
+        /**
+         * return success
+         */
+        return (new HtmlDataJsonResponse())->setMessageAndTranslate('massRessourceStatusHasBeenUpdated')->setStatusSuccess();
+    }
+}

+ 43 - 0
app/UI/Client/Ressource/Sections/AdditionalSection.php

@@ -0,0 +1,43 @@
+<?php
+
+namespace ModulesGarden\Servers\ZimbraEmail\App\UI\Client\Ressource\Sections;
+
+
+use ModulesGarden\Servers\ZimbraEmail\App\Traits\FormExtendedTrait;
+use ModulesGarden\Servers\ZimbraEmail\App\UI\Admin\Custom\Sections\FreeFieldsSection;
+use function ModulesGarden\Servers\ZimbraEmail\Core\Helper\di;
+use ModulesGarden\Servers\ZimbraEmail\Core\UI\Widget\Forms\Fields\Text;
+use ModulesGarden\Servers\ZimbraEmail\Core\UI\Widget\Forms\Sections\InputGroup;
+use ModulesGarden\Servers\ZimbraEmail\Core\UI\Widget\Forms\Fields\InputGroupElements;
+
+/**
+ *
+ * Created by PhpStorm.
+ * User: Tomasz Bielecki ( tomasz.bi@modulesgarden.com )
+ * Date: 12.11.19
+ * Time: 13:42
+ * Class AdditionalSection
+ */
+class AdditionalSection extends FreeFieldsSection
+{
+    protected $id   = 'additionalSection';
+    protected $name = 'additionalSection';
+
+    use FormExtendedTrait;
+
+    public function initContent()
+    {
+        $this->generateDoubleSection([new Text('contact'), new Text('site')]);
+
+        $this->generateDoubleSection([new Text('contact_mail'), new Text('contact_phone')]);
+
+        $this->generateDoubleSection([new Text('street'), new Text('building')]);
+
+        $this->generateDoubleSection([new Text('floor'), new Text('room')]);
+
+        $this->generateDoubleSection([new Text('post_code'), new Text('town')]);
+
+        $this->generateDoubleSection([new Text('state'), new Text('county')]);
+
+    }
+}

+ 41 - 0
app/UI/Client/Ressource/Sections/EditAdditionalSection.php

@@ -0,0 +1,41 @@
+<?php
+
+namespace ModulesGarden\Servers\ZimbraEmail\App\UI\Client\Ressource\Sections;
+
+
+use ModulesGarden\Servers\ZimbraEmail\App\Traits\FormExtendedTrait;
+use ModulesGarden\Servers\ZimbraEmail\App\UI\Admin\Custom\Sections\FreeFieldsSection;
+use ModulesGarden\Servers\ZimbraEmail\Core\UI\Widget\Forms\Fields\Text;
+
+/**
+ *
+ * Created by PhpStorm.
+ * User: Tomasz Bielecki ( tomasz.bi@modulesgarden.com )
+ * Date: 12.11.19
+ * Time: 13:52
+ * Class EditAdditionalSection
+ */
+class EditAdditionalSection extends FreeFieldsSection
+{
+    protected $id   = 'editAdditionalSection';
+    protected $name = 'editAdditionalSection';
+
+    use FormExtendedTrait;
+
+    public function initContent()
+    {
+        $this->generateDoubleSection([new Text('contact'), new Text('site')]);
+
+        $this->generateDoubleSection([new Text('contact_mail'), new Text('contact_phone')]);
+
+        $this->generateDoubleSection([new Text('street'), new Text('building')]);
+
+        $this->generateDoubleSection([new Text('floor'), new Text('room')]);
+
+        $this->generateDoubleSection([new Text('post_code'), new Text('town')]);
+
+        $this->generateDoubleSection([new Text('state'), new Text('county')]);
+
+    }
+
+}

+ 76 - 0
app/UI/Client/Ressource/Sections/EditGeneralSection.php

@@ -0,0 +1,76 @@
+<?php
+
+namespace ModulesGarden\Servers\ZimbraEmail\App\UI\Client\Ressource\Sections;
+
+
+use ModulesGarden\Servers\ZimbraEmail\App\Libs\Product\ProductManager;
+use ModulesGarden\Servers\ZimbraEmail\App\Libs\Zimbra\Components\Api\Soap\Repository\ClassOfServices;
+use ModulesGarden\Servers\ZimbraEmail\App\Traits\FormExtendedTrait;
+use ModulesGarden\Servers\ZimbraEmail\App\UI\Admin\Custom\Sections\FreeFieldsSection;
+use ModulesGarden\Servers\ZimbraEmail\Core\UI\Widget\Forms\Fields\Hidden;
+use ModulesGarden\Servers\ZimbraEmail\Core\UI\Widget\Forms\Fields\Select;
+use ModulesGarden\Servers\ZimbraEmail\Core\UI\Widget\Forms\Fields\Text;
+use ModulesGarden\Servers\ZimbraEmail\Core\UI\Widget\Forms\Fields\Switcher;
+use ModulesGarden\Servers\ZimbraEmail\Core\UI\Widget\Forms\Sections\InputGroup;
+use ModulesGarden\Servers\ZimbraEmail\Core\UI\Widget\Forms\Fields\InputGroupElements;
+
+/**
+ *
+ * Created by PhpStorm.
+ * User: Tomasz Bielecki ( tomasz.bi@modulesgarden.com )
+ * Date: 12.11.19
+ * Time: 13:52
+ * Class EditGeneralSection
+ */
+class EditGeneralSection extends FreeFieldsSection
+{
+    protected $id   = 'editGeneralSection';
+    protected $name = 'editGeneralSection';
+
+    use FormExtendedTrait;
+
+    public function initContent()
+    {
+        /**
+         * hosting id
+         */
+        $hid = $this->getRequestValue('id');
+
+        /**
+         * product manager allow to check product settings
+         */
+        $productManager = new ProductManager();
+        $productManager->loadByHostingId($hid);
+
+        /**
+         * add fields
+         */
+        $field = new Hidden('id');
+        $this->addField($field);
+
+        $email =new InputGroup('usernameGroup');
+
+        $email->addInputComponent((new InputGroupElements\Text('username'))->addHtmlAttribute('readonly','true'));
+        $email->addInputAddon('emailSign', false, '@');
+        $email->addInputComponent((new InputGroupElements\Text('domain'))->addHtmlAttribute('readonly','true'));
+        $this->addSection($email);
+
+        $this->generateDoubleSection([new Text('display_name'), new Select('status')]);
+
+        $type = new Select('type');
+        $capacity = new Text('capacity');
+
+        $this->generateDoubleSection([$type, $capacity]);
+
+        $field = new Text('description');
+        $this->addField($field);
+
+        $field = new Text('notes');
+        $this->addField($field);
+
+        $autoAcceptDecline = new Switcher('auto_accept');
+        $autoDeclineBusy = new Switcher('auto_busy');
+        $this->generateDoubleSection([$autoAcceptDecline, $autoDeclineBusy]);
+
+    }
+}

+ 81 - 0
app/UI/Client/Ressource/Sections/GeneralSection.php

@@ -0,0 +1,81 @@
+<?php
+namespace ModulesGarden\Servers\ZimbraEmail\App\UI\Client\Ressource\Sections;
+use ModulesGarden\Servers\ZimbraEmail\App\Libs\Product\ProductManager;
+use ModulesGarden\Servers\ZimbraEmail\App\Libs\Zimbra\Components\Api\Soap\Repository\ClassOfServices;
+use ModulesGarden\Servers\ZimbraEmail\App\Traits\FormExtendedTrait;
+use ModulesGarden\Servers\ZimbraEmail\App\UI\Admin\Custom\Sections\FreeFieldsSection;
+use ModulesGarden\Servers\ZimbraEmail\App\Validators\PasswordsValidator;
+use ModulesGarden\Servers\ZimbraEmail\App\Validators\RepeatPasswordValidator;
+use ModulesGarden\Servers\ZimbraEmail\Core\UI\Widget\Forms\Fields\Hidden;
+use ModulesGarden\Servers\ZimbraEmail\Core\UI\Widget\Forms\Fields\Password;
+use ModulesGarden\Servers\ZimbraEmail\Core\UI\Widget\Forms\Fields\Select;
+use ModulesGarden\Servers\ZimbraEmail\Core\UI\Widget\Forms\Fields\Text;
+use ModulesGarden\Servers\ZimbraEmail\Core\UI\Widget\Forms\Fields\Switcher;
+use ModulesGarden\Servers\ZimbraEmail\Core\UI\Widget\Forms\Fields\Number;
+use ModulesGarden\Servers\ZimbraEmail\Core\UI\Widget\Forms\Sections\InputGroup;
+use ModulesGarden\Servers\ZimbraEmail\Core\UI\Widget\Forms\Fields\InputGroupElements;
+
+/**
+ *
+ * Created by PhpStorm.
+ * User: Tomasz Bielecki ( tomasz.bi@modulesgarden.com )
+ * Date: 12.11.19
+ * Time: 13:39
+ * Class GeneralSection
+ */
+class GeneralSection extends FreeFieldsSection
+{
+    protected $id   = 'generalSection';
+    protected $name = 'generalSection';
+
+    use FormExtendedTrait;
+
+    public function initContent()
+    {
+        /**
+         * hosting id
+         */
+        $hid = $this->getRequestValue('id');
+
+        /**
+         * product manager allow to check product settings
+         */
+        $productManager = new ProductManager();
+        $productManager->loadByHostingId($hid);
+
+        $email = new InputGroup('usernameGroup');
+
+        $email->addTextField('username', false, true);
+        $email->addInputAddon('emailSign', false, '@');
+        $email->addInputComponent((new InputGroupElements\Text('domain'))->addHtmlAttribute('readonly','true'));
+        $this->addSection($email);
+
+        $this->generateDoubleSection([new Text('display_name'), new Select('status')]);
+
+        $passwd = new Password('password');
+        $passwd->setDescription('description');
+        $passwd->addValidator(new PasswordsValidator());
+        $passwd->notEmpty();
+
+        $repPasswd = (new Password('repeat_password'))->addValidator(new RepeatPasswordValidator());
+        $repPasswd->notEmpty();
+
+        $this->generateDoubleSection([$passwd, $repPasswd]);
+
+        $type = new Select('type');
+        $capacity = new Text('capacity');
+
+        $this->generateDoubleSection([$type, $capacity]);
+
+        $field = new Text('description');
+        $this->addField($field);
+
+        $field = new Text('notes');
+        $this->addField($field);
+
+        $autoAcceptDecline = (new Switcher('auto_accept'))->setDefaultValue('on');
+        $autoDeclineBusy = (new Switcher('auto_busy'))->setDefaultValue('on');
+        $this->generateDoubleSection([$autoAcceptDecline, $autoDeclineBusy]);
+
+    }
+}

BIN
app/UI/Client/Templates/assets/icons/ressource.png


+ 18 - 0
app/UI/Client/Templates/assets/js/ressource/index.js

@@ -0,0 +1,18 @@
+/**
+ *
+ *
+ * Modal position fix.
+ * add custom class if modal height is bigger than window.
+ */
+mgEventHandler.on('ModalLoaded', null,function(){
+
+    $('.lu-modal__dialog').each(function(index){
+        var self = $(this);
+        var pixelDiff = $(window).height() - self.height();
+
+        if(pixelDiff < 30)
+        {
+            self.addClass('lu-modal_fixed_position');
+        }
+    });
+});

+ 5 - 0
app/UI/Client/Templates/ressource/buttons/spanDropdownButton.tpl

@@ -0,0 +1,5 @@
+<mg-component-body-{$elementId|strtolower}
+        component_id='{$elementId}'
+        component_namespace='{$namespace}'
+        component_index='{$rawObject->getIndex()}'
+></mg-component-body-{$elementId|strtolower}>

+ 30 - 0
app/UI/Client/Templates/ressource/buttons/spanDropdownButton_components.tpl

@@ -0,0 +1,30 @@
+
+<script type="text/x-template" id="t-mg-dropdawn-btn-wrapper-{$elementId|strtolower}"
+        :component_id="component_id"
+        :component_namespace="component_namespace"
+        :component_index="component_index"
+>
+    <span class="lu-has-dropdown">
+        <button @click="toogleDropdawn" class="mg-drop-target-btn lu-btn lu-btn--icon lu-btn--link lu-btn--default" data-tooltip="" data-title="{$MGLANG->T('More Actions')}">
+            <i class="lu-btn__icon lu-zmdi lu-zmdi-more-vert"></i>
+        </button>
+        <div class="mg-drop-bg-wrapper" v-show="dropOpen" @click="hideDrop"></div>
+        <div v-show="dropOpen"  @click="hideDrop" class="drop lu-drop-element drop-enabled drop-element-attached-top drop-element-attached-left drop-target-attached-bottom drop-target-attached-left drop-open drop-open-transitionend drop-after-open">
+            <div class="drop-content">
+                <div class="lu-dropdown" data-dropdown-menu="">
+                    <div class="lu-dropdown__arrow" data-arrow="" style="left: auto; right: 10px;"></div>
+                    <ul class="lu-dropdown__menu">
+                        <li class="lu-dropdown__header">
+                            <span class="lu-dropdown__title">{$MGLANG->T('Additional Actions')}</span>
+                        </li>
+                        {foreach from=$rawObject->getButtons() key=buttonKey item=buttonValue}
+                            <li class="lu-dropdown__item">
+                                {$buttonValue->getHtml()}
+                            </li>
+                        {/foreach}
+                    </ul>
+                </div>
+            </div>
+        </div>
+    </span>
+</script>

+ 1 - 1
core/DependencyInjection/Container.php

@@ -19,7 +19,7 @@ class Container extends \Illuminate\Container\Container
         return static::$instance;
     }
 
-    public static function setInstance(ContainerContract $container)
+    public static function setInstance(ContainerContract $container = null)
     {
         self::$instance = $container;
     }

+ 126 - 4
langs/english.php

@@ -244,6 +244,7 @@ $_LANG['createCOConfirmModal']['baseCancelButton']['title'] = 'Cancel';
 $_LANG['mainContainer']['configForm']['clientAreaFeatures']['clientAreaFeatures'] = 'Client Area Pages';
 $_LANG['mainContainer']['configForm']['clientAreaFeatures']['clientAreaFeaturesLeft']['ca_emailAccountPage']['ca_emailAccountPage'] = 'Email Accounts';
 $_LANG['mainContainer']['configForm']['clientAreaFeatures']['clientAreaFeaturesLeft']['ca_distributionListPage']['ca_distributionListPage'] = 'Distribution Lists';
+$_LANG['mainContainer']['configForm']['clientAreaFeatures']['clientAreaFeaturesLeft']['ca_ressourcesListPage']['ca_ressourcesListPage'] = 'Resources';
 $_LANG['mainContainer']['configForm']['clientAreaFeatures']['clientAreaFeaturesLeft']['ca_goToWebmailPage']['ca_goToWebmailPage'] = 'Go To Webmail';
 $_LANG['mainContainer']['configForm']['clientAreaFeatures']['clientAreaFeaturesRight']['ca_emailAliasesPage']['ca_emailAliasesPage'] = 'Email Aliases';
 $_LANG['mainContainer']['configForm']['clientAreaFeatures']['clientAreaFeaturesRight']['ca_domainAliasesPage']['ca_domainAliasesPage'] = 'Domain Aliases';
@@ -261,12 +262,14 @@ $_LANG['addonCA']['homePage']['manageHeader'] = 'Zimbra Email Management';
 $_LANG['addonCA']['homeIcons']['emailAccount'] = 'Email Accounts';
 $_LANG['addonCA']['homeIcons']['emailAlias'] = 'Email Aliases';
 $_LANG['addonCA']['homeIcons']['distributionList'] = 'Distribution Lists';
+$_LANG['addonCA']['homeIcons']['ressource'] = 'Resources';
 $_LANG['addonCA']['homeIcons']['domainAlias'] = 'Domain Aliases';
 $_LANG['addonCA']['homeIcons']['goWebmail'] = 'Go To Webmail';
 $_LANG['management']        = 'Management';
 $_LANG['emailAccount']      = 'Email Accounts';
 $_LANG['emailAlias'] = 'Email Aliases';
 $_LANG['distributionList'] = 'Distribution Lists';
+$_LANG['ressource'] = 'Resources';
 $_LANG['domainAlias'] = 'Domain Aliases';
 $_LANG['goWebmail'] = 'Go To Webmail';
 
@@ -283,6 +286,23 @@ $_LANG['addonCA']['emailAccount']['mainContainer']['accounts']['table']['status'
 $_LANG['addonCA']['emailAccount']['mainContainer']['accounts']['editAccountButton']['button']['editAccountButton'] = 'Edit';
 $_LANG['addonCA']['emailAccount']['mainContainer']['accounts']['deleteAccountButton']['button']['deleteAccountButton'] = 'Delete';
 
+$_LANG['addonCA']['ressource']['mainContainer']['ressource']['ressourcePageTitle'] = 'Resource Accounts Management';
+$_LANG['addonCA']['ressource']['mainContainer']['ressource']['ressourcePageDescription'] = 'In this area you can manage resource accounts associated with your domains.';
+
+$_LANG['addonCA']['ressource']['mainContainer']['ressources']['addRessourceButton']['button']['addRessourceButton'] = 'Add Resource';
+$_LANG['addonCA']['ressource']['mainContainer']['ressources']['table']['ressource'] = 'Resource';
+$_LANG['addonCA']['ressource']['mainContainer']['ressources']['table']['date_created'] = 'Date Created';
+$_LANG['addonCA']['ressource']['mainContainer']['ressources']['table']['last_login'] = 'Last Login';
+$_LANG['addonCA']['ressource']['mainContainer']['ressources']['table']['capacity'] = 'Capacity';
+$_LANG['addonCA']['ressource']['mainContainer']['ressources']['table']['type'] = 'Type';
+$_LANG['addonCA']['ressource']['mainContainer']['ressources']['table']['status'] = 'Status';
+$_LANG['addonCA']['ressource']['mainContainer']['ressources']['editRessourceButton']['button']['editRessourceButton'] = 'Edit';
+$_LANG['addonCA']['ressource']['mainContainer']['ressources']['deleteRessourceButton']['button']['deleteRessourceButton'] = 'Delete';
+$_LANG['addonCA']['ressource']['mainContainer']['ressources']['actions']['More Actions'] = 'More Actions';
+$_LANG['addonCA']['ressource']['ressources']['actions']['More Actions'] = 'More Actions';
+$_LANG['addonCA']['ressource']['mainContainer']['ressources']['actions']['Additional Actions'] = 'Additional Actions';
+$_LANG['addonCA']['ressource']['ressources']['actions']['Additional Actions'] = 'Additional Actions';
+
 $_LANG['addonCA']['emailAccount']['addAccountModal']['modal']['addAccountModal'] = 'Add Email Account';
 $_LANG['addonCA']['emailAccount']['addAccountModal']['generalSection'] = 'General';
 $_LANG['addonCA']['emailAccount']['addAccountModal']['additionalSection'] = 'Additional Information';
@@ -308,6 +328,80 @@ $_LANG['addonCA']['emailAccount']['addAccountForm']['additionalSection']['post_c
 $_LANG['addonCA']['emailAccount']['addAccountModal']['baseAcceptButton']['title'] = 'Confirm';
 $_LANG['addonCA']['emailAccount']['addAccountModal']['baseCancelButton']['title'] = 'Cancel';
 
+$_LANG['addonCA']['ressource']['addRessourceModal']['modal']['addRessourceModal'] = 'Add new Resource';
+$_LANG['addonCA']['ressource']['addRessourceModal']['generalSection'] = 'General';
+$_LANG['addonCA']['ressource']['addRessourceModal']['additionalSection'] = 'Additional Informations';
+$_LANG['addonCA']['ressource']['addRessourceForm']['generalSection']['usernameGroup']['usernameGroup'] = 'E-Mail Address';
+$_LANG['addonCA']['ressource']['addRessourceForm']['generalSection']['display_name']['display_name'] = 'Display Name';
+$_LANG['addonCA']['ressource']['addRessourceForm']['generalSection']['status']['status'] = 'Status';
+$_LANG['addonCA']['ressource']['addRessourceForm']['generalSection']['password']['password'] = 'Password';
+$_LANG['addonCA']['ressource']['addRessourceForm']['generalSection']['repeat_password']['repeat_password'] = 'Repeat Password';
+$_LANG['addonCA']['ressource']['addRessourceForm']['generalSection']['password']['description'] = 'A password must contain at least 8 characters';
+$_LANG['addonCA']['ressource']['addRessourceForm']['generalSection']['type']['type'] = 'Type';
+$_LANG['addonCA']['ressource']['addRessourceForm']['generalSection']['capacity']['capacity'] = 'Number';
+$_LANG['addonCA']['ressource']['addRessourceForm']['generalSection']['auto_accept']['auto_accept'] = 'Accept automatically';
+$_LANG['addonCA']['ressource']['addRessourceForm']['generalSection']['auto_busy']['auto_busy'] = 'Automatically reject when busy';
+$_LANG['addonCA']['ressource']['addRessourceForm']['generalSection']['description']['description'] = 'Description';
+$_LANG['addonCA']['ressource']['addRessourceForm']['generalSection']['notes']['notes'] = 'Notes';
+$_LANG['addonCA']['ressource']['addRessourceForm']['additionalSection']['contact']['contact'] = 'Contact';
+$_LANG['addonCA']['ressource']['addRessourceForm']['additionalSection']['site']['site'] = 'Site';
+$_LANG['addonCA']['ressource']['addRessourceForm']['additionalSection']['contact_mail']['contact_mail'] = 'Contact E-Mail';
+$_LANG['addonCA']['ressource']['addRessourceForm']['additionalSection']['contact_phone']['contact_phone'] = 'Contact Phone';
+$_LANG['addonCA']['ressource']['addRessourceForm']['additionalSection']['street']['street'] = 'Street';
+$_LANG['addonCA']['ressource']['addRessourceForm']['additionalSection']['building']['building'] = 'Building';
+$_LANG['addonCA']['ressource']['addRessourceForm']['additionalSection']['floor']['floor'] = 'Floor';
+$_LANG['addonCA']['ressource']['addRessourceForm']['additionalSection']['room']['room'] = 'Room';
+$_LANG['addonCA']['ressource']['addRessourceForm']['additionalSection']['post_code']['post_code'] = 'Postcode';
+$_LANG['addonCA']['ressource']['addRessourceForm']['additionalSection']['town']['town'] = 'Town';
+$_LANG['addonCA']['ressource']['addRessourceForm']['additionalSection']['state']['state'] = 'State';
+$_LANG['addonCA']['ressource']['addRessourceForm']['additionalSection']['county']['county'] = 'County';
+$_LANG['addonCA']['ressource']['addRessourceModal']['baseAcceptButton']['title'] = 'Confirm';
+$_LANG['addonCA']['ressource']['addRessourceModal']['baseCancelButton']['title'] = 'Cancel';
+
+$_LANG['addonCA']['ressource']['editRessourceModal']['modal']['editRessourceModal'] = 'Ressource bearbeiten';
+$_LANG['addonCA']['ressource']['editRessourceModal']['editGeneralSection'] = 'General';
+$_LANG['addonCA']['ressource']['editRessourceModal']['editAdditionalSection'] = 'Additional Informations';
+$_LANG['addonCA']['ressource']['editRessourceForm']['editGeneralSection']['usernameGroup']['usernameGroup'] = 'E-Mail Address';
+$_LANG['addonCA']['ressource']['editRessourceForm']['editGeneralSection']['display_name']['display_name'] = 'Display Name';
+$_LANG['addonCA']['ressource']['editRessourceForm']['editGeneralSection']['status']['status'] = 'Status';
+$_LANG['addonCA']['ressource']['editRessourceForm']['editGeneralSection']['password']['password'] = 'Password';
+$_LANG['addonCA']['ressource']['editRessourceForm']['editGeneralSection']['repeat_password']['repeat_password'] = 'Repeat Password';
+$_LANG['addonCA']['ressource']['editRessourceForm']['editGeneralSection']['password']['description'] = 'A password must contain at least 8 characters';
+$_LANG['addonCA']['ressource']['editRessourceForm']['editGeneralSection']['type']['type'] = 'Type';
+$_LANG['addonCA']['ressource']['editRessourceForm']['editGeneralSection']['capacity']['capacity'] = 'Number';
+$_LANG['addonCA']['ressource']['editRessourceForm']['editGeneralSection']['auto_accept']['auto_accept'] = 'Accept automatically';
+$_LANG['addonCA']['ressource']['editRessourceForm']['editGeneralSection']['auto_busy']['auto_busy'] = 'Automatically reject when busy';
+$_LANG['addonCA']['ressource']['editRessourceForm']['editGeneralSection']['description']['description'] = 'Description';
+$_LANG['addonCA']['ressource']['editRessourceForm']['editGeneralSection']['notes']['notes'] = 'Notes';
+$_LANG['addonCA']['ressource']['editRessourceForm']['editAdditionalSection']['contact']['contact'] = 'Contact';
+$_LANG['addonCA']['ressource']['editRessourceForm']['editAdditionalSection']['site']['site'] = 'Site';
+$_LANG['addonCA']['ressource']['editRessourceForm']['editAdditionalSection']['contact_mail']['contact_mail'] = 'Contact E-Mail';
+$_LANG['addonCA']['ressource']['editRessourceForm']['editAdditionalSection']['contact_phone']['contact_phone'] = 'Contact Phone';
+$_LANG['addonCA']['ressource']['editRessourceForm']['editAdditionalSection']['street']['street'] = 'Street';
+$_LANG['addonCA']['ressource']['editRessourceForm']['editAdditionalSection']['building']['building'] = 'Building';
+$_LANG['addonCA']['ressource']['editRessourceForm']['editAdditionalSection']['floor']['floor'] = 'Floor';
+$_LANG['addonCA']['ressource']['editRessourceForm']['editAdditionalSection']['room']['room'] = 'Room';
+$_LANG['addonCA']['ressource']['editRessourceForm']['editAdditionalSection']['post_code']['post_code'] = 'Postcode';
+$_LANG['addonCA']['ressource']['editRessourceForm']['editAdditionalSection']['town']['town'] = 'Town';
+$_LANG['addonCA']['ressource']['editRessourceForm']['editAdditionalSection']['state']['state'] = 'State';
+$_LANG['addonCA']['ressource']['editRessourceForm']['editAdditionalSection']['county']['county'] = 'County';
+$_LANG['addonCA']['ressource']['editRessourceModal']['baseAcceptButton']['title'] = 'Confirm';
+$_LANG['addonCA']['ressource']['editRessourceModal']['baseCancelButton']['title'] = 'Cancel';
+
+$_LANG['addonCA']['ressource']['deleteRessourceModal']['modal']['deleteRessourceModal'] = 'Delete Resource';
+$_LANG['addonCA']['ressource']['deleteRessourceModal']['deleteRessourceForm']['confirmRemoveRessource'] = 'Are you sure that you want to delete this resource?';
+$_LANG['addonCA']['ressource']['deleteRessourceModal']['baseAcceptButton']['title'] = 'Confirm';
+$_LANG['addonCA']['ressource']['deleteRessourceModal']['baseCancelButton']['title'] = 'Cancel';
+
+$_LANG['addonCA']['ressource']['changeStatusModal']['modal']['changeStatusModal'] = 'Change Status';
+$_LANG['addonCA']['ressource']['changeStatusModal']['changeStatusForm']['status']['status'] = 'Status';
+$_LANG['addonCA']['ressource']['changeStatusModal']['baseAcceptButton']['title'] = 'Confirm';
+$_LANG['addonCA']['ressource']['changeStatusModal']['baseCancelButton']['title'] = 'Cancel';
+$_LANG['addonCA']['ressource']['mainContainer']['ressources']['changeStatusButton']['button']['changeStatusButton'] = 'Change Status';
+$_LANG['addonCA']['ressource']['mainContainer']['ressources']['changePassword']['button']['changePassword'] = 'Change Password';
+$_LANG['addonCA']['ressource']['ressources']['actions']['changeStatusButton']['button']['changeStatusButton'] = 'Change Status';
+$_LANG['addonCA']['ressource']['ressources']['actions']['changePassword']['button']['changePassword'] = 'Change Password';
+
 $_LANG['zimbra']['account']['status']['active'] = 'Active';
 $_LANG['zimbra']['account']['status']['locked'] = 'Locked';
 $_LANG['zimbra']['account']['status']['maintenance'] = 'Maintenance';
@@ -315,12 +409,19 @@ $_LANG['zimbra']['account']['status']['closed'] = 'Closed';
 $_LANG['zimbra']['account']['status']['lockout'] = 'Lockout';
 $_LANG['zimbra']['account']['status']['pending'] = 'Pending';
 
+$_LANG['zimbra']['ressource']['type']['location'] = 'Room';
+$_LANG['zimbra']['ressource']['type']['equipment'] = 'Equipment';
+
 $_LANG['FormValidators']['passwordsIsNotTheSame'] = 'Passwords must be the same';
 
 $_LANG['emailAccountHasBeenAdded'] = 'The email account has been created successfully';
 $_LANG['emailAccountHasBeenUpdated'] = 'The email account has been updated successfully';
 $_LANG['emailAccountHasBeenDeleted'] = 'The email account has been deleted successfully';
 
+$_LANG['ressourceHasBeenAdded'] = 'Resource has been created successfully';
+$_LANG['ressourceHasBeenUpdated'] = 'Resource has been updated successfully';
+$_LANG['ressourceHasBeenDeleted'] = 'Resource has been deleted successfully';
+
 $_LANG['addonCA']['emailAccount']['editAccountModal']['editGeneralSection'] = 'General';
 $_LANG['addonCA']['emailAccount']['editAccountModal']['editAdditionalSection'] = 'Additional Information';
 $_LANG['addonCA']['emailAccount']['editAccountModal']['modal']['editAccountModal'] = 'Edit Account';
@@ -423,9 +524,6 @@ $_LANG['addonCA']['distributionList']['addListModal']['modal']['addListModal'] =
 $_LANG['addonCA']['distributionList']['addListModal']['baseAcceptButton']['title'] = 'Confirm';
 $_LANG['addonCA']['distributionList']['addListModal']['baseCancelButton']['title'] = 'Cancel';
 
-$_LANG['domainAliasHasBeenCreated'] = 'The domain alias has been created successfully';
-$_LANG['domainAliasHasBeenDeleted'] = 'The domain alias has been deleted successfully';
-
 $_LANG['addonCA']['distributionList']['addListModal']['addMembersDistribution']     = 'Members';
 $_LANG['addonCA']['distributionList']['addListModal']['addPropertiesDistribution']  = 'Properties';
 $_LANG['addonCA']['distributionList']['addListModal']['addAliasesDistribution']     = 'Email Aliases';
@@ -490,6 +588,23 @@ $_LANG['addonCA']['emailAccount']['massDeleteAccountModal']['massDeleteAccountFo
 $_LANG['addonCA']['emailAccount']['massDeleteAccountModal']['baseAcceptButton']['title'] = 'Confirm';
 $_LANG['addonCA']['emailAccount']['massDeleteAccountModal']['baseCancelButton']['title'] = 'Cancel';
 
+$_LANG['addonCA']['ressource']['mainContainer']['ressources']['massChangeStatusButton']['button']['massChangeStatusButton'] = 'Change Status';
+$_LANG['addonCA']['ressource']['mainContainer']['ressources']['massDeleteRessourceButton']['button']['massDeleteRessourceButton'] = 'Delete';
+
+$_LANG['addonCA']['ressource']['massChangeStatusModal']['modal']['massChangeStatusModal'] = 'Change Status';
+$_LANG['addonCA']['ressource']['massChangeStatusModal']['deleteRessourceForm']['status']['status'] = 'Status';
+$_LANG['addonCA']['ressource']['massChangeStatusModal']['baseAcceptButton']['title'] = 'Confirm';
+$_LANG['addonCA']['ressource']['massChangeStatusModal']['baseCancelButton']['title'] = 'Cancel';
+
+$_LANG['massRessourceHasBeenDeleted']        = 'Resources have been deleted successfully';
+$_LANG['massRessourceStatusHasBeenUpdated']  = 'Resources have been updated successfully';
+$_LANG['ressourceStatusHasBeenUpdated']      = 'Resource has been updated successfully';
+
+$_LANG['addonCA']['ressource']['massDeleteRessourceModal']['modal']['massDeleteRessourceModal'] = 'Delete Resources';
+$_LANG['addonCA']['ressource']['massDeleteRessourceModal']['massDeleteRessourceForm']['massDeleteRessourceFormConfirm'] = 'Are you sure that you want to delete the selected resources?';
+$_LANG['addonCA']['ressource']['massDeleteRessourceModal']['baseAcceptButton']['title'] = 'Confirm';
+$_LANG['addonCA']['ressource']['massDeleteRessourceModal']['baseCancelButton']['title'] = 'Cancel';
+
 $_LANG['addonCA']['emailAlias']['mainContainer']['emailAliases']['massDeleteEmailAliasButton']['button']['massDeleteEmailAliasButton'] = 'Delete';
 
 $_LANG['addonCA']['emailAlias']['massDeleteEmailAliasModal']['modal']['massDeleteEmailAliasModal'] = 'Delete Email Aliases';
@@ -553,7 +668,6 @@ $_LANG['configurableOptionsUpdate'] = 'The configurable options have been update
 
 $_LANG['passwordChangedSuccessfully'] = 'The password has been changed successfully';
 $_LANG['addonCA']['emailAccount']['mainContainer']['accounts']['changePassword']['button']['changePassword'] = 'Change Password';
-
 $_LANG['addonCA']['emailAccount']['changePasswordModal']['modal']['changePasswordModal'] = 'Change Password';
 $_LANG['addonCA']['emailAccount']['changePasswordModal']['changePasswordForm']['password']['password'] = 'Password *';
 $_LANG['addonCA']['emailAccount']['changePasswordModal']['changePasswordForm']['password']['description'] = 'A password must contain at least 8 characters';
@@ -561,6 +675,14 @@ $_LANG['addonCA']['emailAccount']['changePasswordModal']['changePasswordForm']['
 $_LANG['addonCA']['emailAccount']['changePasswordModal']['baseAcceptButton']['title'] = 'Confirm';
 $_LANG['addonCA']['emailAccount']['changePasswordModal']['baseCancelButton']['title'] = 'Cancel';
 
+$_LANG['addonCA']['ressource']['mainContainer']['ressources']['changePassword']['button']['changePassword'] = 'Change Password';
+$_LANG['addonCA']['ressource']['changePasswordModal']['modal']['changePasswordModal'] = 'Change Password';
+$_LANG['addonCA']['ressource']['changePasswordModal']['changePasswordForm']['password']['password'] = 'Password *';
+$_LANG['addonCA']['ressource']['changePasswordModal']['changePasswordForm']['password']['description'] = 'A password must contain at least 8 characters';
+$_LANG['addonCA']['ressource']['changePasswordModal']['changePasswordForm']['repeat_password']['repeat_password'] = 'Repeat Password *';
+$_LANG['addonCA']['ressource']['changePasswordModal']['baseAcceptButton']['title'] = 'Confirm';
+$_LANG['addonCA']['ressource']['changePasswordModal']['baseCancelButton']['title'] = 'Cancel';
+
 $_LANG['Automatically accept'] = 'Automatically accept';
 $_LANG['Require list owner approval'] = 'Require list owner approval';
 $_LANG['Automatically reject'] = 'Automatically reject';

+ 130 - 10
langs/german.php

@@ -244,6 +244,7 @@ $_LANG['createCOConfirmModal']['baseCancelButton']['title'] = 'Abbrechen';
 $_LANG['mainContainer']['configForm']['clientAreaFeatures']['clientAreaFeatures'] = 'Client Area Pages';
 $_LANG['mainContainer']['configForm']['clientAreaFeatures']['clientAreaFeaturesLeft']['ca_emailAccountPage']['ca_emailAccountPage'] = 'Email Accounts';
 $_LANG['mainContainer']['configForm']['clientAreaFeatures']['clientAreaFeaturesLeft']['ca_distributionListPage']['ca_distributionListPage'] = 'Verteiler-Listen';
+$_LANG['mainContainer']['configForm']['clientAreaFeatures']['clientAreaFeaturesLeft']['ca_ressourcesListPage']['ca_ressourcesListPage'] = 'Ressourcen';
 $_LANG['mainContainer']['configForm']['clientAreaFeatures']['clientAreaFeaturesLeft']['ca_goToWebmailPage']['ca_goToWebmailPage'] = 'Go To Webmail';
 $_LANG['mainContainer']['configForm']['clientAreaFeatures']['clientAreaFeaturesRight']['ca_emailAliasesPage']['ca_emailAliasesPage'] = 'Email Aliases';
 $_LANG['mainContainer']['configForm']['clientAreaFeatures']['clientAreaFeaturesRight']['ca_domainAliasesPage']['ca_domainAliasesPage'] = 'Domain Aliases';
@@ -261,12 +262,14 @@ $_LANG['addonCA']['homePage']['manageHeader'] = 'Zimbra Email Verwaltung';
 $_LANG['addonCA']['homeIcons']['emailAccount'] = 'Email Accounts';
 $_LANG['addonCA']['homeIcons']['emailAlias'] = 'Email Aliases';
 $_LANG['addonCA']['homeIcons']['distributionList'] = 'Email Verteiler';
+$_LANG['addonCA']['homeIcons']['ressource'] = 'Ressourcen';
 $_LANG['addonCA']['homeIcons']['domainAlias'] = 'Domain Aliases';
 $_LANG['addonCA']['homeIcons']['goWebmail'] = 'Zimbra Webmail Login';
 $_LANG['management']        = 'Management';
 $_LANG['emailAccount']      = 'Email Accounts';
 $_LANG['emailAlias'] = 'Email Aliases';
 $_LANG['distributionList'] = 'Email Verteiler';
+$_LANG['ressource'] = 'Ressourcen';
 $_LANG['domainAlias'] = 'Domain Aliases';
 $_LANG['goWebmail'] = 'Zimbra Webmail Login';
 
@@ -277,12 +280,29 @@ $_LANG['addonCA']['breadcrumbs']['MG Demo'] = 'addonCA breadcrumbs MG Demo';
 $_LANG['addonCA']['emailAccount']['mainContainer']['accounts']['addAccountButton']['button']['addAccountButton'] = 'Neuer Account';
 $_LANG['addonCA']['emailAccount']['mainContainer']['accounts']['table']['mailbox'] = 'Account';
 $_LANG['addonCA']['emailAccount']['mainContainer']['accounts']['table']['date_created'] = 'Erstellungsdatum';
-$_LANG['addonCA']['emailAccount']['mainContainer']['accounts']['table']['last_login'] = 'Letzes Login';
+$_LANG['addonCA']['emailAccount']['mainContainer']['accounts']['table']['last_login'] = 'Letztes Login';
 $_LANG['addonCA']['emailAccount']['mainContainer']['accounts']['table']['quota'] = 'Quota (MB)';
 $_LANG['addonCA']['emailAccount']['mainContainer']['accounts']['table']['status'] = 'Status';
 $_LANG['addonCA']['emailAccount']['mainContainer']['accounts']['editAccountButton']['button']['editAccountButton'] = 'Editieren';
 $_LANG['addonCA']['emailAccount']['mainContainer']['accounts']['deleteAccountButton']['button']['deleteAccountButton'] = 'Löschen';
 
+$_LANG['addonCA']['ressource']['mainContainer']['ressource']['ressourcePageTitle'] = 'Verwaltung von Ressourcen Accounts';
+$_LANG['addonCA']['ressource']['mainContainer']['ressource']['ressourcePageDescription'] = 'In diesem Bereich können Sie die Ressourcen Accounts für Ihre Domäne verwalten.';
+
+$_LANG['addonCA']['ressource']['mainContainer']['ressources']['addRessourceButton']['button']['addRessourceButton'] = 'Neue Ressource';
+$_LANG['addonCA']['ressource']['mainContainer']['ressources']['table']['ressource'] = 'Name';
+$_LANG['addonCA']['ressource']['mainContainer']['ressources']['table']['date_created'] = 'Erstellungsdatum';
+$_LANG['addonCA']['ressource']['mainContainer']['ressources']['table']['capacity'] = 'Anzahl';
+$_LANG['addonCA']['ressource']['mainContainer']['ressources']['table']['last_login'] = 'Letztes Login';
+$_LANG['addonCA']['ressource']['mainContainer']['ressources']['table']['type'] = 'Type';
+$_LANG['addonCA']['ressource']['mainContainer']['ressources']['table']['status'] = 'Status';
+$_LANG['addonCA']['ressource']['mainContainer']['ressources']['editRessourceButton']['button']['editRessourceButton'] = 'Editieren';
+$_LANG['addonCA']['ressource']['mainContainer']['ressources']['deleteRessourceButton']['button']['deleteRessourceButton'] = 'Löschen';
+$_LANG['addonCA']['ressource']['mainContainer']['ressources']['actions']['More Actions'] = 'Mehr Aktionen';
+$_LANG['addonCA']['ressource']['ressources']['actions']['More Actions'] = 'Mehr Aktionen';
+$_LANG['addonCA']['ressource']['mainContainer']['ressources']['actions']['Additional Actions'] = 'Weitere Aktionen';
+$_LANG['addonCA']['ressource']['ressources']['actions']['Additional Actions'] = 'Weitere Aktionen';
+
 $_LANG['addonCA']['emailAccount']['addAccountModal']['modal']['addAccountModal'] = 'Neuer Email Account hinzufügen';
 $_LANG['addonCA']['emailAccount']['addAccountModal']['generalSection'] = 'Allgemein';
 $_LANG['addonCA']['emailAccount']['addAccountModal']['additionalSection'] = 'Zusätzliche Informationen';
@@ -308,19 +328,100 @@ $_LANG['addonCA']['emailAccount']['addAccountForm']['additionalSection']['post_c
 $_LANG['addonCA']['emailAccount']['addAccountModal']['baseAcceptButton']['title'] = 'Bestätigen';
 $_LANG['addonCA']['emailAccount']['addAccountModal']['baseCancelButton']['title'] = 'Abbrechen';
 
+$_LANG['addonCA']['ressource']['addRessourceModal']['modal']['addRessourceModal'] = 'Neue Ressource hinzufügen';
+$_LANG['addonCA']['ressource']['addRessourceModal']['generalSection'] = 'Allgemein';
+$_LANG['addonCA']['ressource']['addRessourceModal']['additionalSection'] = 'Zusätzliche Informationen';
+$_LANG['addonCA']['ressource']['addRessourceForm']['generalSection']['usernameGroup']['usernameGroup'] = 'E-Mail Adresse';
+$_LANG['addonCA']['ressource']['addRessourceForm']['generalSection']['display_name']['display_name'] = 'Anzeigename';
+$_LANG['addonCA']['ressource']['addRessourceForm']['generalSection']['status']['status'] = 'Status';
+$_LANG['addonCA']['ressource']['addRessourceForm']['generalSection']['password']['password'] = 'Passwort';
+$_LANG['addonCA']['ressource']['addRessourceForm']['generalSection']['repeat_password']['repeat_password'] = 'Passwort wiederholen';
+$_LANG['addonCA']['ressource']['addRessourceForm']['generalSection']['password']['description'] = 'Das Passwort muss mindestens 8 Zeichen enthalten';
+$_LANG['addonCA']['ressource']['addRessourceForm']['generalSection']['type']['type'] = 'Typ';
+$_LANG['addonCA']['ressource']['addRessourceForm']['generalSection']['capacity']['capacity'] = 'Anzahl';
+$_LANG['addonCA']['ressource']['addRessourceForm']['generalSection']['auto_accept']['auto_accept'] = 'Automatisch akzeptieren';
+$_LANG['addonCA']['ressource']['addRessourceForm']['generalSection']['auto_busy']['auto_busy'] = 'Automatisch ablehnen wenn belegt';
+$_LANG['addonCA']['ressource']['addRessourceForm']['generalSection']['description']['description'] = 'Beschreibung';
+$_LANG['addonCA']['ressource']['addRessourceForm']['generalSection']['notes']['notes'] = 'Notizen';
+$_LANG['addonCA']['ressource']['addRessourceForm']['additionalSection']['contact']['contact'] = 'Kontakt';
+$_LANG['addonCA']['ressource']['addRessourceForm']['additionalSection']['site']['site'] = 'Abteilung';
+$_LANG['addonCA']['ressource']['addRessourceForm']['additionalSection']['contact_mail']['contact_mail'] = 'Kontakt E-Mail';
+$_LANG['addonCA']['ressource']['addRessourceForm']['additionalSection']['contact_phone']['contact_phone'] = 'Kontakt Telefon';
+$_LANG['addonCA']['ressource']['addRessourceForm']['additionalSection']['street']['street'] = 'Strasse';
+$_LANG['addonCA']['ressource']['addRessourceForm']['additionalSection']['building']['building'] = 'Gebäude';
+$_LANG['addonCA']['ressource']['addRessourceForm']['additionalSection']['floor']['floor'] = 'Etage';
+$_LANG['addonCA']['ressource']['addRessourceForm']['additionalSection']['room']['room'] = 'Raum';
+$_LANG['addonCA']['ressource']['addRessourceForm']['additionalSection']['post_code']['post_code'] = 'Postleitzahl';
+$_LANG['addonCA']['ressource']['addRessourceForm']['additionalSection']['town']['town'] = 'Stadt/Gemeinde';
+$_LANG['addonCA']['ressource']['addRessourceForm']['additionalSection']['state']['state'] = 'Land';
+$_LANG['addonCA']['ressource']['addRessourceForm']['additionalSection']['county']['county'] = 'Bundesland';
+$_LANG['addonCA']['ressource']['addRessourceModal']['baseAcceptButton']['title'] = 'Bestätigen';
+$_LANG['addonCA']['ressource']['addRessourceModal']['baseCancelButton']['title'] = 'Abbrechen';
+
+$_LANG['addonCA']['ressource']['editRessourceModal']['modal']['editRessourceModal'] = 'Ressource bearbeiten';
+$_LANG['addonCA']['ressource']['editRessourceModal']['editGeneralSection'] = 'Allgemein';
+$_LANG['addonCA']['ressource']['editRessourceModal']['editAdditionalSection'] = 'Zusätzliche Informationen';
+$_LANG['addonCA']['ressource']['editRessourceForm']['editGeneralSection']['usernameGroup']['usernameGroup'] = 'E-Mail Adresse';
+$_LANG['addonCA']['ressource']['editRessourceForm']['editGeneralSection']['display_name']['display_name'] = 'Anzeigename';
+$_LANG['addonCA']['ressource']['editRessourceForm']['editGeneralSection']['status']['status'] = 'Status';
+$_LANG['addonCA']['ressource']['editRessourceForm']['editGeneralSection']['password']['password'] = 'Passwort';
+$_LANG['addonCA']['ressource']['editRessourceForm']['editGeneralSection']['repeat_password']['repeat_password'] = 'Passwort wiederholen';
+$_LANG['addonCA']['ressource']['editRessourceForm']['editGeneralSection']['password']['description'] = 'Das Passwort muss mindestens 8 Zeichen enthalten';
+$_LANG['addonCA']['ressource']['editRessourceForm']['editGeneralSection']['type']['type'] = 'Typ';
+$_LANG['addonCA']['ressource']['editRessourceForm']['editGeneralSection']['capacity']['capacity'] = 'Anzahl';
+$_LANG['addonCA']['ressource']['editRessourceForm']['editGeneralSection']['auto_accept']['auto_accept'] = 'Automatisch akzeptieren';
+$_LANG['addonCA']['ressource']['editRessourceForm']['editGeneralSection']['auto_busy']['auto_busy'] = 'Automatisch ablehnen wenn belegt';
+$_LANG['addonCA']['ressource']['editRessourceForm']['editGeneralSection']['description']['description'] = 'Beschreibung';
+$_LANG['addonCA']['ressource']['editRessourceForm']['editGeneralSection']['notes']['notes'] = 'Notizen';
+$_LANG['addonCA']['ressource']['editRessourceForm']['editAdditionalSection']['contact']['contact'] = 'Kontakt';
+$_LANG['addonCA']['ressource']['editRessourceForm']['editAdditionalSection']['site']['site'] = 'Abteilung';
+$_LANG['addonCA']['ressource']['editRessourceForm']['editAdditionalSection']['contact_mail']['contact_mail'] = 'Kontakt E-Mail';
+$_LANG['addonCA']['ressource']['editRessourceForm']['editAdditionalSection']['contact_phone']['contact_phone'] = 'Kontakt Telefon';
+$_LANG['addonCA']['ressource']['editRessourceForm']['editAdditionalSection']['street']['street'] = 'Strasse';
+$_LANG['addonCA']['ressource']['editRessourceForm']['editAdditionalSection']['building']['building'] = 'Gebäude';
+$_LANG['addonCA']['ressource']['editRessourceForm']['editAdditionalSection']['floor']['floor'] = 'Etage';
+$_LANG['addonCA']['ressource']['editRessourceForm']['editAdditionalSection']['room']['room'] = 'Raum';
+$_LANG['addonCA']['ressource']['editRessourceForm']['editAdditionalSection']['post_code']['post_code'] = 'Postleitzahl';
+$_LANG['addonCA']['ressource']['editRessourceForm']['editAdditionalSection']['town']['town'] = 'Stadt/Gemeinde';
+$_LANG['addonCA']['ressource']['editRessourceForm']['editAdditionalSection']['state']['state'] = 'Land';
+$_LANG['addonCA']['ressource']['editRessourceForm']['editAdditionalSection']['county']['county'] = 'Bundesland';
+$_LANG['addonCA']['ressource']['editRessourceModal']['baseAcceptButton']['title'] = 'Bestätigen';
+$_LANG['addonCA']['ressource']['editRessourceModal']['baseCancelButton']['title'] = 'Abbrechen';
+
+$_LANG['addonCA']['ressource']['deleteRessourceModal']['modal']['deleteRessourceModal'] = 'Ressource löschen';
+$_LANG['addonCA']['ressource']['deleteRessourceModal']['deleteRessourceForm']['confirmRemoveRessource'] = 'Sind Sie sicher, dass diese Ressource gelöscht werden soll?';
+$_LANG['addonCA']['ressource']['deleteRessourceModal']['baseAcceptButton']['title'] = 'Bestätigen';
+$_LANG['addonCA']['ressource']['deleteRessourceModal']['baseCancelButton']['title'] = 'Abbrechen';
+
+$_LANG['addonCA']['ressource']['changeStatusModal']['modal']['changeStatusModal'] = 'Status ändern';
+$_LANG['addonCA']['ressource']['changeStatusModal']['changeStatusForm']['status']['status'] = 'Status';
+$_LANG['addonCA']['ressource']['changeStatusModal']['baseAcceptButton']['title'] = 'Bestätigen';
+$_LANG['addonCA']['ressource']['changeStatusModal']['baseCancelButton']['title'] = 'Abbrechen';
+$_LANG['addonCA']['ressource']['mainContainer']['ressources']['changeStatusButton']['button']['changeStatusButton'] = 'Status ändern';
+$_LANG['addonCA']['ressource']['mainContainer']['ressources']['changePassword']['button']['changePassword'] = 'Passwort ändern';
+$_LANG['addonCA']['ressource']['ressources']['actions']['changeStatusButton']['button']['changeStatusButton'] = 'Status ändern';
+$_LANG['addonCA']['ressource']['ressources']['actions']['changePassword']['button']['changePassword'] = 'Passwort ändern';
+
 $_LANG['zimbra']['account']['status']['active'] = 'Aktiv';
 $_LANG['zimbra']['account']['status']['locked'] = 'Blockiert';
 $_LANG['zimbra']['account']['status']['maintenance'] = 'Maintenance';
 $_LANG['zimbra']['account']['status']['closed'] = 'Geschlossen';
-$_LANG['zimbra']['account']['status']['lockout'] = 'Blockiert';
+$_LANG['zimbra']['account']['status']['lockout'] = 'Gesperrt';
 $_LANG['zimbra']['account']['status']['pending'] = 'Pending';
 
+$_LANG['zimbra']['ressource']['type']['location'] = 'Ort';
+$_LANG['zimbra']['ressource']['type']['equipment'] = 'Inventar';
+
 $_LANG['FormValidators']['passwordsIsNotTheSame'] = 'Die Passwörter stimmen nicht überein';
 
 $_LANG['emailAccountHasBeenAdded'] = 'Der Email Account wurde erfolgreich erstellt';
 $_LANG['emailAccountHasBeenUpdated'] = 'Der Email Account wurde erfolgreich aktualisiert';
 $_LANG['emailAccountHasBeenDeleted'] = 'Der Email Account wurde erfolgreich gelöscht';
 
+$_LANG['ressourceHasBeenAdded'] = 'Die Ressource wurde erfolgreich erstellt';
+$_LANG['ressourceHasBeenUpdated'] = 'Die Ressource wurde erfolgreich aktualisiert';
+$_LANG['ressourceHasBeenDeleted'] = 'Die Ressource wurde erfolgreich gelöscht';
+
 $_LANG['addonCA']['emailAccount']['editAccountModal']['editGeneralSection'] = 'Allgemein';
 $_LANG['addonCA']['emailAccount']['editAccountModal']['editAdditionalSection'] = 'Zusätzliche Informationen';
 $_LANG['addonCA']['emailAccount']['editAccountModal']['modal']['editAccountModal'] = 'Account bearbeiten';
@@ -393,11 +494,7 @@ $_LANG['domainAliasHasBeenCreated'] = 'Der Domain Alias wurde erfolgreich erstel
 $_LANG['domainAliasHasBeenDeleted'] = 'Der Domain Alias wurde erfolgreich gelöscht';
 
 $_LANG['addonCA']['distributionList']['mainContainer']['distributionList']['distributionListPageTitle'] = 'Verwaltung von Email Verteilern';
-$_LANG['addonCA']['distributionList']['mainContainer']['distributionList']['distributionListPageDescription'] = 
-
-
-'Ein Email Verteiler eine virtuelle Email Adresse welche mit einer Gruppe von Postfächern verbunden ist. Wenn ein Mail an einen Email Verteiler geschickt wird, erhalten alle angeschlossenen Postfächer (Mitglieder) dieses Verteilers eine Kopie dieser Email.';
-
+$_LANG['addonCA']['distributionList']['mainContainer']['distributionList']['distributionListPageDescription'] = 'Ein Email Verteiler eine virtuelle Email Adresse welche mit einer Gruppe von Postfächern verbunden ist. Wenn ein Mail an einen Email Verteiler geschickt wird, erhalten alle angeschlossenen Postfächer (Mitglieder) dieses Verteilers eine Kopie dieser Email.';
 $_LANG['addonCA']['distributionList']['mainContainer']['lists']['addListButton']['button']['addListButton'] = 'Verteiler hinzufügen';
 $_LANG['addonCA']['distributionList']['mainContainer']['lists']['table']['email'] = 'Email';
 $_LANG['addonCA']['distributionList']['mainContainer']['lists']['table']['name'] = 'Anzeigename';
@@ -427,7 +524,6 @@ $_LANG['addonCA']['distributionList']['addListModal']['modal']['addListModal'] =
 $_LANG['addonCA']['distributionList']['addListModal']['baseAcceptButton']['title'] = 'Bestätigen';
 $_LANG['addonCA']['distributionList']['addListModal']['baseCancelButton']['title'] = 'Abbrechen';
 
-
 $_LANG['addonCA']['distributionList']['addListModal']['addMembersDistribution']     = 'Mitglieder';
 $_LANG['addonCA']['distributionList']['addListModal']['addPropertiesDistribution']  = 'Eigenschaften';
 $_LANG['addonCA']['distributionList']['addListModal']['addAliasesDistribution']     = 'Email Aliases';
@@ -492,6 +588,23 @@ $_LANG['addonCA']['emailAccount']['massDeleteAccountModal']['massDeleteAccountFo
 $_LANG['addonCA']['emailAccount']['massDeleteAccountModal']['baseAcceptButton']['title'] = 'Bestätigen';
 $_LANG['addonCA']['emailAccount']['massDeleteAccountModal']['baseCancelButton']['title'] = 'Abbrechen';
 
+$_LANG['addonCA']['ressource']['mainContainer']['ressources']['massChangeStatusButton']['button']['massChangeStatusButton'] = 'Status ändern';
+$_LANG['addonCA']['ressource']['mainContainer']['ressources']['massDeleteRessourceButton']['button']['massDeleteRessourceButton'] = 'Löschen';
+
+$_LANG['addonCA']['ressource']['massChangeStatusModal']['modal']['massChangeStatusModal'] = 'Status ändern';
+$_LANG['addonCA']['ressource']['massChangeStatusModal']['deleteRessourceForm']['status']['status'] = 'Status';
+$_LANG['addonCA']['ressource']['massChangeStatusModal']['baseAcceptButton']['title'] = 'Bestätigen';
+$_LANG['addonCA']['ressource']['massChangeStatusModal']['baseCancelButton']['title'] = 'Abbrechen';
+
+$_LANG['massRessourceHasBeenDeleted']        = 'Die Ressourcen wurden erfolgreich gelöscht';
+$_LANG['massRessourceStatusHasBeenUpdated']  = 'Die Ressourcen wurden erfolgreich aktualisiert';
+$_LANG['ressourceStatusHasBeenUpdated']      = 'Die Ressource wurde erfolgreich aktualisiert';
+
+$_LANG['addonCA']['ressource']['massDeleteRessourceModal']['modal']['massDeleteRessourceModal'] = 'Ressourcen löschen';
+$_LANG['addonCA']['ressource']['massDeleteRessourceModal']['massDeleteRessourceForm']['massDeleteRessourceFormConfirm'] = 'Sind Sie sicher dass Sie die ausgewählten Ressourcen löschen wollen?';
+$_LANG['addonCA']['ressource']['massDeleteRessourceModal']['baseAcceptButton']['title'] = 'Bestätigen';
+$_LANG['addonCA']['ressource']['massDeleteRessourceModal']['baseCancelButton']['title'] = 'Abbrechen';
+
 $_LANG['addonCA']['emailAlias']['mainContainer']['emailAliases']['massDeleteEmailAliasButton']['button']['massDeleteEmailAliasButton'] = 'Löschen';
 
 $_LANG['addonCA']['emailAlias']['massDeleteEmailAliasModal']['modal']['massDeleteEmailAliasModal'] = 'Delete Email Aliases';
@@ -553,9 +666,8 @@ $_LANG['configurableOptionsCreate'] = 'The configurable options have been create
 $_LANG['configurableOptionsUpdate'] = 'The configurable options have been updated successfully.';
 
 
-$_LANG['passwordChangedSuccessfully'] = 'The password has been changed successfully';
+$_LANG['passwordChangedSuccessfully'] = 'Das Passwort wurde erfolgreich geändert';
 $_LANG['addonCA']['emailAccount']['mainContainer']['accounts']['changePassword']['button']['changePassword'] = 'Passwort ändern';
-
 $_LANG['addonCA']['emailAccount']['changePasswordModal']['modal']['changePasswordModal'] = 'Passwort ändern';
 $_LANG['addonCA']['emailAccount']['changePasswordModal']['changePasswordForm']['password']['password'] = 'Passwort *';
 $_LANG['addonCA']['emailAccount']['changePasswordModal']['changePasswordForm']['password']['description'] = 'Das Passwort muss mindestens 8 Zeichen enthalten';
@@ -563,6 +675,14 @@ $_LANG['addonCA']['emailAccount']['changePasswordModal']['changePasswordForm']['
 $_LANG['addonCA']['emailAccount']['changePasswordModal']['baseAcceptButton']['title'] = 'Bestätigen';
 $_LANG['addonCA']['emailAccount']['changePasswordModal']['baseCancelButton']['title'] = 'Abbrechen';
 
+$_LANG['addonCA']['ressource']['mainContainer']['ressources']['changePassword']['button']['changePassword'] = 'Passwort ändern';
+$_LANG['addonCA']['ressource']['changePasswordModal']['modal']['changePasswordModal'] = 'Passwort ändern';
+$_LANG['addonCA']['ressource']['changePasswordModal']['changePasswordForm']['password']['password'] = 'Passwort *';
+$_LANG['addonCA']['ressource']['changePasswordModal']['changePasswordForm']['password']['description'] = 'Das Passwort muss mindestens 8 Zeichen enthalten';
+$_LANG['addonCA']['ressource']['changePasswordModal']['changePasswordForm']['repeat_password']['repeat_password'] = 'Passwort wiederholen *';
+$_LANG['addonCA']['ressource']['changePasswordModal']['baseAcceptButton']['title'] = 'Bestätigen';
+$_LANG['addonCA']['ressource']['changePasswordModal']['baseCancelButton']['title'] = 'Abbrechen';
+
 $_LANG['Automatically accept'] = 'Automatisch akzeptieren';
 $_LANG['Require list owner approval'] = 'Benötigt die Bestätigung des Eigentümers';
 $_LANG['Automatically reject'] = 'Automatisch zurückweisen';

+ 0 - 17
vendor/mso/idna-convert/.gitattributes

@@ -1,17 +0,0 @@
-# Auto detect text files and perform LF normalization
-* text=auto
-
-# Custom for Visual Studio
-*.cs     diff=csharp
-
-# Standard to msysgit
-*.doc	 diff=astextplain
-*.DOC	 diff=astextplain
-*.docx diff=astextplain
-*.DOCX diff=astextplain
-*.dot  diff=astextplain
-*.DOT  diff=astextplain
-*.pdf  diff=astextplain
-*.PDF	 diff=astextplain
-*.rtf	 diff=astextplain
-*.RTF	 diff=astextplain

+ 0 - 4
vendor/mso/idna-convert/.gitignore

@@ -1,4 +0,0 @@
-/vendor/
-.htaccess
-.idea
-IdnaConvert-*.zip

+ 0 - 5
vendor/piwik/ini/.gitattributes

@@ -1,5 +0,0 @@
-# .gitattributes
-tests/ export-ignore
-
-# Auto detect text files and perform LF normalization
-* text=auto

+ 0 - 3
vendor/piwik/ini/.gitignore

@@ -1,3 +0,0 @@
-/composer.phar
-/composer.lock
-/vendor/

+ 0 - 3
vendor/psr/container/.gitignore

@@ -1,3 +0,0 @@
-composer.lock
-composer.phar
-/vendor/

+ 0 - 1
vendor/psr/log/.gitignore

@@ -1 +0,0 @@
-vendor

+ 0 - 5
vendor/rappasoft/laravel-helpers/.gitignore

@@ -1,5 +0,0 @@
-/vendor
-composer.phar
-composer.lock
-.DS_Store
-.idea

+ 0 - 3
vendor/symfony/cache/.gitignore

@@ -1,3 +0,0 @@
-composer.lock
-phpunit.xml
-vendor/

+ 0 - 3
vendor/symfony/dependency-injection/.gitignore

@@ -1,3 +0,0 @@
-vendor/
-composer.lock
-phpunit.xml

+ 0 - 3
vendor/symfony/http-foundation/.gitignore

@@ -1,3 +0,0 @@
-vendor/
-composer.lock
-phpunit.xml

+ 0 - 3
vendor/symfony/yaml/.gitignore

@@ -1,3 +0,0 @@
-vendor/
-composer.lock
-phpunit.xml

+ 326 - 121
zimbraEmail_help_mx.tpl

@@ -1,128 +1,333 @@
-<h2>Information zum MX Eintrag für {$maildomain}</h2>
+<h2>DNS Einstellungen für E-Mail @{$maildomain}</h2>
 <hr>
-
+<div class="alert alert-warning">
+	Wenn Sie Änderungen am DNS gemacht haben, kann es bis zu einer Stunde dauern, bevor die Änderung vollständig repliziert wurde. 
+	Da die Prüfung Ihrer Settings auf dieser Webseite von der Replikation abhängt, wird auch hier die Änderung erst angezeigt, wenn die Replikation abgeschlossen ist. 
+	Vermeiden Sie es bitte, zu versuchen, nach einer Änderung im DNS diese Änderung zu wiederholen, weil das Ergebnis aus obigen Gründen noch nicht direkt angezeigt wird!
+</div>
 <div class="row">
-    <div class="col-xl-9 primary-content left-layout">
-	<div class="section">
-	    <div class="row row-eq-height row-eq-height-sm">
-                <div class="col-md-5">
-		    {$LANG.clientareaproductdetails}
-    		</div>
-	        <div class="col-md-7">
-    		    {$product}
-        	</div>
-    	    </div>
-        </div>
-	<div class="section" style="margin-top: 0px">
-	    <div class="row row-eq-height row-eq-height-sm">
-		<div class="col-md-5">
-    		    Domain
-		</div>
-		<div class="col-md-7">
-    		    {$maildomain}
+    <div class="col-xl-12 primary-content left-layout">
+{* debug		
+		mx: {$mx}<br>
+		selfDNS: {$selfDNS}<br>
+		multiMX: {$multiMX}<br>
+		mxtarget: {$mxtarget}<br>
+		domainMX:
+		{foreach $domainMX as $MX}
+			{$MX->preference} {$MX->exchange}<br>
+		{/foreach}
+		SPF: {$spf}<br>
+		multiSPF: {$multiSPF}<br>
+		domainSPF:
+		{foreach $domainSPF as $record}
+			TXT "{$record}"<br>
+		{/foreach}
+*}
+		<div class="row row-eq-height row-eq-height-sm">
+			<div class="col-md-6">
+				<div class="section">
+					<div class="center">
+						<h4>Mails empfangen (MX Eintrag)
+					</div>
+					{if $mx === 'set' && $selfDNS == true && $multiXM == false}
+						<div class="alert alert-success" style="width:90%">
+							Der MX Eintrag ist richtig konfiguriert. Ihr Mailserver empfängt E-Mails für <b>{$maildomain}</b>
+						</div>
+						<div class="alert alert-info" style="width:90%">
+							Mailserver für {$maildomain}:
+							<div><small>
+								{$mxtarget}
+							</small></div>
+						</div>
+					{elseif $mx === 'set' && $selfDNS == true && $multiMX == true}
+						<div class="alert alert-info" style="width:90%">
+							Ein MX Eintrag mit für {$maildomain} zeigt auf diesen Mailserver. 
+							Es wurden aber weitere MX Einträge für {$maildomain} konfiguriert.
+							<div><small>
+								{foreach $domainMX as $MX}
+									Priorität: {$MX->preference} Ziel: {$MX->exchange}{if $MX->exchange == $mxtarget} ✔ {/if}<br>
+								{/foreach}
+							</small></div>
+							Bitte prüfen Sie die Einstellungen und korrigieren Sie diese gegebenenfalls.
+						</div>
+					{elseif $mx === 'set' && $selfDNS == false && $multiMX == true}
+						<div class="alert alert-info" style="width:90%">
+							Ein MX Eintrag mit für {$maildomain} zeigt auf diesen Mailserver. 
+							Es wurden aber weitere MX Einträge für {$maildomain} konfiguriert.
+							<div><small>
+								{foreach $domainMX as $MX}
+									Priorität: {$MX->preference} Ziel: {$MX->exchange}{if $MX->exchange == $mxtarget} ✔ {/if}<br>
+								{/foreach}
+							</small></div>
+							Bitte prüfen Sie die Einstellungen und korrigieren Sie diese gegebenenfalls.
+							Wenn Sie zukünftig Ihre DNS Einträge über Ihr ThurData Portal einfach verwalten wollen, 
+							können Sie Ihre Domain {$maildomain} auch transferieren lassen.
+						</div>
+					{elseif $mx === 'set' && $selfDNS == false && $multiMX == false}
+						<div class="alert alert-success" style="width:90%">
+							Der MX Eintrag ist richtig konfiguriert. Ihr Mailserver empfängt E-Mails für <b>{$maildomain}</b>
+						</div>
+						<div class="alert alert-info" style="width:90%">
+							Mailserver für {$maildomain}:
+							<div><small>
+								{$mxtarget}
+							</small></div>
+						</div>
+					{elseif $mx === 'unset' && $selfDNS == false}
+						<div class="alert alert-warning" style="width:90%">
+							Es ist kein MX Eintrag für <b>{$maildomain}</b> konfiguriert.
+						</div>
+						<div class="alert alert-info" style="width:90%">
+							Damit dieser Server E-Mails für @{$maildomain} empfangen kann, müssen Sie bei Ihrem DNS Server einen MX Eintrag für die Domain {$maildomain} mit Ziel <b>{$mxtarget}</b> hinzufügen.<br>
+							Wenn Sie zukünftig Ihre DNS Einträge über Ihr ThurData Portal einfach verwalten wollen, 
+							können Sie Ihre Domain {$maildomain} auch transferieren lassen.
+						</div>
+					{elseif $mx === 'unset' && $selfDNS == true}
+						<div class="alert alert-warning" style="width:90%">
+							Es ist kein MX Eintrag für <b>{$maildomain}</b> konfiguriert.
+						</div>
+						<div class="alert alert-info" style="width:90%">
+							Damit dieser Server E-Mails für @{$maildomain} empfangen kann, muß ein MX Eintrag für die Domain {$maildomain} mit Ziel {$mxtarget} hinzugefügt werden.
+						</div>
+						<form method="post" action="clientarea.php?action=productdetails">
+							<input type="hidden" name="id" value="{$id}" />
+							<input type="hidden" name="modop" value="custom" />
+							<input type="hidden" name="a" value="setMX" />
+							<button type="submit" class="btn btn-primary" title="automatisch konfigurieren">
+								MX {$LANG.orderconfigure}
+							</button>
+						</form>
+					{elseif $mx === 'wrong' && $selfDNS == true && $multiMX == false}
+						<div class="alert alert-warning" style="width:90%">
+							Der MX Eintrag für <b>{$maildomain}</b> ist nicht für diesen Mailserver konfiguriert.
+							E-Mails an @{$maildomain} werden an den Server {$mxtarget} geschickt.
+						</div>
+						<div class="alert alert-info" style="width:90%">
+							Damit dieser Server E-Mails für @{$maildomain} empfangen kann, muß ein MX Eintrag für die Domain {$maildomain} korrigiert werden.
+							Bitte beachten Sie, das nach dem Hinzufügen des Eintrags die DNS Replikation abgewartet werden muß.
+						</div>
+						<form method="post" action="clientarea.php?action=productdetails">
+							<input type="hidden" name="id" value="{$id}" />
+							<input type="hidden" name="modop" value="custom" />
+							<input type="hidden" name="a" value="setMX" />
+							<button type="submit" class="btn btn-primary" title="automatisch korrigieren">
+								MX {$LANG.orderconfigure}
+							</button>
+						</form>
+					{elseif $mx === 'wrong' && $selfDNS == true && $multiMX == true}
+						<div class="alert alert-warning" style="width:90%">
+							Der MX Eintrag für <b>{$maildomain}</b> ist nicht für diesen Mailserver konfiguriert.
+							Folgende Mailserver sind für @{$maildomain} konfiguriert:<br>
+							<div><small>
+								{foreach $domainMX as $MX}
+									Priorität: {$MX->preference} Ziel: {$MX->exchange}<br>
+								{/foreach}
+							</small></div>
+						</div>
+						<div class="alert alert-info" style="width:90%">
+							Damit dieser Server E-Mails für @{$maildomain} empfangen kann, ein MX Eintrag für die Domain {$maildomain} mit Ziel {$mxtarget} hinzugefügt werden.
+							Bitte beachten Sie, das nach dem Hinzufügen des Eintrags die DNS Replikation abgewartet werden muß.
+						</div>
+						<form method="post" action="clientarea.php?action=productdetails">
+							<input type="hidden" name="id" value="{$id}" />
+							<input type="hidden" name="modop" value="custom" />
+							<input type="hidden" name="a" value="setMX" />
+							<button type="submit" class="btn btn-primary">
+								MX {$LANG.orderconfigure}
+							</button>
+						</form>
+					{elseif $mx === 'wrong' && $selfDNS == false}
+						<div class="alert alert-warning" style="width:90%">
+							Der MX Eintrag für <b>{$maildomain}</b> ist nicht für diesen Mailserver konfiguriert.
+							E-Mails an @{$maildomain} werden an den Server {$mxtarget} geschickt.
+						</div>
+						<div class="alert alert-info" style="width:90%">
+							Damit dieser Server E-Mails für @{$maildomain} empfangen kann, muß der MX Eintrag für die Domain {$maildomain} auf das Ziel {$mxtarget} geändert werden.
+							Bitte beachten Sie, das nach dem Hinzufügen des Eintrags die DNS Replikation abgewartet werden muß.
+							Wenn Sie zukünftig Ihre DNS Einträge über Ihr ThurData Portal einfach verwalten wollen, 
+							können Sie Ihre Domain {$maildomain} auch transferieren lassen.
+						</div>
+					{else}
+						{* sollte nie erreicht werden *}
+						<div class="alert alert-warning" style="width:90%">
+							Beim Versuche, den MX Eintrag für <b>{$maildomain}</b> zu ermitteln, ist ein Fehler aufgetreten.
+							Bitte versuchen Sie es später noch einmal!
+						</div>
+					{/if}
+				</div>
+			</div>
+			<div class="col-md-6">
+				<div class="section">
+					<div class="center">
+						<h4>Mails verschicken (SPF Eintrag)
+					</div>
+					{if $spf === 'set' && $multiSPF == false}
+						<div class="alert alert-success" style="width:90%">
+							Der SPF Eintrag für Ihren Mailserver ist richtig konfiguriert.
+						</div>
+						<div class="alert alert-info" style="width:90%">
+							SPF Eintrag für {$maildomain}:
+							<div><small>
+								{$domainSPF.0}
+							</small></div>
+						</div>
+					{elseif $spf === 'set' && $selfDNS == false && $multiSPF == true}
+						<div class="alert alert-info" style="width:90%">
+							Ein korrekter SPF Eintrag für {$maildomain} existiert. 
+							Es wurden aber weitere SPF Einträge für {$maildomain} erkannt.
+							<div><small>
+								{foreach $domainSPF as $SPF}
+									{$SPF}<br>
+								{/foreach}
+							</small></div>
+							Bitte prüfen Sie die Einstellungen bei Ihrem DNS Anbieter und korrigieren Sie diese gegebenenfalls.
+							Wenn Sie zukünftig Ihre DNS Einträge über Ihr ThurData Portal einfach verwalten wollen, 
+							können Sie Ihre Domain {$maildomain} auch transferieren lassen.
+						</div>
+					{elseif $spf === 'set' && $selfDNS == true && $multiSPF == true}
+						<div class="alert alert-info" style="width:90%">
+							Ein korrekter SPF Eintrag für {$maildomain} existiert. 
+							Es wurden aber weitere SPF Einträge für {$maildomain} erkannt.
+							<div><small>
+								{foreach $domainSPF as $SPF}
+									{$SPF}<br>
+								{/foreach}
+							</small></div>
+							Bitte prüfen Sie die Einstellungen und korrigieren Sie diese gegebenenfalls.
+						</div>
+					{elseif $spf === 'unset' && $selfDNS == false}
+						<div class="alert alert-warning" style="width:90%">
+							Es ist kein SPF Eintrag für <b>{$maildomain}</b> konfiguriert.
+						</div>
+						<div class="alert alert-info" style="width:90%">
+							Ein falscher SPF Eintrag führt zu Zustellungsproblemen bei einigen E-Mail Providern. Thurdata empfiehlt die Einrichtung eines 
+							SPF Eintrags (Type TXT) in Ihrer Nameserver Verwaltung mit folgendem Inhalt:
+							<div><small>
+								'v=spf1 mx a:mail1.thurdata.ch ip4:185.163.51.0/24 ip4:89.35.78.0/23 ~all'
+							</small></div>
+						</div>
+					{elseif $spf === 'unset' && $selfDNS == true}
+						<div class="alert alert-warning" style="width:90%">
+							Es ist kein SPF Eintrag für <b>{$maildomain}</b> konfiguriert.
+						</div>
+						<div class="alert alert-info" style="width:90%">
+							Ein fehlender SPF Eintrag führt zu Zustellungsproblemen bei einigen E-Mail Providern. 
+							Bitte prüfen Sie die Einstellungen und korrigieren Sie diese gegebenenfalls.
+						</div>
+						<div class="col-md-4">
+							<form method="post" action="clientarea.php?action=productdetails">
+								<input type="hidden" name="id" value="{$id}" />
+								<input type="hidden" name="modop" value="custom" />
+								<input type="hidden" name="a" value="setSPF" />
+								<button type="submit" class="btn btn-primary" title="automatisch korrigieren">
+									SPF {$LANG.orderconfigure}
+								</button>
+							</form>
+						</div>
+					{elseif $spf === 'wrong' && $selfDNS == true && $multiSPF == false}
+						<div class="alert alert-warning" style="width:90%">
+							Der SPF Eintrag für <b>{$maildomain}</b> ist falsch oder entspricht nicht unser Empfehlung.
+							SPF Eintrag für {$maildomain}:
+							<div><small>
+								{$domainSPF.0}
+							</small></div>
+						</div>
+						<div class="alert alert-info" style="width:90%">
+							Ein falscher SPF Eintrag führt zu Zustellungsproblemen bei einigen E-Mail Providern. 
+						</div>
+						<form method="post" action="clientarea.php?action=productdetails">
+							<input type="hidden" name="id" value="{$id}" />
+							<input type="hidden" name="modop" value="custom" />
+							<input type="hidden" name="a" value="setSPF" />
+							<button type="submit" class="btn btn-primary" title="automatisch korrigieren">
+								SPF {$LANG.orderconfigure}
+							</button>
+						</form>
+					{elseif $spf === 'wrong' && $selfDNS == false && $multiSPF == true}
+						<div class="alert alert-warning" style="width:90%">
+							Der SPF Eintrag für <b>{$maildomain}</b> ist falsch oder entspricht nicht unser Empfehlung.
+							SPF Einträge für {$maildomain}:
+							<div><small>
+								{foreach $domainSPF as $record}
+									TXT "{$record}"<br>
+								{/foreach}
+							</small></div>
+						</div>
+						<div class="alert alert-info" style="width:90%">
+							Ein falscher SPF Eintrag führt zu Zustellungsproblemen bei einigen E-Mail Providern. 
+							Bitte prüfen Sie die Einstellungen bei Ihrem DNS Anbieter und korrigieren Sie diese gegebenenfalls.
+							Wenn Sie zukünftig Ihre DNS Einträge über Ihr ThurData Portal einfach verwalten wollen, 
+							können Sie Ihre Domain {$maildomain} auch transferieren lassen.
+						</div>
+					{elseif $spf === 'wrong' && $selfDNS == false && $multiSPF == false}
+						<div class="alert alert-warning" style="width:90%">
+							Der SPF Eintrag für <b>{$maildomain}</b> ist falsch oder entspricht nicht unser Empfehlung.
+							SPF Eintrag für {$maildomain}:
+							<div><small>
+								{$domainSPF.0}
+							</small></div>
+						</div>
+						<div class="alert alert-info" style="width:90%">
+							Ein falscher SPF Eintrag führt zu Zustellungsproblemen bei einigen E-Mail Providern. 
+							Bitte prüfen Sie die Einstellungen bei Ihrem DNS Anbieter und korrigieren Sie diese gegebenenfalls.
+							Wenn Sie zukünftig Ihre DNS Einträge über Ihr ThurData Portal einfach verwalten wollen, 
+							können Sie Ihre Domain {$maildomain} auch transferieren lassen.
+						</div>
+					{elseif $spf === 'wrong' && $selfDNS == true && $multiSPF == true}
+						<div class="alert alert-warning" style="width:90%">
+							Der SPF Eintrag für <b>{$maildomain}</b> ist falsch oder entspricht nicht unser Empfehlung.
+							SPF Einträge für {$maildomain}:
+							<div><small>
+								{foreach $domainSPF as $record}
+									TXT "{$record}"<br>
+								{/foreach}
+							</small></div>
+						</div>
+						<div class="alert alert-info" style="width:90%">
+							Ein falscher SPF Eintrag führt zu Zustellungsproblemen bei einigen E-Mail Providern. 
+							Bitte prüfen Sie die Einstellungen und korrigieren Sie diese gegebenenfalls.
+						</div>
+						<form method="post" action="clientarea.php?action=productdetails">
+							<input type="hidden" name="id" value="{$id}" />
+							<input type="hidden" name="modop" value="custom" />
+							<input type="hidden" name="a" value="setSPF" />
+							<button type="submit" class="btn btn-primary" title="automatisch korrigieren">
+								SPF {$LANG.orderconfigure}
+							</button>
+						</form>
+					{else}
+						{* sollte nie erreicht werden *}
+						<div class="alert alert-warning" style="width:90%">
+							Beim Versuche, den SPF Eintrag für <b>{$maildomain}</b> zu ermitteln, ist ein Fehler aufgetreten.
+							Bitte versuchen Sie es später noch einmal!
+						</div>
+					{/if}
+				</div>
+			</div>
 		</div>
-	    </div>
-	</div>
-	<div class="section">
-	    {if $action === 'show'}
-		<div class="alert alert-success" style="width:90%">
-	            Der MX Eintrag ist richtig konfiguriert. Ihr Mailserver empfängt E-Mails für <b>{$maildomain}</b>
-	        </div>
-	        <div class="alert alert-info" style="width:90%">
-	            Mailserver für {$maildomain}: {$mxtarget}
-	        </div>
-	    {elseif $action === 'set'}
-	        <div class="alert alert-warning" style="width:90%">
-	            Der MX Eintrag fehlt. Ihr Mailserver empfängt keine E-Mails für <b>{$maildomain}</b> !
-	        </div>
-	        <div class="alert alert-info">
-	            Klicken Sie auf <b>MX konfigurieren</b> um den Mailempfang für <b>{$maildomain}</b auf Ihr Thurmail Produkt zu aktivieren.
-	        </div>
-	    {elseif $action === 'change'}
-	        <div class="alert alert-warning" style="width:90%">
-	            Der MX Eintrag ist falsch. Ihr Mailserver empfängt keine E-Mails für <b>{$maildomain}</b> !<br>
-	            Mail für <b>{$maildomain}</b werden an den Server <b>{$mxtarget}</b> verschickt.
-	        </div>
-	        <div class="alert alert-info" style="width:90%">
-	            Klicken Sie auf <b>MX konfigurieren</b> um den Mailempfang für <b>{$maildomain}</b auf Ihr Thurmail Produkt zu aktivieren.
-	        </div>
-	    {elseif $action === 'noMX'}
-	        <div class="alert alert-warning" style="width:90%">
-	            Der MX Eintrag fehlt. Ihr Mailserver empfängt keine E-Mails für <b>{$maildomain}</b> !
-	        </div>
-	        <div class="alert alert-info" style="width:90%">
-		    Sie müssen den MX Eintrag bei Ihrem DNS-Hoster konfigurieren.<br>
-	            Alternativ bieten wir Ihnen die Option, Ihre Domain <b>{$maildomain}</b><br />
-	            zu uns zu transferieren und hier im Portal zu verwalten.
-	        </div>
-	    {elseif $action === 'wrongMX'}
-	        <div class="alert alert-warning" style="width:90%">
-	            Der MX Eintrag ist falsch. Ihr Mailserver empfängt keine E-Mails für <b>{$maildomain}</b> !<br>
-	            Mail für <b>{$maildomain}</b> werden an den Server <b>{$mxtarget}</b> verschickt.
-	        </div>
-	        <div class="alert alert-info" style="width:90%">
-	            Sie müssen den MX Eintrag bei Ihrem DNS-Hoster anpassen.<br>
-	            Alternativ bieten wir Ihnen die Option, Ihre Domain <b>{$maildomain}</b><br />
-	            zu uns zu transferieren und hier im Portal zu verwalten.
-	        </div>
-	    {elseif $action === 'manual'}
-	        <div class="alert alert-warning" style="width:90%">
-	            Es wurden mehrere MX Einträge für <b>{$maildomain}</b> gefunden.
-	        </div>
-	        <div class="alert alert-info" style="width:90%">
-	            Sie haben bereits mehrere MX Einträge für Ihre Domain <b>{$maildomain}</b> konfiguriert.<br>
-	            Da Sie Ihre Domain bei uns verwalten können Sie den DNS-Manager aufrufen, um Ihre MX Einträge zu prüfen.
-	        </div>
-	    {elseif $action === 'manualext'}
-	        <div class="alert alert-warning" style="width:90%">
-	            Es wurden mehrere MX Einträge für <b>{$maildomain}</b> bei einem externen Registrar gefunden.
-	        </div>
-	        <div class="alert alert-info" style="width:90%">
-	            Sie haben mehrere MX Einträge für Ihre Domain <b>{$maildomain}</b> bereits anderweitig konfiguriert.<br>
-	            Sie können Ihre MX Einträge bei Ihrem Registrar prüfen.<br>
-	            Alternativ bieten wir Ihnen die Option, Ihre Domain <b>{$maildomain}</b><br />
-	            zu uns zu transferieren und hier im Portal zu verwalten.
-	        </div>
-	    {/if}
-	</div>
-	<div class="clear"><br /><br /><br /></div>
-	<div class="section">
-	    <div class="row row-eq-height row-eq-height-sm">
-		<div class="col-md-4">
-    		    <form method="post" action="clientarea.php?action=productdetails">
-	        	<input type="hidden" name="id" value="{$id}" />
-    			<button type="submit" class="btn btn-default btn-block">
-            		    {$LANG.clientareabacklink}
-	        	</button>
-    		    </form>
+		<div class="clear">
+			<br /><hr /><br />
 		</div>
-		<div class="col-md-4">
-		    {if $action === 'show'}
-		    {elseif $action === 'set' || $action === 'change'}
-    			<form method="post" action="clientarea.php?action=productdetails">
-	        	    <input type="hidden" name="id" value="{$id}" />
-    			    <input type="hidden" name="modop" value="custom" />
-	        	    <input type="hidden" name="a" value="setMX" />
-	        	    <button type="submit" class="btn btn-default btn-block">
-    		    		MX {$LANG.orderconfigure}
-	        	    </button>
-	    		</form>
-    		    {elseif $action === 'manual'}
-    			<form method="post" action="clientarea.php?action=domaindns&domainid={$domainId}">
-	        	    <button type="submit" class="btn btn-default btn-block">
-    		    		{$LANG.domaindnsmanagement}
-	        	    </button>
-	    		</form>
-		    {else}
-    			<form method="post" action="cart.php?a=add&domain=transfer">
-			    <input type="hidden" name="sld" value="{$maildomain}" />
-	        	    <button type="submit" class="btn btn-default btn-block">
-            			{$LANG.domainstransfer} {$maildomain}
-	        	    </button>
-    			</form>
-		    {/if}
+		<div class="row row-eq-height row-eq-height-sm">
+			<div class="col-md-4">
+				<form method="post" action="clientarea.php?action=productdetails&id={$id}">
+					<input type="hidden" name="id" value="{$id}" />
+					<button type="submit" class="btn btn-default">
+						{$LANG.clientareabacklink}
+					</button>
+				</form>
+			</div>
+			{* Wenn bei Fehlern die Domain nicht selbst verwaltet wird, biete Domaintransfer an *}
+			{if $selfDNS == false && ($multiMX == true || $mx != 'set' || $multiSPF == true || $spf != 'set')}
+				<div class="col-md-4">
+					<form method="post" action="cart.php?a=add&domain=transfer">
+						<input type="hidden" name="sld" value="{$maildomain}" />
+						<button type="submit" class="btn btn-primary">
+							{$LANG.domainstransfer} {$maildomain}
+						</button>
+					</form>
+				</div>
+			{/if}
 		</div>
-	    </div>
 	</div>
-    </div>
 </div>

+ 145 - 76
zimbraEmail_mx.php

@@ -9,93 +9,35 @@ require_once 'Net/DNS2.php';
 const NS1 = '185.163.51.130';
 const NS2 = '185.163.51.131';
 const MX  = 'mail1.thurdata.ch';
+const SPF = 'v=spf1 mx a:mail1.thurdata.ch ip4:185.163.51.0/24 ip4:89.35.78.0/23 ~all';
 
 function ZimbraEmail_ClientAreaCustomButtonArray ($params)
 {
-    $mxStatus = ZimbraEmailCheckMX($params);
-    switch($mxStatus['action']) {
-        case 'set':
-            return array(
-                'MX Info' => 'infoMX',
-                'MX Setzen' => 'setMX',
-            );
-        case 'change':
-            return array(
-                'MX Info' => 'infoMX',
-                'MX Ändern' => 'setMX',
-            );
-        default:
-            return array(
-                'MX Info' => 'infoMX',
-            );
-    }
+    return array(
+        'DNS-Settings' => 'DNS',
+    );
 }
 
-function ZimbraEmail_infoMX($params)
+function ZimbraEmail_ClientAreaAllowedFunctions ($params)
 {
-    $mxStatus = ZimbraEmailCheckMX($params);
     return array(
-        'breadcrumb' => array(
-            'clientarea.php?action=productdetails&id=' . $params['serviceid'] . '&modop=custom&a=infoMX' => 'MX Info',
-        ),
-        'templatefile' => 'zimbraEmail_help_mx',
-        'vars' => array(
-            'maildomain' => $params['domain'],
-            'action' => $mxStatus['action'],
-            'mxtarget' => (isset($mxStatus['mxtarget']) ? $mxStatus['mxtarget'] : 'false'),
-        ),
+        'MX konfigurieren' => 'setMX',
+        'SPF konfigurieren' => 'setSPF',
     );
 }
 
-function ZimbraEmailCheckMX($params)
+function ZimbraEmail_DNS($params)
 {
-    unset($zoneID);
-    unset($mxStatus);
-    $clientDomains = localAPI('GetClientsDomains', array('clientid' => $params['userid']));
-    $nameserver = array(
-        NS1,
-        NS2);
-    
-    $resolver = new Net_DNS2_Resolver(array('nameservers' => $nameserver));
-    try {
-            $result = $resolver->query($params['domain'], 'MX');
-            
-    } catch(Net_DNS2_Exception $e) {
-            
-            echo "::query() failed: ", $e->getMessage(), "\n";
-    }
-    $domainMX = $result->answer;
-    if(count($domainMX) > 1) {
-        for($i=$clientDomains['startnumber'];$i<=$clientDomains['numreturned'];$i++) {
-            if($params['domain'] == $clientDomains['domains']['domain'][$i]['domainname']) {
-                return array('action' => 'manual', 'mxtarget' => $domainMX);
-            }
-        }
-        return array('action' => 'manualext', 'mxtarget' => $domainMX);
-    }
-    if(empty($domainMX)){
-        for($i=$clientDomains['startnumber'];$i<=$clientDomains['numreturned'];$i++) {
-            if($params['domain'] == $clientDomains['domains']['domain'][$i]['domainname']) {
-                return array('action' => 'set');
-            }
-        }
-        return array('action' => 'noMX');
-    } else {
-        $domainMXrecord = array_shift($domainMX);
-//        if($domainMXrecord['target'] == $params['serverhostname']) {
-        if($domainMXrecord->exchange == MX) {
-            return array('action' => 'show', 'mxtarget' => $domainMXrecord->exchange);
-        }
-        for($i=$clientDomains['startnumber'];$i<=$clientDomains['numreturned'];$i++) {
-            if($params['domain'] == $clientDomains['domains']['domain'][$i]['domainname']) {
-                return array('action' => 'change', 'mxtarget' => $domainMXrecord->exchange);
-            }
-        }
-        return array('action' => 'wrongMX', 'mxtarget' => $domainMXrecord->exchange);
-    }
+    $vars = ZimbraEmailCheckDNS($params);
+    return array(
+        'breadcrumb' => array(
+            'clientarea.php?action=productdetails&id=' . $params['serviceid'] . '&modop=custom&a=DNS' => 'DNS Mail Settings',
+        ),
+        'templatefile' => 'zimbraEmail_help_mx',
+        'vars' => $vars,
+    );
 }
 
-
 function ZimbraEmail_setMX($params)
 {
     $zoneIDcollection = Capsule::table('dns_manager2_zone')
@@ -119,13 +61,58 @@ function ZimbraEmail_setMX($params)
         'class' => 'IN',
         'data' => array(
             'preference' => '10',
-//            'exchange' => $params['serverhostname'],
             'exchange' => MX,
         ),
     );
     array_push($zoneRecords, $mxRecord);
     foreach($dnsZone['data']->records as $record) {
-        if($record->type != 'MX') {
+    if($record->type != 'MX') {
+            array_push($zoneRecords, $record);
+        };
+    }
+    $result = localAPI('dnsmanager' ,
+        array(
+            'dnsaction' => 'updateZone',
+            'zone_id' => $zoneID,
+            'records' => $zoneRecords,
+        )
+    );
+    if($result['result'] != 'success') {
+        return 'Error: cloud not update zone for ID ' . $zoneID;
+    }
+    return 'success';
+}
+
+function ZimbraEmail_setSPF($params)
+{
+    $zoneIDcollection = Capsule::table('dns_manager2_zone')
+        ->select('id')
+        ->where('name', '=', $params['domain'])
+        ->get();
+    $zoneIDobj = $zoneIDcollection[0];
+    $zoneID = $zoneIDobj->{'id'};
+    if(!isset($zoneID)) {
+        return 'Error: zone ID not found for domain ' . $params['domain'];
+    }
+    $dnsZone = localAPI('dnsmanager', array( 'dnsaction' => 'getZone', 'zone_id' => $zoneID));
+    if($dnsZone['result'] != 'success') {
+        return 'Error: cloud not fetch zone for ID ' . $zoneID;
+    }
+    $zoneRecords = array();
+    $spfRecord = array(
+            'line' => $params['domain'].'.|TXT|0',
+            'name' => '@',
+            'type' => 'TXT',
+            'class' => 'IN',
+            'data' => SPF
+        );
+    array_push($zoneRecords, $spfRecord);
+
+    foreach($dnsZone['data']->records as $record) {
+
+        if(!$record->type === 'TXT'){
+            array_push($zoneRecords, $record);
+        } elseif (!preg_match('/^v=spf(.*)$/i', trim($record->rdata->txtdata,'"'))) {
             array_push($zoneRecords, $record);
         };
     }
@@ -136,9 +123,91 @@ function ZimbraEmail_setMX($params)
             'records' => $zoneRecords,
         )
     );
+
     if($result['result'] != 'success') {
         return 'Error: cloud not update zone for ID ' . $zoneID;
     }
     return 'success';
 }
 
+function ZimbraEmailCheckDNS($params)
+{
+    unset($zoneID);
+    unset($mxStatus);
+    unset($dnsData);
+    unset($vars);
+    $vars['maildomain'] = $params['domain'];
+    $clientDomains = localAPI('GetClientsDomains', array('clientid' => $params['userid']));
+    $nameserver = array(
+        NS1,
+        NS2);
+    
+    $resolver = new Net_DNS2_Resolver(array('nameservers' => $nameserver));
+    try {
+            $result = $resolver->query($params['domain'], 'MX');
+            
+    } catch(Net_DNS2_Exception $e) {
+            
+            echo "::query() failed: ", $e->getMessage(), "\n";
+    }
+    $domainMX = $result->answer;
+    try {
+        $result = $resolver->query($params['domain'], 'TXT');
+        
+    } catch(Net_DNS2_Exception $e) {
+            
+            echo "::query() failed: ", $e->getMessage(), "\n";
+    }
+    $domainTXT = $result->answer;
+    $domainSPF = array();
+    foreach($domainTXT as $txtRecord) {
+        foreach($txtRecord->text as $txtData) {
+            if(strstr($txtData,'v=spf')) {
+                array_push($domainSPF,$txtData);
+            }
+        }
+    }
+    if (count($domainSPF) > 1) {
+        $vars['multiSPF'] = TRUE;
+    } else {
+        $vars['multiSPF'] = FALSE;
+    }
+    $vars['spf'] = 'wrong';
+    if (empty($domainSPF)) {
+        $vars['spf'] = 'unset';
+    } else {        
+        foreach($domainSPF as $spf) {
+            if($spf === SPF) {
+                $vars['spf'] = 'set';
+            }
+        }
+    }
+    $vars['domainSPF'] = $domainSPF;
+    if(count($domainMX) > 1) {
+        $vars['multiMX'] = TRUE;
+    } else {
+        $vars['multiMX'] = FALSE;
+    }
+    $vars['selfDNS'] = FALSE;
+    for($i=$clientDomains['startnumber'];$i<=$clientDomains['numreturned'];$i++) {
+        if($params['domain'] == $clientDomains['domains']['domain'][$i]['domainname']) {
+            $vars['selfDNS'] = TRUE;
+            $vars['domainId'] = $clientDomains['domains']['domain'][$i]['id'];
+        }
+    }
+    if(empty($domainMX)){
+        $vars['mx'] = 'unset';
+        $vars['mxtarget'] = MX;
+    } else {
+        $vars['domainMX'] = $domainMX;
+        $domainMXrecord = array_shift($domainMX);
+        $vars['mxtarget'] = $domainMXrecord->exchange;
+        if($domainMXrecord->exchange == MX) {
+            $vars['mx'] = 'set';
+        } else {
+            $var['mx'] = 'wrong';
+        }
+    }
+    return $vars;
+}
+