Admin - Quota - show virtual emails tree in filesystem quota tree
authorPaul Mehrer <p.mehrer@metaways.de>
Tue, 1 Aug 2017 10:00:41 +0000 (12:00 +0200)
committerPaul Mehrer <p.mehrer@metaways.de>
Wed, 2 Aug 2017 11:20:33 +0000 (13:20 +0200)
the virtual emails tree contains the quotas and sizes of the dovecot
accounts.

Change-Id: I45c595324895600dedacae2743bbe80eb50a0b32
Reviewed-on: http://gerrit.tine20.com/customers/5374
Tested-by: Jenkins CI (http://ci.tine20.com/)
Reviewed-by: Paul Mehrer <p.mehrer@metaways.de>
Tested-by: Paul Mehrer <p.mehrer@metaways.de>
tests/tine20/Admin/JsonTest.php
tine20/Admin/Frontend/Json.php
tine20/Tinebase/EmailUser/Imap/Dovecot.php
tine20/Tinebase/EmailUser/Sql.php
tine20/Tinebase/Model/Tree/Node.php

index 6b75366..1bbc247 100644 (file)
@@ -1308,10 +1308,44 @@ class Admin_JsonTest extends TestCase
         $filterAppResult = $this->_json->searchQuotaNodes(array(array(
             'field'     => 'path',
             'operator'  => 'equals',
-            'value'     => '/' . $filterNullResult['results'][0]['name']
+            'value'     => '/' . Tinebase_Application::getInstance()->getApplicationByName('Tinebase')->getId()
         )));
 
         static::assertEquals(1, $filterAppResult['totalcount']);
         static::assertEquals('folders', $filterAppResult['results'][0]['name']);
+
+        $filterAppResult = $this->_json->searchQuotaNodes(array(array(
+            'field'     => 'path',
+            'operator'  => 'equals',
+            'value'     => '/' . Tinebase_Application::getInstance()->getApplicationByName('Felamimail')->getId()
+        )));
+
+        $imapBackend = Tinebase_EmailUser::getInstance();
+        if ($imapBackend instanceof Tinebase_EmailUser_Imap_Dovecot) {
+            static::assertEquals(2, $filterAppResult['totalcount']);
+            static::assertEquals('Emails', $filterAppResult['results'][1]['name']);
+
+            $dovecotResult = $this->_json->searchQuotaNodes(array(array(
+                'field'     => 'path',
+                'operator'  => 'equals',
+                'value'     => '/' . Tinebase_Application::getInstance()->getApplicationByName('Felamimail')->getId() .
+                    '/Emails'
+            )));
+            static::assertGreaterThanOrEqual(1, $dovecotResult['totalcount']);
+
+            /** ATTENTION as the third part of a path needs to be 'personal' or 'shared' below would error!
+            $dovecotResult = $this->_json->searchQuotaNodes(array(array(
+                'field'     => 'path',
+                'operator'  => 'equals',
+                'value'     => '/' . Tinebase_Application::getInstance()->getApplicationByName('Felamimail')->getId() .
+                    '/Emails/' . $dovecotResult['results'][0]['parent_id']
+            )));
+            static::assertEquals(0, $dovecotResult['totalcount']);
+             *  */
+
+        } else {
+            static::assertEquals(1, $filterAppResult['totalcount']);
+        }
+        static::assertEquals('folders', $filterAppResult['results'][0]['name']);
     }
 }
index 3c7edee..7430f79 100644 (file)
@@ -1327,6 +1327,8 @@ class Admin_Frontend_Json extends Tinebase_Frontend_Json_Abstract
             return FALSE;
         }
 
+        $emailPath = Tinebase_FileSystem::getInstance()->getApplicationBasePath('Felamimail');
+        $virtualPath = $emailPath . '/Emails';
         $path = '';
         if (null !== $filter) {
             array_walk($filter, function ($val) use (&$path) {
@@ -1335,6 +1337,7 @@ class Admin_Frontend_Json extends Tinebase_Frontend_Json_Abstract
                 }
             });
         }
+
         $filter = $this->_decodeFilter($filter, 'Tinebase_Model_Tree_Node_Filter');
         // ATTENTION sadly the pathfilter to Array does path magic, returns the flatpath and not the statpath
         // etc. this is Filemanager path magic. We don't want that here!
@@ -1367,7 +1370,30 @@ class Admin_Frontend_Json extends Tinebase_Frontend_Json_Abstract
                     'value'     => Tinebase_Model_Tree_FileObject::TYPE_FOLDER,
                 )));
 
-        $records = Tinebase_FileSystem::getInstance()->search($filter);
+        if (strpos($path, $virtualPath) === 0) {
+            if (count(explode('/', trim($path, '/'))) > 2) {
+                $records = new Tinebase_Record_RecordSet('Tinebase_Model_Tree_Node', array());
+            } else {
+                $records = $this->_getVirtualEmailQuotaNodes();
+            }
+        } else {
+            $records = Tinebase_FileSystem::getInstance()->search($filter);
+            if ($path === $emailPath) {
+                $imapBackend = Tinebase_EmailUser::getInstance();
+                if ($imapBackend instanceof Tinebase_EmailUser_Imap_Dovecot) {
+                    /** @var Tinebase_Model_Tree_Node $emailNode */
+                    $emailNode = clone $records->getFirstRecord();
+                    $emailNode->setId(trim($emailPath, '/'));
+                    $emailNode->name = 'Emails';
+                    $emailNode->path = $virtualPath;
+                    $imapUsageQuota = $imapBackend->getTotalUsageQuota();
+                    $emailNode->quota = $imapUsageQuota['mailQuota'];
+                    $emailNode->size = $imapUsageQuota['mailSize'];
+                    $emailNode->revision_size = $emailNode->size;
+                    $records->addRecord($emailNode);
+                }
+            }
+        }
 
         $result = $this->_multipleRecordsToJson($records, $filter);
 
@@ -1384,6 +1410,36 @@ class Admin_Frontend_Json extends Tinebase_Frontend_Json_Abstract
         );
     }
 
+    /**
+     * @return Tinebase_Record_RecordSet of Tinebase_Model_Tree_Node
+     */
+    protected function _getVirtualEmailQuotaNodes()
+    {
+        /** @var Tinebase_EmailUser_Imap_Dovecot $imapBackend */
+        $imapBackend = Tinebase_EmailUser::getInstance();
+        $result = new Tinebase_Record_RecordSet('Tinebase_Model_Tree_Node', array());
+
+        if (!$imapBackend instanceof Tinebase_EmailUser_Imap_Dovecot) {
+            return $result;
+        }
+
+        $parent_id = Tinebase_Application::getInstance()->getApplicationByName('Felamimail')->getId();
+        /** @var Tinebase_Model_EmailUser $emailUser */
+        foreach ($imapBackend->getAllEmailUsers() as $emailUser) {
+            $node = new Tinebase_Model_Tree_Node(array(), true);
+            $node->parent_id = $parent_id;
+            $node->name = $emailUser->emailUsername;
+            $node->quota = $emailUser->emailMailQuota;
+            $node->size = $emailUser->emailMailSize;
+            $node->revision_size = $emailUser->emailMailSize;
+            $node->setId($emailUser->emailUserId);
+            $node->type = Tinebase_Model_Tree_FileObject::TYPE_FOLDER;
+            $result->addRecord($node);
+        }
+
+        return $result;
+    }
+
     /****************************** common ******************************/
     
     /**
index 3666d77..a753f8e 100644 (file)
@@ -220,6 +220,23 @@ class Tinebase_EmailUser_Imap_Dovecot extends Tinebase_EmailUser_Sql implements
         // makes mapping data to _config easier
         'emailHome'            => 'home'
     );
+
+    protected $_tableMapping = array(
+        'emailUserId'       => 'USERTABLE',
+        'emailUsername'     => 'USERTABLE',
+        'emailPassword'     => 'USERTABLE',
+        'emailUID'          => 'USERTABLE',
+        'emailGID'          => 'USERTABLE',
+        'emailLastLogin'    => 'USERTABLE',
+        'emailMailQuota'    => 'USERTABLE',
+        #'emailSieveQuota'   => 'USERTABLE',
+
+        'emailMailSize'     => 'QUOTATABLE',
+        'emailSieveSize'    => 'QUOTATABLE',
+
+        // makes mapping data to _config easier
+        'emailHome'            => 'USERTABLE'
+    );
     
     /**
      * Dovecot readonly
@@ -253,6 +270,11 @@ class Tinebase_EmailUser_Imap_Dovecot extends Tinebase_EmailUser_Sql implements
         
         // _quotaTable = dovecot_aliases
         $this->_quotasTable = $this->_config['prefix'] . $this->_config['quotaTable'];
+
+        $this->_replaceValue($this->_tableMapping, array(
+            'USERTABLE' => $this->_userTable,
+            'QUOTATABLE' => $this->_quotasTable
+        ));
         
         // set domain from imap config
         $this->_config['domain'] = !empty($this->_config['domain']) ? $this->_config['domain'] : null;
@@ -282,17 +304,17 @@ class Tinebase_EmailUser_Imap_Dovecot extends Tinebase_EmailUser_Sql implements
     {
         $select = $this->_db->select()
         
-            ->from(array($this->_userTable))
+            ->from(array($this->_userTable), $_cols)
 
             // Left Join Quotas Table
             ->joinLeft(
                 array($this->_quotasTable), // table
                 '(' . $this->_db->quoteIdentifier($this->_userTable . '.' . $this->_propertyMapping['emailUsername']) .  ' = ' . // ON (left)
                     $this->_db->quoteIdentifier($this->_quotasTable . '.' . $this->_propertyMapping['emailUsername']) . ')', // ON (right)
-                array( // Select
+                '*' === $_cols ? array( // Select
                     $this->_propertyMapping['emailMailSize']  => $this->_quotasTable . '.' . $this->_propertyMapping['emailMailSize'], // emailMailSize
                     $this->_propertyMapping['emailSieveSize'] => $this->_quotasTable . '.' . $this->_propertyMapping['emailSieveSize'] // emailSieveSize
-                ) 
+                ) : array()
             )
             
             // Only want 1 user (shouldn't be more than 1 anyway)
index b4b2782..8815040 100644 (file)
@@ -46,6 +46,11 @@ abstract class Tinebase_EmailUser_Sql extends Tinebase_User_Plugin_Abstract
     protected $_propertyMapping = array();
 
     /**
+     * @var array
+     */
+    protected $_tableMapping = array();
+
+    /**
      * config key (IMAP/SMTP)
      * 
      * @var string
@@ -516,4 +521,43 @@ abstract class Tinebase_EmailUser_Sql extends Tinebase_User_Plugin_Abstract
      * @return array
      */
     abstract protected function _recordToRawData(Tinebase_Model_FullUser $_user, Tinebase_Model_FullUser $_newUserProperties);
+
+    /**
+     * @return Tinebase_Record_RecordSet of Tinebase_Model_EmailUser
+     */
+    public function getAllEmailUsers()
+    {
+        $result = new Tinebase_Record_RecordSet('Tinebase_Model_EmailUser', array());
+        foreach ($this->_getSelect()->limit(0)->query()->fetchAll() as $row) {
+            $result->addRecord($this->_rawDataToRecord($row));
+        }
+        return $result;
+    }
+
+    /**
+     * returns array with keys mailQuota and mailSize
+     * @return array
+     */
+    public function getTotalUsageQuota()
+    {
+        $data = $this->_getSelect(
+            array(
+                new Zend_Db_Expr('SUM(' . $this->_db->quoteIdentifier($this->_tableMapping['emailMailQuota'] . '.' .
+                        $this->_propertyMapping['emailMailQuota']) . ') as mailQuota'),
+                new Zend_Db_Expr('SUM(' . $this->_db->quoteIdentifier($this->_tableMapping['emailMailSize']  . '.' .
+                        $this->_propertyMapping['emailMailSize'])  . ') as mailSize'),
+                //new Zend_Db_Expr('SUM(' . $this->_propertyMapping['emailSieveSize'] . ') as sieveSize'),
+            ))->query()->fetchAll();
+        return $data[0];
+    }
+
+    protected function _replaceValue(array &$array, array $replacements)
+    {
+        foreach($array as &$value) {
+            if (isset($replacements[$value])) {
+                $value = $replacements[$value];
+            }
+        }
+    }
+
 }
index 7d27813..87c1578 100644 (file)
@@ -35,6 +35,7 @@
  * @property    integer            quota
  * @property    Tinebase_Record_RecordSet grants
  * @property    bool               pin_protected
+ * @property    string             path
  */
 class Tinebase_Model_Tree_Node extends Tinebase_Record_Abstract
 {