Explorar el Código

customized by thurdata

andre hace 4 años
padre
commit
eeb274eb07

+ 4 - 2
app/Enums/ProductParams.php

@@ -17,13 +17,15 @@ class ProductParams
     const FILTER_ACCOUNT_BY_COS     = 'filterAccountsByCOS';
     const ACCOUNT_LIMIT             = 'acc_limit';
     const ACCOUNT_SIZE              = 'acc_size';
+    const ACCOUNT_BASE              = 'acc_base';
     const SIZE_UNLIMITED            = '-1';
     const ZIMBRA_PREFIX_SETTINGS    = 'zimbra';
     const ALIAS_LIMIT               = 'alias_limit';
     const DOMAIN_ALIAS_LIMIT        = 'domain_alias_limit';
     const DOMAIN_LIST_LIMIT         = 'dist_list_limit';
     const DOMAIN_MAX_SIZE           = 'domainMaxSize';
-    const SWITCHER_ENABLED = 'on';
-    const SWITCHER_DISABLED = 'off';
+    const DOMAIN_BASE_SIZE          = 'domainBaseSize';
+    const SWITCHER_ENABLED          = 'on';
+    const SWITCHER_DISABLED         = 'off';
 
 }

+ 2 - 0
app/Enums/Size.php

@@ -13,10 +13,12 @@ namespace ModulesGarden\Servers\ZimbraEmail\App\Enums;
  */
 class Size
 {
+    const B_TO_GB = 1073741824;
     const B_TO_MB = 1048576;
     const B_TO_KB = 1024;
 
     const DEFAULT_ACC_LIMIT          = 20;
+    const DEFAULT_ACC_BASE           = 1;
     const DEFAULT_ACC_SIZE           = 100;
     const DEFAULT_ALIAS_LIMIT        = 10;
     const DEFAULT_DOMAIN_ALIAS_LIMIT = 10;

+ 8 - 0
app/Http/Actions/CreateAccount.php

@@ -5,6 +5,7 @@ namespace ModulesGarden\Servers\ZimbraEmail\App\Http\Actions;
 
 use ModulesGarden\Servers\ZimbraEmail\App\Enums\Response;
 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\Domain;
 use ModulesGarden\Servers\ZimbraEmail\App\Traits\ExtensionsCheckerTrait;
 use ModulesGarden\Servers\ZimbraEmail\Core\App\Controllers\Instances\AddonController;
@@ -67,12 +68,19 @@ class CreateAccount extends AddonController
             ->service()
             ->createDomain();
 
+        /**
+         * product manager allow to check product settings
+         */
+        $productManager = new ProductManager();
+        $productManager->loadByHostingId($params['serviceid']);
+
         /**
          *
          * set params
          * run service (Create domain in Zimbra API)
          */
         $result = $service
+            ->setProductManager($productManager)
             ->setFormData($params)
             ->run();
 

+ 9 - 8
app/Http/Actions/UsageUpdate.php

@@ -22,17 +22,18 @@ class UsageUpdate extends AddonController
             ->repository()
             ->domains()
             ->getAll();
-
         foreach ($domains as $domain)
         {
             try
             {
                 $domainName = $domain->getName();
-                $storage = $this->getDomainUsage($domainName);
+                $usage = $this->getDomainUsage($domainName);
+                $mailboxes = $usage['mailboxes'];
+                $storage = $usage['usage'];
                 $storage = $storage == 0 ? 0 : round($storage/1024/1024);
-
                 $serverId =$params['serverid'];
 
+                Whmcs\Hosting::where('server', $serverId)->where('domain', $domainName)->update(['bwusage' => $mailboxes]);
                 Whmcs\Hosting::where('server', $serverId)->where('domain', $domainName)->update(['diskusage' => $storage]);
 
                 usleep(5000);
@@ -47,13 +48,13 @@ class UsageUpdate extends AddonController
 
     private function getDomainUsage($tenant)
     {
-        $accounts =(new ZimbraManager())
+        $client = (new ZimbraManager())
             ->getApiByServer($this->moduleParams['serverid'])
             ->soap
             ->repository()
-            ->accounts
-            ->getUsages($tenant);
-
+            ->accounts;
+        $accounts = $client->getUsages($tenant);
+        $mailboxes = count($client->getMailboxes($tenant));
         $totalUsage = 0;
         foreach ($accounts as $account)
         {
@@ -61,6 +62,6 @@ class UsageUpdate extends AddonController
             $totalUsage += $usage;
         }
 
-        return $totalUsage;
+        return array('usage' => $totalUsage, 'mailboxes' => $mailboxes);
     }
 }

+ 6 - 5
app/Libs/Metrics/MyMetricProvider.php

@@ -5,13 +5,14 @@ namespace ModulesGarden\Servers\ZimbraEmail\App\Libs\Metrics;
 use ModulesGarden\Servers\HetznerVps\App\Libs\HetznerVps\Api;
 use ModulesGarden\Servers\HetznerVps\App\Libs\HetznerVps\Api\Constants;
 use ModulesGarden\Servers\ZimbraEmail\App\Helpers\ZimbraManager;
+use ModulesGarden\Servers\ZimbraEmail\App\Enums\Size;
 use mysql_xdevapi\DocResult;
 use WHMCS\UsageBilling\Contracts\Metrics\MetricInterface;
 use WHMCS\UsageBilling\Contracts\Metrics\ProviderInterface;
 use WHMCS\UsageBilling\Metrics\Metric;
 use WHMCS\UsageBilling\Metrics\Units\WholeNumber;
 use WHMCS\UsageBilling\Metrics\Usage;
-use WHMCS\UsageBilling\Metrics\Units\MegaBytes;
+use WHMCS\UsageBilling\Metrics\Units\GigaBytes;
 
 class MyMetricProvider implements ProviderInterface
 {
@@ -48,7 +49,7 @@ class MyMetricProvider implements ProviderInterface
                 'storage',
                 'Storage',
                 MetricInterface::TYPE_SNAPSHOT,
-                new MegaBytes()
+                new GigaBytes()
             )
         ];
     }
@@ -90,7 +91,7 @@ class MyMetricProvider implements ProviderInterface
                 'distributionLists' => $countOfDistributionList,
                 'aliases' => $countOfEmailAliases,
                 'domainAliases' => $countOfDomainAliases,
-                'storage' => $storage/1024/1024,
+                'storage' => round($storage / Size::B_TO_GB, 2),
             ];
 
             $usage[$domainName] = $this->wrapUserData($domainData);
@@ -123,7 +124,7 @@ class MyMetricProvider implements ProviderInterface
             'distributionLists' => $countOfDistributionList,
             'aliases' => $countOfEmailAliases,
             'domainAliases' => $countOfDomainAliases,
-            'storage' => ($storage/1024/1024),
+            'storage' => round($storage / Size::B_TO_GB, 2),
         ];
 
         return $this->wrapUserData($userData);
@@ -202,4 +203,4 @@ class MyMetricProvider implements ProviderInterface
         return $distributionList;
     }
 
-}
+}

+ 7 - 6
app/Libs/Zimbra/Components/Api/Soap/Models/Domain.php

@@ -15,12 +15,13 @@ use ModulesGarden\Servers\ZimbraEmail\App\Libs\Zimbra\Components\Api\Soap\Interf
  */
 class Domain extends AbstractModel
 {
-    const ATTR_ALIAS_TARGET_ID = 'zimbraDomainAliasTargetId';
-    const ATTR_DOMAIN_TYPE     = 'zimbraDomainType';
-    const ATTR_DESCRIPTION     = 'description';
-    const ATTR_DOMAIN_STATUS   = 'zimbraDomainStatus';
-    const ATTR_MAIL_STATUS     = 'zimbraMailStatus';
-    const TYPE_ALIAS           = 'alias';
+    const ATTR_ALIAS_TARGET_ID      = 'zimbraDomainAliasTargetId';
+    const ATTR_DOMAIN_TYPE          = 'zimbraDomainType';
+    const ATTR_DESCRIPTION          = 'description';
+    const ATTR_DOMAIN_STATUS        = 'zimbraDomainStatus';
+    const ATTR_MAIL_STATUS          = 'zimbraMailStatus';
+    const ATTR_MAIL_DOMAIN_QUOTA    = 'zimbraMailDomainQuota';
+    const TYPE_ALIAS                = 'alias';
 
     protected $id;
     protected $name;

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

@@ -22,6 +22,7 @@ use ModulesGarden\Servers\ZimbraEmail\App\Libs\Zimbra\Components\Api\Soap\Servic
 use ModulesGarden\Servers\ZimbraEmail\App\Libs\Zimbra\Components\Api\Soap\Services\Update\ChangePackageCosQuota;
 use ModulesGarden\Servers\ZimbraEmail\App\Libs\Zimbra\Components\Api\Soap\Services\Update\ChangePackageDedicatedCos;
 use ModulesGarden\Servers\ZimbraEmail\App\Libs\Zimbra\Components\Api\Soap\Services\Update\SuspendDomain;
+use ModulesGarden\Servers\ZimbraEmail\App\Libs\Zimbra\Components\Api\Soap\Services\Update\UpdateDomain;
 use ModulesGarden\Servers\ZimbraEmail\App\Libs\Zimbra\Components\Api\Soap\Services\Update\UnsuspendDomain;
 use ModulesGarden\Servers\ZimbraEmail\App\Libs\Zimbra\Components\Api\Soap\Services\Update\UpdateAccount;
 use ModulesGarden\Servers\ZimbraEmail\App\Libs\Zimbra\Components\Api\Soap\Services\Update\UpdateAccountCosQuota;

+ 7 - 2
app/Libs/Zimbra/Components/Api/Soap/Services/Create/CreateAccount.php

@@ -17,6 +17,7 @@ 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\Account;
 use ModulesGarden\Servers\ZimbraEmail\App\Libs\Zimbra\Components\Api\Soap\Traits\ProductManagerHandler;
+use ModulesGarden\Servers\ZimbraEmail\Core\Helper\ConfigOptionsHelper;
 
 class CreateAccount extends ApiService
 {
@@ -50,7 +51,7 @@ class CreateAccount extends ApiService
         /**
          * check full usages of domains
          */
-        $maxDomainQuota = $this->productManager->get('domainMaxSize');
+        $maxDomainQuota = $this->productManager->get('domainMaxSize') * Size::B_TO_GB;
         $usages = $this->api->repository()->accounts->getFullUsages($this->formData['domain']);
 
         if($maxDomainQuota !== Size::UNLIMITED && $usages >= $maxDomainQuota)
@@ -63,7 +64,11 @@ class CreateAccount extends ApiService
          *
          * Check if accounts limit has been reached
          */
-        $accountLimit = $this->productManager->get('acc_limit');
+        $hosting = $this->productManager->getHosting();
+        $configOption = new ConfigOptionsHelper;
+        $acc_addObj = $configOption->getConfigurableOption($hosting->id, 'acc_add');
+        $acc_add = $acc_addObj->qty ? $acc_addObj->qty : 0;
+        $accountLimit = $this->productManager->get('acc_base') + $acc_add;
         $mailBoxes = $this->getMailboxes();
 
         if(count($mailBoxes) >= $accountLimit && $accountLimit !== ProductParams::SIZE_UNLIMITED && 'editAccountForm' !== $this->getRequestValue('loadData'))

+ 1 - 1
app/Libs/Zimbra/Components/Api/Soap/Services/Create/CreateAccountAlias.php

@@ -28,7 +28,7 @@ class CreateAccountAlias extends ApiService
         $limit = $this->productManager->get(ProductParams::ALIAS_LIMIT);
         $createdAlias = $this->api->repository()->accounts->getAccountAliasesByDomainName($this->formData['domain']);
 
-        if(count($createdAlias) >= $limit)
+        if(count($createdAlias) >= $limit && $limit !== ProductParams::SIZE_UNLIMITED)
         {
             $this->setError('Account alias limit has been reached');
             return false;

+ 61 - 2
app/Libs/Zimbra/Components/Api/Soap/Services/Create/CreateDomain.php

@@ -2,9 +2,12 @@
 
 namespace ModulesGarden\Servers\ZimbraEmail\App\Libs\Zimbra\Components\Api\Soap\Services\Create;
 
-
+use ModulesGarden\Servers\ZimbraEmail\App\Enums\Size;
 use ModulesGarden\Servers\ZimbraEmail\App\Libs\Zimbra\Components\Api\Soap\Interfaces\ApiService;
 use ModulesGarden\Servers\ZimbraEmail\App\Libs\Zimbra\Components\Api\Soap\Models\Domain;
+use ModulesGarden\Servers\ZimbraEmail\App\Libs\Zimbra\Components\Api\Soap\Traits\ProductManagerHandler;
+use ModulesGarden\Servers\ZimbraEmail\Core\Helper\ConfigOptionsHelper;
+use ModulesGarden\Servers\ZimbraEmail\Core\Helper\UpdateLimit;
 
 /**
  *
@@ -16,6 +19,8 @@ use ModulesGarden\Servers\ZimbraEmail\App\Libs\Zimbra\Components\Api\Soap\Models
  */
 class CreateDomain extends ApiService
 {
+    use ProductManagerHandler;
+    use \ModulesGarden\Servers\ZimbraEmail\App\Traits\HostingService;
 
     /**
      * @return mixed|void
@@ -25,8 +30,62 @@ class CreateDomain extends ApiService
         /**
          * prepare model
          */
+        $hosting = $this->productManager->getHosting();
+        $serviceID = $hosting->id;
+        $configOption = new ConfigOptionsHelper;
+        $acc_base = $this->productManager->get('acc_base') ? $this->productManager->get('acc_base') : 0;
+        if(isset($this->formData['configoptions']['acc_add']) && isset($this->formData['configoptions']['acc_new'])) {
+            $acc_add = $this->formData['configoptions']['acc_add'];
+            $acc_new = $this->formData['configoptions']['acc_new'];
+            $acc_add = $acc_add + $acc_new;
+            $acc_new = 0;
+            $accountLimit = $acc_base + $acc_add;
+            if (($this->productManager->get('acc_limit') > 0) && ($accountLimit > $this->productManager->get('acc_limit'))) {
+                $acc_add = $this->productManager->get('acc_limit') - $acc_base;
+                $accountLimit = $this->productManager->get('acc_limit');
+            }
+            $acc_addObj = $configOption->getConfigurableOption($serviceID, 'acc_add');
+            if(isset($acc_addObj->id)) {
+                $configOption->updateConfigurableOption($acc_addObj->id, ['qty' => $acc_add]);
+            }
+            $acc_newObj = $configOption->getConfigurableOption($serviceID, 'acc_new');
+            if(isset($acc_newObj->id)) {
+                $configOption->updateConfigurableOption($acc_newObj->id, ['qty' => $acc_new]);
+            }
+        } else {
+            $accountLimit = $acc_base;
+        }
         $domain = new Domain();
         $domain->setName($this->formData['domain']);
+        $domainBaseSize = $this->productManager->get('domainBaseSize') ? $this->productManager->get('domainBaseSize') : 0;
+        if(isset($this->formData['configoptions']['domainAddSize']) && isset($this->formData['configoptions']['domainNewSize'])) {
+            $domainAddSize = $this->formData['configoptions']['domainAddSize'];
+            $domainNewSize = $this->formData['configoptions']['domainNewSize'];
+            $domainAddSize = $domainAddSize + $domainNewSize;
+            $domainNewSize = 0;
+            $domainSize = $domainBaseSize + $domainAddSize;
+            if (($this->productManager->get('domainMaxSize') > 0) && ($domainSize > $this->productManager->get('domainMaxSize'))) {
+                $domainMaxSize = $this->productManager->get('domainMaxSize');
+                $domainAddSize = $domainMaxSize - $domainBaseSize;
+                $domainSize = $domainBaseSize + $domainAddSize;
+            }
+            $domainAddSizeObj = $configOption->getConfigurableOption($serviceID, 'domainAddSize');
+            if(isset($domainAddSizeObj->id)) {
+                $configOption->updateConfigurableOption($domainAddSizeObj->id, ['qty' => $domainAddSize]);
+            }
+            $domainNewSizeObj = $configOption->getConfigurableOption($serviceID, 'domainNewSize');
+            if(isset($domainNewSizeObj->id)) {
+                $configOption->updateConfigurableOption($domainNewSizeObj->id, ['qty' => $domainNewSize]);
+            }
+        } else {
+            $domainSize = $domainBaseSize;
+        }
+        $updateLimit = new UpdateLimit;
+        $updateLimit->updateDiskLimit($serviceID, $domainSize * 1024);
+        $updateLimit->updateBWLimit($serviceID, $accountLimit);
+        $domain->setAttrs([
+            Domain::ATTR_MAIL_DOMAIN_QUOTA  => $domainSize * Size::B_TO_GB,
+        ]);
 
         /**
          * API request
@@ -44,4 +103,4 @@ class CreateDomain extends ApiService
 
         return $result;
     }
-}
+}

+ 1 - 1
app/Libs/Zimbra/Components/Api/Soap/Services/Create/CreateDomainAlias.php

@@ -50,7 +50,7 @@ class CreateDomainAlias extends ApiService
          */
         $domainAliases = $this->api->repository()->domains->getAliases($this->formData['domain']);
 
-        if(count($domainAliases) >= $domainAliasesLimit)
+        if(count($domainAliases) >= $domainAliasesLimit && $domainAliasesLimit !== ProductParams::SIZE_UNLIMITED)
         {
             $this->setError('Domain aliases limit has been reached');
             return false;

+ 69 - 5
app/Libs/Zimbra/Components/Api/Soap/Services/Update/ChangePackage.php

@@ -4,10 +4,14 @@ namespace ModulesGarden\Servers\ZimbraEmail\App\Libs\Zimbra\Components\Api\Soap\
 
 
 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\Zimbra\Components\Api\Soap\Interfaces\ApiService;
 use ModulesGarden\Servers\ZimbraEmail\App\Libs\Zimbra\Components\Api\Soap\Models\Account;
+use ModulesGarden\Servers\ZimbraEmail\App\Libs\Zimbra\Components\Api\Soap\Models\Domain;
 use ModulesGarden\Servers\ZimbraEmail\App\Libs\Zimbra\Components\Api\Soap\Traits\ProductManagerHandler;
+use ModulesGarden\Servers\ZimbraEmail\Core\Helper\ConfigOptionsHelper;
+use ModulesGarden\Servers\ZimbraEmail\Core\Helper\UpdateLimit;
 
 /**
  *
@@ -20,6 +24,7 @@ use ModulesGarden\Servers\ZimbraEmail\App\Libs\Zimbra\Components\Api\Soap\Traits
 class ChangePackage extends ApiService
 {
     use ProductManagerHandler;
+    use \ModulesGarden\Servers\ZimbraEmail\App\Traits\HostingService;
 
     public function isValid()
     {
@@ -34,9 +39,30 @@ class ChangePackage extends ApiService
 
     public function process()
     {
-
+        $serviceID = $this->formData['serviceid'];
+        $configOption = new ConfigOptionsHelper;
         $accounts = $this->api->repository()->accounts->getByDomainName($this->formData['domain']);
-
+        $acc_base = $this->productManager->get('acc_base') ? $this->productManager->get('acc_base') : 0;
+        if(isset($this->formData['configoptions']['acc_add']) && isset($this->formData['configoptions']['acc_new'])) {
+            $acc_add = $this->formData['configoptions']['acc_add'];
+            $acc_new = $this->formData['configoptions']['acc_new'];
+            $acc_add = $acc_add + $acc_new;
+            $acc_new = 0;
+            $accountLimit = $acc_base + $acc_add;
+            if (($this->productManager->get('acc_limit') > 0) && ($accountLimit > $this->productManager->get('acc_limit'))) {
+                $acc_add = $this->productManager->get('acc_limit') - $acc_base;
+            }
+            $acc_addObj = $configOption->getConfigurableOption($serviceID, 'acc_add');
+            if(isset($acc_addObj->id)) {
+                $configOption->updateConfigurableOption($acc_addObj->id, ['qty' => $acc_add]);
+            }
+            $acc_newObj = $configOption->getConfigurableOption($serviceID, 'acc_new');
+            if(isset($acc_newObj->id)) {
+                $configOption->updateConfigurableOption($acc_newObj->id, ['qty' => $acc_new]);
+            }
+        } else {
+            $accountLimit = $acc_base;
+        }
         foreach($accounts as $account)
         {
             /* @var $account Account*/
@@ -52,9 +78,47 @@ class ChangePackage extends ApiService
                 }
             }
         }
+        $domain = $this->api->repository()->domains->getByName($this->formData['domain']);
+        if(!$domain) {
+            throw new \Exception($this->api->repository()->domains->getError());
+            return false;
+        }
+        $domainBaseSize = $this->productManager->get('domainBaseSize') ? $this->productManager->get('domainBaseSize') : 0;
+        if(isset($this->formData['configoptions']['domainAddSize']) && isset($this->formData['configoptions']['domainNewSize'])) {
+            $domainAddSize = $this->formData['configoptions']['domainAddSize'];
+            $domainNewSize = $this->formData['configoptions']['domainNewSize'];
+            $domainAddSize = $domainAddSize + $domainNewSize;
+            $domainNewSize = 0;
+            $domainSize = $domainBaseSize + $domainAddSize;
+            if (($this->productManager->get('domainMaxSize') > 0) && ($domainSize > $this->productManager->get('domainMaxSize'))) {
+                $domainMaxSize = $this->productManager->get('domainMaxSize');
+                $domainAddSize = $domainMaxSize - $domainBaseSize;
+                $domainSize = $domainBaseSize + $domainAddSize;
+            }
+            $domainAddSizeObj = $configOption->getConfigurableOption($serviceID, 'domainAddSize');
+            if(isset($domainAddSizeObj->id)) {
+                $configOption->updateConfigurableOption($domainAddSizeObj->id, ['qty' => $domainAddSize]);
+            }
+            $domainNewSizeObj = $configOption->getConfigurableOption($serviceID, 'domainNewSize');
+            if(isset($domainNewSizeObj->id)) {
+                $configOption->updateConfigurableOption($domainNewSizeObj->id, ['qty' => $domainNewSize]);
+            }
+        } else {
+            $domainSize = $this->productManager->get('domainBaseSize');
+        }
+        $updateLimit = new UpdateLimit;
+        $updateLimit->updateDiskLimit($serviceID, $domainSize * 1024);
+        $updateLimit->updateBWLimit($serviceID, $accountLimit);
+        $domain->setAttrs([
+            Domain::ATTR_MAIL_DOMAIN_QUOTA  => $domainSize * Size::B_TO_GB,
+        ]);
+        $response = $this->api->domain->update($domain);
+        if(!$response)
+        {
+            throw new \Exception($this->api->domain->getError());
+            return false;
+        }
 
         return true;
     }
-
-
-}
+}

+ 13 - 1
app/Services/ConfigurableOptions/Strategy/Types/BasedOptions.php

@@ -19,7 +19,11 @@ class BasedOptions extends AbstractOptions
      */
     public function initContent()
     {
-        $option  = new Option('acc_limit', 'Email Accounts Limit', TypeConstans::QUANTITY);
+        $option  = new Option('acc_add', 'Email Accounts Additional', TypeConstans::QUANTITY);
+        $option->addSubOption(new SubOption('1', 'Email Account'));
+        $this->addOption($option);
+
+        $option  = new Option('acc_new', 'Email Accounts Increase', TypeConstans::QUANTITY);
         $option->addSubOption(new SubOption('1', 'Email Account'));
         $this->addOption($option);
 
@@ -39,6 +43,14 @@ class BasedOptions extends AbstractOptions
         $option->addSubOption(new SubOption('1', 'Domain Alias'));
         $this->addOption($option);
 
+        $option  = new Option('domainAddSize', 'Domain Space Additional', TypeConstans::QUANTITY);
+        $option->addSubOption(new SubOption('1', 'GB'));
+        $this->addOption($option);
+
+        $option  = new Option('domainNewSize', 'Domain Space Increase', TypeConstans::QUANTITY);
+        $option->addSubOption(new SubOption('1', 'GB'));
+        $this->addOption($option);
+
         return $this;
     }
 }

+ 12 - 2
app/UI/Admin/ProductConfiguration/Pages/Sections/ZimbraSettings.php

@@ -47,6 +47,12 @@ class ZimbraSettings extends BoxSectionExtended implements AdminArea
         $field->setDescription('description');
         $leftSection->addField($field);
 
+        $field = new ExtendedInputField('acc_base');
+        $field->setFieldType(ExtendedInputField::TYPE_NUMBER);
+        $field->addHtmlAttribute('min', Size::UNLIMITED);
+        $field->setDescription('description');
+        $leftSection->addField($field);
+
         $field = new ExtendedInputField('alias_limit');
         $field->setFieldType(ExtendedInputField::TYPE_NUMBER);
         $field->addHtmlAttribute('min', Size::UNLIMITED);
@@ -66,9 +72,7 @@ class ZimbraSettings extends BoxSectionExtended implements AdminArea
         $field->setDescription('description');
         $leftSection->addField($field);
 
-
         return $leftSection;
-
     }
 
     /**
@@ -103,6 +107,12 @@ class ZimbraSettings extends BoxSectionExtended implements AdminArea
         $field->setDescription('description');
         $right->addField($field);
 
+        $field = new ExtendedInputField('domainBaseSize');
+        $field->setFieldType(ExtendedInputField::TYPE_NUMBER);
+        $field->addHtmlAttribute('min', Size::UNLIMITED);
+        $field->setDescription('description');
+        $right->addField($field);
+
         return $right;
     }
 }

+ 4 - 0
app/UI/Admin/ProductConfiguration/Providers/ProductConfigurationDataProvider.php

@@ -31,6 +31,7 @@ class ProductConfigurationDataProvider extends BaseDataProvider implements Admin
 
     const FORM_DATA = [
             'acc_limit',
+            'acc_base',
             'alias_limit',
             'cos_name',
             'login_link',
@@ -39,6 +40,7 @@ class ProductConfigurationDataProvider extends BaseDataProvider implements Admin
             'domain_alias_limit',
             'dist_list_limit',
             'domainMaxSize',
+            'domainBaseSize',
             'cos',
             'ca_emailAccountPage',
             'ca_distributionListPage',
@@ -98,6 +100,7 @@ class ProductConfigurationDataProvider extends BaseDataProvider implements Admin
     {
         /* default data */
         $this->data['acc_limit']          = Size::DEFAULT_ACC_LIMIT;
+        $this->data['acc_base']           = Size::DEFAULT_ACC_BASE;
         $this->data['acc_size']           = Size::DEFAULT_ACC_SIZE;
         $this->data['alias_limit']        = Size::DEFAULT_ALIAS_LIMIT;
         $this->data['domain_alias_limit'] = Size::DEFAULT_DOMAIN_ALIAS_LIMIT;
@@ -105,6 +108,7 @@ class ProductConfigurationDataProvider extends BaseDataProvider implements Admin
         $this->data['dist_list_limit']    = Size::DEFAULT_DIST_ALIAS_LIMIT;
         $this->data['login_link']         = Zimbra::DEFAULT_LOGIN_LINK;
         $this->data['domainMaxSize']      = Size::UNLIMITED;
+        $this->data['domainBaseSize']     = Size::UNLIMITED;
 
         /* available class of services*/
         $this->availableValues['cos_name'] = [

+ 57 - 0
core/Helper/ConfigOptionsHelper.php

@@ -0,0 +1,57 @@
+<?php
+
+namespace ModulesGarden\Servers\ZimbraEmail\Core\Helper;
+
+use ModulesGarden\Servers\ZimbraEmail\Core\FileReader\Reader;
+use ModulesGarden\Servers\ZimbraEmail\Core\ServiceLocator;
+use WHMCS\Database\Capsule;
+
+/**
+ * Autometes some of database queries
+ *
+ * @author
+ */
+class ConfigOptionsHelper
+{
+    
+    /**
+     * Helper to perform Configurable Options queries for module
+     *
+     * @param int $productID
+     * @param string $optionName
+     * @return Object
+     */
+    public function getConfigurableOption(int $productID, string $optionName) {
+        $configOption = Capsule::table('tblproductconfigoptions')
+            ->join('tblhostingconfigoptions', 'tblproductconfigoptions.id', '=', 'tblhostingconfigoptions.configid')
+            ->where('tblhostingconfigoptions.relid', '=', $productID)
+            ->where('tblproductconfigoptions.optionname', 'like', $optionName.'%')
+            ->select('*')
+            ->get();
+        return $configOption->pull(0);
+    }
+    /**
+     * Helper to perform Configurable Options queries for module
+     *
+     * @param int $optionID
+     * @param array $optionValues
+     * @return bool
+     */
+    public function updateConfigurableOption(int $optionID, array $optionValues) {
+        try {
+            $updateOption = Capsule::table('tblhostingconfigoptions')
+                ->where('id', $optionID)
+                ->update($optionValues);
+        } catch (\Exception $e) {
+            logModuleCall(
+                'zimbraEmail',
+                __FUNCTION__,
+                $updateOption,
+                'Error: could not update option ' . $optionID .' in database.',
+                $e->getMessage()
+            );
+            return false;
+        }
+        return true;
+    }
+}

+ 93 - 0
core/Helper/UpdateLimit.php

@@ -0,0 +1,93 @@
+<?php
+
+namespace ModulesGarden\Servers\ZimbraEmail\Core\Helper;
+
+use ModulesGarden\Servers\ZimbraEmail\Core\FileReader\Reader;
+use ModulesGarden\Servers\ZimbraEmail\Core\ServiceLocator;
+use WHMCS\Database\Capsule;
+
+/**
+ * Autometes some of database queries
+ *
+ * @author
+ */
+class UpdateLimit
+{
+    
+    /**
+     * Helper to perform DiskLimit queries for module
+     *
+     * @param int $serviceID
+     * @return Object
+     */
+    public function getDiskLimit(int $serviceID) {
+        $diskLimit = Capsule::table('tblhosting')
+            ->where('id', '=', $serviceID)
+            ->select('disklimit')
+            ->get();
+        return $diskLimit->pull(0);
+    }
+    /**
+     * Helper to perform DiskLimit queries for module
+     *
+     * @param int $serviceID
+     * @return Object
+     */
+    public function getBWLimit(int $serviceID) {
+        $BWLimit = Capsule::table('tblhosting')
+            ->where('id', '=', $serviceID)
+            ->select('bwlimit')
+            ->get();
+        return $BWLimit->pull(0);
+    }
+    /**
+     * Helper to perform DiskLimit queries for module
+     *
+     * @param int $serviceID
+     * @param int $diskLimitValue
+     * @return bool
+     */
+    public function updateDiskLimit(int $serviceID, int $diskLimitValue) {
+        try {
+            $diskLimit = Capsule::table('tblhosting')
+                ->where('id', $serviceID)
+                ->update(['disklimit' => $diskLimitValue]);
+        } catch (\Exception $e) {
+            logModuleCall(
+                'zimbraEmail',
+                __FUNCTION__,
+                $diskLimit,
+                'Error: could not update disklimit for ' . $serviceID .' in database.',
+                $e->getMessage()
+            );
+            return false;
+        }
+        return true;
+    }
+    /**
+     * Helper to perform BWLimit queries for module
+     *
+     * @param int $serverID
+     * @param string $domainName
+     * @param int $usageUpdateValue
+     * @return bool
+     */
+    public function updateBWLimit(int $serviceID, int $bwLimitValue) {
+        try {
+            $usage = Capsule::table('tblhosting')
+                ->where('server', $serverId)
+                ->where('domain', $domainName)
+                ->update(['bwlimit' => $bwLimitValue]);
+        } catch (\Exception $e) {
+            logModuleCall(
+                'zimbraEmail',
+                __FUNCTION__,
+                $usage,
+                'Error: could not update bwlimit for ' . $serviceID .' in database.',
+                $e->getMessage()
+            );
+            return false;
+        }
+        return true;
+    }
+}

+ 2 - 1
core/Http/Response.php

@@ -233,7 +233,8 @@ class Response extends SymfonyRespose
     
     public function returnClientProvisioning($vars, $path, $fileName)
     {
-        $templateVarName = ($this->getRequestValue('a', false) === 'management') ? 'tabOverviewReplacementTemplate' : 'templatefile';          
+//        $templateVarName = ($this->getRequestValue('a', false) === 'management') ? 'tabOverviewReplacementTemplate' : 'templatefile';          
+        $templateVarName = 'tabOverviewReplacementTemplate';          
 
         return [
             $templateVarName => str_replace(\ModulesGarden\Servers\ZimbraEmail\Core\ModuleConstants::getTemplateDir() . DIRECTORY_SEPARATOR,

+ 8 - 2
langs/english.php

@@ -107,6 +107,9 @@ $_LANG['mainContainer']['configForm']['zimbraSettings']['zimbraSettings'] = 'Zim
 $_LANG['mainContainer']['configForm']['zimbraSettings']['leftSide']['acc_limit']['acc_limit'] = 'Default Email Accounts Limit';
 $_LANG['mainContainer']['configForm']['zimbraSettings']['leftSide']['acc_limit']['description'] = 'Type -1 for unlimited (used when the configurable option is not provided).';
 
+$_LANG['mainContainer']['configForm']['zimbraSettings']['leftSide']['acc_base']['acc_base'] = 'Inclusive Email Accounts';
+$_LANG['mainContainer']['configForm']['zimbraSettings']['leftSide']['acc_base']['description'] = 'How many Email Accounts are inlcuded?';
+
 $_LANG['mainContainer']['configForm']['zimbraSettings']['leftSide']['alias_limit']['alias_limit'] = 'Default Email Aliases Limit';
 $_LANG['mainContainer']['configForm']['zimbraSettings']['leftSide']['alias_limit']['description'] = 'Type -1 for unlimited (used when the configurable option is not provided).';
 
@@ -128,8 +131,11 @@ $_LANG['mainContainer']['configForm']['zimbraSettings']['rightSide']['domain_ali
 $_LANG['mainContainer']['configForm']['zimbraSettings']['rightSide']['dist_list_limit']['dist_list_limit'] = 'Default Distribution Lists Limit';
 $_LANG['mainContainer']['configForm']['zimbraSettings']['rightSide']['dist_list_limit']['description'] = 'Type -1 for unlimited (used when the configurable option is not provided).';
 
-$_LANG['mainContainer']['configForm']['zimbraSettings']['rightSide']['domainMaxSize']['domainMaxSize'] = 'Domain Max Size (MB)';
-$_LANG['mainContainer']['configForm']['zimbraSettings']['rightSide']['domainMaxSize']['description'] = 'It is a sum off all accounts within a domain. Type -1 for unlimited. Note that when the limit is exceeded, the possibility to add new mailboxes is blocked.';
+$_LANG['mainContainer']['configForm']['zimbraSettings']['rightSide']['domainMaxSize']['domainMaxSize'] = 'Domain Max Size (GB)';
+$_LANG['mainContainer']['configForm']['zimbraSettings']['rightSide']['domainMaxSize']['description'] = 'Type -1 for unlimited (used when the configurable option is not provided).';
+
+$_LANG['mainContainer']['configForm']['zimbraSettings']['rightSide']['domainBaseSize']['domainBaseSize'] = 'Domain inclusive Size (GB)';
+$_LANG['mainContainer']['configForm']['zimbraSettings']['rightSide']['domainBaseSize']['description'] = 'Type -1 for unlimited (used when the configurable option is not provided).';
 
 $_LANG['mainContainer']['configForm']['essentialFeatures']['essentialFeatures'] = 'Essential Features';
 

+ 319 - 11
templates/client/default/controlers/main.tpl

@@ -1,18 +1,326 @@
-<div class="mg-wrapper body" data-target=".body" data-spy="scroll" data-twttr-rendered="true">
-
-    <link href="https://fonts.googleapis.com/css?family=Roboto:300,400,500,700" rel="stylesheet">
-    <link rel="stylesheet" href="{$assetsURL}/css/layers-ui.css">
-    <link rel="stylesheet" href="{$assetsURL}/css/mg_styles.css">
-    {if $isCustomModuleCss}
-        <link rel="stylesheet" href="{$customAssetsURL}/css/module_styles.css">
+{if $currentPageName == 'Home'}
+    {if $modulecustombuttonresult}
+        {if $modulecustombuttonresult == "success"}
+            {include file="$template/includes/alert.tpl" type="success" msg=$LANG.moduleactionsuccess textcenter=true idname="alertModuleCustomButtonSuccess"}
+        {else}
+            {include file="$template/includes/alert.tpl" type="error" msg=$LANG.moduleactionfailed|cat:' ':$modulecustombuttonresult textcenter=true idname="alertModuleCustomButtonFailed"}
+        {/if}
     {/if}
-
-    <div class="full-screen-module-container" id="layers">
-        <div class="lu-app">
-            {$content}
+    {if $pendingcancellation}
+        {include file="$template/includes/alert.tpl" type="error" msg=$LANG.cancellationrequestedexplanation textcenter=true idname="alertPendingCancellation"}
+    {/if}
+    {if $unpaidInvoice}
+        <div class="alert alert-{if $unpaidInvoiceOverdue}danger{else}warning{/if}" id="alert{if $unpaidInvoiceOverdue}Overdue{else}Unpaid{/if}Invoice">
+            <div class="pull-right">
+                <a href="viewinvoice.php?id={$unpaidInvoice}" class="btn btn-xs btn-default">
+                    {lang key='payInvoice'}
+                </a>
+            </div>
+            {$unpaidInvoiceMessage}
         </div>
+    {/if}
+    <div class="tab-content margin-bottom">
+        <div class="tab-pane fade show active" id="tabOverview">
+            {if $tplOverviewTabOutput}
+                    {$tplOverviewTabOutput}
+            {else}
+            <div class="section">
+                <div class="product-details">
+                    <div class="row row-eq-height row-eq-height-sm">
+                        <div class="col-md-6">
+                            <div class="product-holder product-status-{$rawstatus|strtolower}">
+                                <div class="product-content">
+                                    <div class="product-image">
+                                        <div class="feature-icon">
+                                            <img src="https://portal.thurdata.ch/templates/croster/assets/images/zimbra-only-logo.svg" class="img-fluid">
+                                        </div>
+                                    </div>
+                                    <h4><small>{$groupname}</small> - {$product}</h4>
+                                    <div class="status-sticker-wrapper">
+                                        <div class="status-sticker product-status-{$rawstatus|strtolower}">
+                                            {$status}
+                                        </div>
+                                    </div>
+                                </div>
+                            </div>
+                        </div>
+                        <div class="col-md-6">
+                            <div class="product-info">
+                                <ul class="list-info list-v">
+                                    <li>
+                                        <span class="list-heading">{$LANG.clientareahostingregdate}</span>
+                                        <span class="list-text">{$regdate}</span>
+                                    </li>
+                                    {if $firstpaymentamount neq $recurringamount}
+                                        <li>
+                                            <span class="list-heading">{$LANG.firstpaymentamount}</span>
+                                            <span class="list-text">{$firstpaymentamount}</span>
+                                        </li>
+                                    {/if}
+                                    {if $billingcycle != $LANG.orderpaymenttermonetime && $billingcycle != $LANG.orderfree}
+                                        <li>
+                                            <span class="list-heading">{$LANG.recurringamount}</span>
+                                            <span class="list-text">{$recurringamount}</span>
+                                        </li>
+                                    {/if}
+                                    <li>
+                                            <span class="list-heading">{$LANG.orderbillingcycle}</span>
+                                            <span class="list-text">{$billingcycle}</span>
+                                    </li>
+                                    {if $nextduedate == '-'}{else}
+                                        <li>
+                                            <span class="list-heading">{$LANG.clientareahostingnextduedate}</span>
+                                            <span class="list-text">{$nextduedate}</span>
+                                        </li>
+                                    {/if}
+                                    <li>
+                                        <span class="list-heading">{$LANG.orderpaymentmethod}</span>
+                                        <span class="list-text">{$paymentmethod}</span>
+                                    </li>
+                                </ul>
+                            </div>
+                        </div>
+                    </div>
+                </div>
+            </div>
+            {*
+                {if $showcancelbutton || $packagesupgrade}
+                    <div class="row">
+                        {if $packagesupgrade}
+                            <div class="col-xs-{if $showcancelbutton}6{else}12{/if}">
+                                <a href="upgrade.php?type=package&amp;id={$id}" class="btn btn-block btn-primary">{$LANG.upgrade}</a>
+                            </div>
+                        {/if}
+                        {if $showcancelbutton}
+                            <div class="col-xs-{if $packagesupgrade}6{else}12{/if}">
+                                <a href="clientarea.php?action=cancel&amp;id={$id}" class="btn btn-block btn-danger {if $pendingcancellation}disabled{/if}">{if $pendingcancellation}{$LANG.cancellationrequested}{else}{$LANG.clientareacancelrequestbutton}{/if}</a>
+                            </div>
+                        {/if}
+                    </div>
+                {/if}
+            *}
+            {if $systemStatus == 'Active'}
+                {foreach $hookOutput as $output}
+                    <div class="section">
+                        <div>
+                            {$output}
+                        </div>
+                        <div class=" clearfix"></div>
+                    </div>
+                {/foreach}
+                {if $domain || $moduleclientarea || $configurableoptions || $customfields || $lastupdate}
+                    <div class="section">
+                        <div class="card panel panel-tabs">
+                            <div class="card-header">
+                                <ul class="nav nav-pills card-header-pills flex-column flex-md-row">
+                                    {if $domain}
+                                        <li class="nav-item">
+                                            <a href="#domain" data-toggle="tab" class="nav-link active"><i class="fas fa-globe fa-fw"></i> {lang key='manage'}</a>
+                                        </li>
+                                    {/if}
+                                    {if $configurableoptions}
+                                        <li class="nav-item">
+                                            <a href="#configoptions" data-toggle="tab" class="nav-link{if !$domain && !$moduleclientarea} active{/if}"><i class="fas fa-cubes fa-fw"></i>Details</a>
+                                        </li>
+                                    {/if}
+                                    {if $metricStats}
+                                        <li class="nav-item">
+                                            <a href="#metrics" data-toggle="tab" class="nav-link{if !$domain && !$moduleclientarea && !$configurableoptions} active{/if}"><i class="fas fa-chart-line fa-fw"></i> {lang key='metrics.title'}</a>
+                                        </li>
+                                    {/if}
+                                    {if $customfields}
+                                        <li class="nav-item">
+                                            <a href="#additionalinfo" data-toggle="tab" class="nav-link{if !$domain && !$moduleclientarea && !$metricStats && !$configurableoptions} active{/if}"><i class="fas fa-info fa-fw"></i>Zugangsdaten</a>
+                                        </li>
+                                    {/if}
+                                    {if $lastupdate}
+                                        <li class="nav-item">
+                                            <a href="#resourceusage" data-toggle="tab" class="nav-link{if !$domain && !$moduleclientarea && !$configurableoptions && !$customfields} active{/if}"><i class="fas fa-inbox fa-fw"></i> {lang key='resourceUsage'}</a>
+                                        </li>
+                                    {/if}
+                                </ul>
+                            </div>
+                            <div class="card-body">
+                                <div class="tab-content">
+                                    {if $configurableoptions}
+                                        <div class="tab-pane fade{if !$domain && !$moduleclientarea} show active{/if}" role="tabpanel" id="configoptions">
+                                        <table width="100%" cellspacing="0" cellpadding="0" class="frame">
+                                            <tr>
+                                            <td>
+                                                <table width="100%" border="0" cellpadding="10" cellspacing="0" class="table table-striped table-framed">
+                                                <tr>
+                                                    <td align='left'>E-Mail Speicher inklusive</td>
+                                                    <td align="left">{$domainBaseSize} GB</td>
+                                                </tr>
+                                                <tr>
+                                                    <td align='left'>E-Mail Speicher zugebucht</td>
+                                                    <td align="left">{$domainAddSize} GB</td>
+                                                </tr>
+                                                <tr>
+                                                    <td align='left'>E-Mail Accounts inklusive</td>
+                                                    <td align="left">{$acc_base}</td>
+                                                </tr>
+                                                <tr>
+                                                    <td align='left'>E-Mail Accounts zugebucht</td>
+                                                    <td align="left">{$acc_add}</a></td>
+                                                </tr>
+                                                </table>
+                                            </td>
+                                            </tr>
+                                        </table>
+                                        </div>
+                                    {/if}
+                                    {if $metricStats}
+                                        <div class="tab-pane fade{if !$domain && !$moduleclientarea && !$configurableoptions} show active{/if}" role="tabpanel" id="metrics">
+                                            <p>{lang key='metrics.explanation'}</p>
+                                            <table class="table table-striped mb-1 table-solid-bottom-border-light-gray">
+                                                <tr>
+                                                    <th>{lang key='metrics.metric'}</th>
+                                                    <th>{lang key='metrics.currentUsage'}</th>
+                                                    <th>{lang key='metrics.pricing'}</th>
+                                                    <th>{lang key='metrics.lastUpdated'}</th>
+                                                </tr>
+                                                {foreach $metricStats as $metric}
+                                                    <tr>
+                                                        <td>{$metric.displayName}</td>
+                                                        <td>{$metric.currentValue|round:1}</td>
+                                                        <td>
+                                                            {if count($metric.pricing) > 1}
+                                                                {lang key='metrics.startingFrom'} {$metric.lowestPrice} / {if $metric.unitName}{$metric.unitName}{else}{lang key='metrics.unit'}{/if}
+                                                                <br>
+                                                                <button type="button" class="btn btn-default btn-xs" data-toggle="modal" data-target="#modalMetricPricing-{$metric.systemName}">
+                                                                    {lang key='metrics.viewPricing'}
+                                                                </button>
+                                                            {elseif count($metric.pricing) == 1}
+                                                                {$metric.lowestPrice} / {if $metric.unitName}{$metric.unitName}{else}{lang key='metrics.unit'}{/if}
+                                                                {if $metric.includedQuantity > 0} ({$metric.includedQuantity|round:1} {lang key='metrics.includedNotCounted'}){/if}
+                                                            {else}
+                                                                &mdash;
+                                                            {/if}
+                                                            {include file="$template/usagebillingpricing.tpl"}
+                                                        </td>
+                                                        <td>{if is_string($metric.lastUpdated)}{$metric.lastUpdated}{else}{$metric.lastUpdated->diffForHumans()}{/if}</td>
+                                                    </tr>
+                                                {/foreach}
+                                            </table>
+                                        </div>
+                                    {/if}
+                                    {if $domain}
+                                        <div class="tab-pane fade show active" role="tabpanel" id="domain">
+                                            <table width="100%" cellspacing="0" cellpadding="0" class="frame">
+                                                <tr>
+                                                    <td align='left'>Maildomain</td>
+                                                    <td align="left">{$domain}</td>
+                                                </tr>
+                                                <tr>
+                                                    <td colspan=2 align='left'><hr></td>
+                                                </tr>
+                                                <tr>
+                                                    <td colspan=2 align='center'>
+                                                        <div class="mg-wrapper body" data-target=".body" data-spy="scroll" data-twttr-rendered="true">
+                                                            <link href="https://fonts.googleapis.com/css?family=Roboto:300,400,500,700" rel="stylesheet">
+                                                            <link rel="stylesheet" href="{$assetsURL}/css/layers-ui.css">
+                                                            <link rel="stylesheet" href="{$assetsURL}/css/mg_styles.css">
+                                                            {if $isCustomModuleCss}
+                                                                <link rel="stylesheet" href="{$customAssetsURL}/css/module_styles.css">
+                                                            {/if}
+                                                            <div class="full-screen-module-container" id="layers">
+                                                                <div class="lu-app">
+                                                                    {$content}
+                                                                </div>
+                                                            </div>
+                                                        </div>
+                                                    </td>
+                                                </tr>
+                                            </table>
+                                        </div>
+                                    {/if}
+                                    {if $customfields}
+                                        <div class="tab-pane fade{if !$domain && !$moduleclientarea && !$configurableoptions && !$metricStats} show active{/if}" role="tabpanel" id="additionalinfo">
+                                        </div>
+                                    {/if}
+                                    {if $lastupdate}
+                                        <div class="tab-pane fade" role="tabpanel" id="resourceusage" align="center">
+                                            <table width="100%" cellspacing="0" cellpadding="0" class="frame">
+                                                <tr>
+                                                    <td align="center">
+                                                        <div class="col-sm-10">
+                                                                <h4>Accounts %</h4>
+                                                                <input type="text" value="{$bwpercent|substr:0:-1}" class="dial-usage" data-width="100" data-height="100" data-min="0" data-readOnly="true" />
+                                                                <p>{$bwusage} / {$bwlimit}</p>
+                                                        </div>
+                                                        <div class="clearfix"></div>
+                                                        <p class="text-muted">{lang key='clientarealastupdated'}: {$lastupdate}</p>
+                                                    </td>
+                                                    <td align="center">
+                                                        <div class="col-sm-10">
+                                                                <h4>{lang key='diskSpace'} %</h4>
+                                                                <input type="text" value="{$diskpercent|substr:0:-1}" class="dial-usage" data-width="100" data-height="100" data-min="0" data-readOnly="true" />
+                                                                <p>{($diskusage / 1024)|round:1} GB / {($disklimit / 1024)|round:1} GB</p>
+                                                        </div>
+                                                        <div class="clearfix"></div>
+                                                        <p class="text-muted">{lang key='clientarealastupdated'}: {$lastupdate}</p>
+                                                    </td>
+                                                </tr>
+                                            </table>
+                                            <script src="{$BASE_PATH_JS}/jquery.knob.js"></script>
+                                            <script>
+                                                jQuery(function() {
+                                                    jQuery(".dial-usage").knob({
+                                                        'format': function(v) {
+                                                            alert(v);
+                                                        }
+                                                    });
+                                                });
+                                            </script>
+                                            <div class="col-xs-{if $showcancelbutton}6{else}12{/if}">
+                                                <a href="upgrade.php?type=configoptions&amp;id={$id}" class="btn btn-block btn-primary">Accounts oder Speicher hinzubuchen</a>
+                                            </div>
+                                        </div>
+                                    {/if}
+                                </div>
+                            </div>
+                        </div>
+                    </div>
+                {/if}
+            {else}
+                <div class="alert-lg no-data">
+                    <div class="icon">
+                        <i class="fas fa-exclamation-triangle"></i>
+                    </div>
+                    <div class="text">
+                        {if $suspendreason}
+                            <strong>{$suspendreason}</strong><br />
+                        {/if}
+                        {$LANG.cPanel.packageNotActive} {$status}.<br />
+                        {if $systemStatus eq "Pending"}
+                            {$LANG.cPanel.statusPendingNotice}
+                        {elseif $systemStatus eq "Suspended"}
+                            {$LANG.cPanel.statusSuspendedNotice}
+                        {/if}
+                    </div>
+                </div>
+            {/if}
+        {/if}
     </div>
 </div>
+{else}
+    <div class="mg-wrapper body" data-target=".body" data-spy="scroll" data-twttr-rendered="true">
+
+        <link href="https://fonts.googleapis.com/css?family=Roboto:300,400,500,700" rel="stylesheet">
+        <link rel="stylesheet" href="{$assetsURL}/css/layers-ui.css">
+        <link rel="stylesheet" href="{$assetsURL}/css/mg_styles.css">
+        {if $isCustomModuleCss}
+            <link rel="stylesheet" href="{$customAssetsURL}/css/module_styles.css">
+        {/if}
+
+        <div class="full-screen-module-container" id="layers">
+            <div class="lu-app">
+                {$content}
+            </div>
+        </div>
+    </div>
+{/if}
 
 {if $isDebug}
     <script type="text/javascript" src="https://unpkg.com/vue"></script>

+ 15 - 8
zimbraEmail.php

@@ -1,6 +1,7 @@
 <?php
 
 use \ModulesGarden\Servers\ZimbraEmail\Core\App\AppContext;
+use \ModulesGarden\Servers\ZimbraEmail\App\Libs\Product\ProductManager;
 
 if (!defined("WHMCS"))
 {
@@ -65,9 +66,7 @@ function ZimbraEmail_TerminateAccount(array $params)
 function ZimbraEmail_ChangePackage(array $params)
 {
     require_once __DIR__ . DIRECTORY_SEPARATOR . 'core' . DIRECTORY_SEPARATOR . 'App' . DIRECTORY_SEPARATOR . 'AppContext.php';
-    
-    
-    
+
     $appContext = new AppContext();    
     
     return $appContext->runApp(__FUNCTION__, $params);
@@ -131,11 +130,17 @@ function ZimbraEmail_ClientArea($params)
 {
     require_once __DIR__ . DIRECTORY_SEPARATOR . 'core' . DIRECTORY_SEPARATOR . 'App' . DIRECTORY_SEPARATOR . 'AppContext.php';
     
-    
-    
-    $appContext = new AppContext();    
-    
-    return $appContext->runApp('clientarea', $params);
+    $appContext = new AppContext();
+    $productManager = new ProductManager;
+    $productManager->loadByHostingId($params['serviceid']);
+    $domainBaseSize = $productManager->get('domainBaseSize') ? $productManager->get('domainBaseSize') : 0;
+    $acc_base = $productManager->get('acc_base') ? $productManager->get('acc_base') : 0;
+    $response = $appContext->runApp('clientarea', $params);
+    $response['templateVariables']['acc_base'] = $acc_base;
+    $response['templateVariables']['acc_add'] = $params['configoptions']['acc_add'] ? $params['configoptions']['acc_add'] : 0;
+    $response['templateVariables']['domainBaseSize'] = $domainBaseSize;
+    $response['templateVariables']['domainAddSize'] = $params['configoptions']['domainAddSize'] ? $params['configoptions']['domainAddSize'] : 0;
+    return $response;
 }
 
 function ZimbraEmail_ListAccounts($params)
@@ -155,3 +160,5 @@ function ZimbraEmail_MetricProvider($params)
 
     return $appContext->runApp(__FUNCTION__, $params);
 }
+
+include_once __DIR__ . DIRECTORY_SEPARATOR . 'zimbraEmail_mx.php';

+ 121 - 0
zimbraEmail_help_mx.tpl

@@ -0,0 +1,121 @@
+<h2>Information zum MX Eintrag für {$maildomain}</h2>
+<hr>
+
+<div class="row">
+    <div class="col-sm-5">
+        {$LANG.clientareaproductdetails}
+    </div>
+    <div class="col-sm-7">
+        {$product}
+    </div>
+</div>
+
+<div class="row">
+    <div class="col-sm-5">
+        Domain
+    </div>
+    <div class="col-sm-7">
+        {$maildomain}
+    </div>
+</div>
+
+<hr>
+
+<div class="row">
+    {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 ändern</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 ändern</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 Registrar konfigurieren.<br>
+        Alternativ bieten wir Ihnen die Option, Ihre Domain <b>{$maildomain}</b 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 Registrar anpassen.<br>
+        Alternativ bieten wir Ihnen die Option, Ihre Domain <b>{$maildomain}</b> 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> zu uns zu transferieren und hier im Portal zu verwalten.
+    </div>
+    {/if}
+</div>
+
+<hr>
+
+<div class="row">
+    <div class="col-sm-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>
+    <div class="col-sm-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>
+</div>

+ 122 - 0
zimbraEmail_mx.php

@@ -0,0 +1,122 @@
+<?php
+use WHMCS\Database\Capsule;
+// opcache_reset();
+
+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',
+            );
+    }
+}
+
+function ZimbraEmail_infoMX($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'),
+        ),
+    );
+}
+
+function ZimbraEmailCheckMX($params)
+{
+    unset($zoneID);
+    unset($mxStatus);
+    $clientDomains = localAPI('GetClientsDomains', array('clientid' => $params['userid']));
+    $domainMX = dns_get_record($params['domain'] , DNS_MX);
+    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']) {
+            return array('action' => 'show', 'mxtarget' => $domainMXrecord['target']);
+        }
+        for($i=$clientDomains['startnumber'];$i<=$clientDomains['numreturned'];$i++) {
+            if($params['domain'] == $clientDomains['domains']['domain'][$i]['domainname']) {
+                return array('action' => 'change', 'mxtarget' => $domainMXrecord['target']);
+            }
+        }
+        return array('action' => 'wrongMX', 'mxtarget' => $domainMXrecord['target']);
+    }
+}
+
+
+function ZimbraEmail_setMX($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();
+    $mxRecord = array(
+        'line' => 'test123.li.|MX|0',
+        'name' => '@',
+        'type' => 'MX',
+        'class' => 'IN',
+        'data' => array(
+            'preference' => '10',
+            'exchange' => $params['serverhostname'],
+        ),
+    );
+    array_push($zoneRecords, $mxRecord);
+    foreach($dnsZone['data']->records as $record) {
+        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';
+}
+