AntonLV 6 năm trước cách đây
mục cha
commit
92e46ad33d

+ 42 - 0
inc/classes/BxDolProfileQuery.php

@@ -277,6 +277,48 @@ class BxDolProfileQuery extends BxDolDb implements iBxDolSingleton
         return (int)$this->getOne($sSql);
     }
 
+    public function getProfileQuota($iProfileId)
+    {
+        if (!$iProfileId) // for guests and storages without owner don't count per-user quota
+            return array('current_size' => 0, 'current_number' => 0, 'quota_size' => 0, 'quota_number' => 0, 'max_file_size' => 0);
+
+        $sQuery = $this->prepare("SELECT `current_size`, `current_number`, 0 as `quota_size`, 0 as `quota_number`, 0 as `max_file_size` FROM `sys_storage_user_quotas` WHERE `profile_id` = ?", $iProfileId);
+        $a = $this->getRow($sQuery);
+        if (!is_array($a) || !$a)
+            $a = array ('current_size' => 0, 'current_number' => 0, 'quota_size' => 0, 'quota_number' => 0, 'max_file_size' => 0);
+
+        // get quota_number and quota_size from user's acl/membership
+        $aMembershipInfo = BxDolAcl::getInstance()->getMemberMembershipInfo($iProfileId);
+        if ($aMembershipInfo) {
+            if (isset($aMembershipInfo['quota_size']))
+                $a['quota_size'] = $aMembershipInfo['quota_size'];
+            if (isset($aMembershipInfo['quota_number']))
+                $a['quota_number'] = $aMembershipInfo['quota_number'];
+            if (isset($aMembershipInfo['quota_max_file_size']))
+                $a['max_file_size'] = $aMembershipInfo['quota_max_file_size'];
+        }
+
+        return $a;
+    }
+
+    public function updateProfileQuota($iProfileId, $iSize, $iNumber = 1)
+    {
+        if (!$iProfileId) // for guests and storages without owner don't update per-user quota
+            return true;
+
+        $iTime = time();
+        $sQuery = $this->prepare("
+            INSERT INTO `sys_storage_user_quotas`
+            SET `profile_id` = ?, `current_size` = `current_size` + ?, `current_number` = `current_number` + ?, `ts` = ?
+            ON DUPLICATE KEY UPDATE `current_size` = `current_size` + ?, `current_number` = `current_number` + ?, `ts` = ?",
+            $iProfileId, $iSize, $iNumber, $iTime, $iSize, $iNumber, $iTime
+        );
+        if ($this->query($sQuery))
+            return true;
+        else
+            return false;
+    }
+
     /**
      * Get profile field by specified field name and value.
      * In most cases it is for internal usage only.

+ 2 - 47
inc/classes/BxDolStorageQuery.php

@@ -36,19 +36,6 @@ class BxDolStorageQuery extends BxDolDb
         $sQuery = "SELECT * FROM `sys_objects_storage`";
         return $oDb->getAll($sQuery);
     }
-    
-    static public function getAllGhosts ($aParams)
-    {
-        $oDb = BxDolDb::getInstance();
-        $sQuery = "SELECT * FROM `sys_storage_ghosts` WHERE 2>1 ";
-        if (isset($aParams['profile_id']))
-            $sQuery .= " AND profile_id = :profile_id";
-        if (isset($aParams['object']))
-            $sQuery .= " AND object = :object";
-        if (isset($aParams['content_id']))
-            $sQuery .= " AND content_id = :content_id";
-        return $oDb->getAll($sQuery, $aParams);
-    }
 
     public function changeStorageEngine ($sEngine)
     {
@@ -109,44 +96,12 @@ class BxDolStorageQuery extends BxDolDb
 
     public function getUserQuota($iProfileId)
     {
-        if (!$iProfileId) // for guests and storages without owner don't count per-user quota
-            return array('current_size' => 0, 'current_number' => 0, 'quota_size' => 0, 'quota_number' => 0, 'max_file_size' => 0);
-
-        $sQuery = $this->prepare("SELECT `current_size`, `current_number`, 0 as `quota_size`, 0 as `quota_number`, 0 as `max_file_size` FROM `sys_storage_user_quotas` WHERE `profile_id` = ?", $iProfileId);
-        $a = $this->getRow($sQuery);
-        if (!is_array($a) || !$a)
-            $a = array ('current_size' => 0, 'current_number' => 0, 'quota_size' => 0, 'quota_number' => 0, 'max_file_size' => 0);
-
-        // get quota_number and quota_size from user's acl/membership
-        $aMembershipInfo = BxDolAcl::getInstance()->getMemberMembershipInfo($iProfileId);
-        if ($aMembershipInfo) {
-            if (isset($aMembershipInfo['quota_size']))
-                $a['quota_size'] = $aMembershipInfo['quota_size'];
-            if (isset($aMembershipInfo['quota_number']))
-                $a['quota_number'] = $aMembershipInfo['quota_number'];
-            if (isset($aMembershipInfo['quota_max_file_size']))
-                $a['max_file_size'] = $aMembershipInfo['quota_max_file_size'];
-        }
-
-        return $a;
+        return BxDolProfileQuery::getInstance()->getProfileQuota($iProfileId);
     }
 
     public function updateUserQuota($iProfileId, $iSize, $iNumber = 1)
     {
-        if (!$iProfileId) // for guests and storages without owner don't update per-user quota
-            return true;
-            
-        $iTime = time();
-        $sQuery = $this->prepare("
-            INSERT INTO `sys_storage_user_quotas`
-            SET `profile_id` = ?, `current_size` = `current_size` + ?, `current_number` = `current_number` + ?, `ts` = ?
-            ON DUPLICATE KEY UPDATE `current_size` = `current_size` + ?, `current_number` = `current_number` + ?, `ts` = ?",
-            $iProfileId, $iSize, $iNumber, $iTime, $iSize, $iNumber, $iTime
-        );
-        if ($this->query($sQuery))
-            return true;
-        else
-            return false;
+        return BxDolProfileQuery::getInstance()->updateProfileQuota($iProfileId, $iSize, $iNumber);
     }
 
     public function addFile($iProfileId, $sLocalId, $sPath, $aFileName, $sMimeType, $sExt, $iSize, $iTime, $isPrivate)

+ 2 - 0
install/sql/system.sql

@@ -4780,6 +4780,8 @@ INSERT INTO `sys_pages_blocks` (`object`, `cell_id`, `module`, `title_system`, `
 
 ('sys_dashboard', 3, 'system', '', '_sys_page_block_title_chart_growth', 11, 2147483647, 'service', 'a:4:{s:6:"module";s:6:"system";s:6:"method";s:16:"get_chart_growth";s:6:"params";a:0:{}s:5:"class";s:18:"TemplChartServices";}', 0, 1, 1, 0),
 
+('sys_dashboard', 2, 'system', '', '_sys_page_block_title_membership_stats', 11, 2147483647, 'service', 'a:4:{s:6:"module";s:6:"system";s:6:"method";s:24:"profile_membership_stats";s:6:"params";a:0:{}s:5:"class";s:20:"TemplServiceProfiles";}', 0, 1, 1, 2),
+
 ('sys_dashboard', 2, 'system', '', '_sys_page_block_title_chart_stats', 11, 2147483647, 'service', 'a:4:{s:6:"module";s:6:"system";s:6:"method";s:15:"get_chart_stats";s:6:"params";a:0:{}s:5:"class";s:18:"TemplChartServices";}', 0, 1, 1, 3),
 
 ('sys_create_account', 1, 'system', '', '_sys_page_block_title_create_account', 11, 2147483647, 'service', 'a:4:{s:6:\"module\";s:6:\"system\";s:6:\"method\";s:19:\"create_account_form\";s:6:\"params\";a:0:{}s:5:\"class\";s:19:\"TemplServiceAccount\";}', 0, 1, 1, 1),

+ 5 - 0
modules/boonex/english/data/langs/system/en.xml

@@ -109,6 +109,7 @@
 	<string name="_Times allowed"><![CDATA[Times allowed]]></string>
 	<string name="_Title"><![CDATA[Title]]></string>
 	<string name="_To"><![CDATA[to]]></string>
+        <string name="_unlimit"><![CDATA[unlimit]]></string>
 	<string name="_VIEW_MEMBERSHIP_ACTIONS"><![CDATA[View Allowed Actions]]></string>
 	<string name="_View"><![CDATA[View]]></string>
 	<string name="_Yes"><![CDATA[Yes]]></string>
@@ -2712,6 +2713,7 @@ If it is not enabled then please consider implement this optimization, since it
 	<string name="_sys_page_block_title_homepage_menu"><![CDATA[Content modules menu]]></string>
         <string name="_sys_page_block_title_homepage_splash"><![CDATA[Splash]]></string>
 	<string name="_sys_page_block_title_forgot_password"><![CDATA[Forgot Password]]></string>
+        <string name="_sys_page_block_title_membership_stats"><![CDATA[Membership Limits]]></string>
 	<string name="_sys_page_block_system_title_login"><![CDATA[Log in with Sign up link]]></string>
 	<string name="_sys_page_block_system_title_login_step2"><![CDATA[Log in - step2]]></string>
 	<string name="_sys_page_block_system_title_login_step3"><![CDATA[Log in - step3]]></string>
@@ -2822,6 +2824,8 @@ If it is not enabled then please consider implement this optimization, since it
 	<string name="_sys_profile_status_active"><![CDATA[Active]]></string>
 	<string name="_sys_profile_status_pending"><![CDATA[Pending]]></string>
 	<string name="_sys_profile_status_suspended"><![CDATA[Suspended]]></string>
+        <string name="_sys_profile_storage_quota_size"><![CDATA[Storage]]></string>
+        <string name="_sys_profile_storage_quota_number"><![CDATA[Number of files]]></string>
 	<string name="_sys_private"><![CDATA[Private]]></string>
         <string name="_sys_privacy_groups_acl"><![CDATA[Membership Levels]]></string>
     <string name="_sys_pruning_db"><![CDATA[<h3>Database pruning:</h3>
@@ -2902,6 +2906,7 @@ If it is not enabled then please consider implement this optimization, since it
 	<string name="_sys_storage_err_unlink"><![CDATA[file deletion failed]]></string>
 	<string name="_sys_storage_err_user_quota_exceeded"><![CDATA[user quota exceeded]]></string>
 	<string name="_sys_storage_err_wrong_ext"><![CDATA[wrong file extension]]></string>
+        <string name="_sys_storage_files"><![CDATA[file(s)]]></string>
 	<string name="_sys_storage_invalid_file"><![CDATA[file is invalid]]></string>
 	<string name="_sys_storage_restriction_ext_all_allowed"><![CDATA[Wow, files of all types are allowed!]]></string>
 	<string name="_sys_storage_restriction_ext_all_denied"><![CDATA[Sorry, adding all file types is currently restricted.]]></string>

+ 5 - 0
modules/boonex/russian/data/langs/system/ru.xml

@@ -109,6 +109,7 @@
 	<string name="_Times allowed"><![CDATA[Сколько раз разрешено]]></string>
 	<string name="_Title"><![CDATA[Заголовок]]></string>
 	<string name="_To"><![CDATA[кому]]></string>
+        <string name="_unlimit"><![CDATA[unlimit]]></string>
 	<string name="_VIEW_MEMBERSHIP_ACTIONS"><![CDATA[Просмотреть разрешённые действия]]></string>
 	<string name="_View"><![CDATA[Просмотреть]]></string>
 	<string name="_Yes"><![CDATA[Да]]></string>
@@ -2697,6 +2698,7 @@
     <string name="_sys_page_block_title_homepage_menu"><![CDATA[Меню модулей с содержимым]]></string>
     <string name="_sys_page_block_title_homepage_splash"><![CDATA[Заставка]]></string>
 	<string name="_sys_page_block_title_forgot_password"><![CDATA[Забыли пароль]]></string>
+        <string name="_sys_page_block_title_membership_stats"><![CDATA[Лимиты членства]]></string>
 	<string name="_sys_page_block_system_title_login"><![CDATA[Вход с линкой регистрации]]></string>
 	<string name="_sys_page_block_system_title_login_step2"><![CDATA[Вход - шаг 2]]></string>
 	<string name="_sys_page_block_system_title_login_step3"><![CDATA[Вход - шаг 3]]></string>
@@ -2807,6 +2809,8 @@
 	<string name="_sys_profile_status_active"><![CDATA[Активный]]></string>
     <string name="_sys_profile_status_pending"><![CDATA[В ожидании]]></string>
     <string name="_sys_profile_status_suspended"><![CDATA[Заблокированный]]></string>
+    <string name="_sys_profile_storage_quota_size"><![CDATA[Хранилище]]></string>
+        <string name="_sys_profile_storage_quota_number"><![CDATA[Количество файлов]]></string>
 	<string name="_sys_private"><![CDATA[Приватные]]></string>
         <string name="_sys_privacy_groups_acl"><![CDATA[Членство]]></string>
     <string name="_sys_pruning_db"><![CDATA[<h3>Очистка базы данных:</h3>
@@ -2887,6 +2891,7 @@
 	<string name="_sys_storage_err_unlink"><![CDATA[не удалось удалить файл]]></string>
 	<string name="_sys_storage_err_user_quota_exceeded"><![CDATA[квота пользователя превышена]]></string>
 	<string name="_sys_storage_err_wrong_ext"><![CDATA[неправильное расширение файла]]></string>
+        <string name="_sys_storage_files"><![CDATA[файл(ов)]]></string>
 	<string name="_sys_storage_invalid_file"><![CDATA[неправильный файл]]></string>
 	<string name="_sys_storage_restriction_ext_all_allowed"><![CDATA[Ого, разрешены файлы всех типов!]]></string>
 	<string name="_sys_storage_restriction_ext_all_denied"><![CDATA[Извините, добавление файлов любого вида сейчас запрещено.]]></string>

+ 104 - 0
template/css/acl.css

@@ -10,4 +10,108 @@ div.bx-acl-membeship .bx-acl-m-thumbnail .sys-icon {
 div.bx-acl-membeship .bx-acl-m-thumbnail img {
 	width: 100px;
 	height: 100px;
+}
+
+/*-- Profile Membership Stats block --*/
+div.bx-pms-si-graph {
+	display: table;
+	width: 100%;
+}
+div.bx-pms-si-graph .bx-pms-sig-bar,
+div.bx-pms-si-graph .bx-pms-sig-text {
+	display: table-cell;
+}
+div.bx-pms-si-graph .bx-pms-sig-bar {
+    -webkit-animation-fill-mode: both;
+    -moz-animation-fill-mode: both;
+    -o-animation-fill-mode: both;
+    animation-fill-mode: both;
+
+    -webkit-transform-origin: left;
+    -moz-transform-origin: left;
+    -ms-transform-origin: left;
+    -o-transform-origin: left;
+    transform-origin: left;
+
+    -webkit-animation: stats-bar 1000ms ease-out;
+    -o-animation: stats-bar 1000ms ease-out;
+    animation: stats-bar 1000ms ease-out;
+
+    background: #2196F3;
+    background: -moz-linear-gradient(left,#2196F3 0%,#1976D2 100%);
+    background: -webkit-gradient(linear,left top,right top,color-stop(0%,#2196F3),color-stop(100%,#1976D2));
+    background: -webkit-linear-gradient(left,#2196F3 0%,#1976D2 100%);
+    background: -o-linear-gradient(left,#2196F3 0%,#1976D2 100%);
+    background: -ms-linear-gradient(left,#2196F3 0%,#1976D2 100%);
+    background: linear-gradient(to right,#2196F3 0%,#1976D2 100%);
+    filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#2196F3',endColorstr='#1976D2',GradientType=1);
+}
+div.bx-pms-si-graph .bx-pms-sig-text {
+	white-space: nowrap;
+}
+
+/*--- Animation ---*/
+@-webkit-keyframes stats-bar {
+    from {
+        -webkit-transform:scaleX(0);
+        -moz-transform:scaleX(0);
+        -ms-transform:scaleX(0);
+        -o-transform:scaleX(0);
+        transform:scaleX(0)
+    }
+    to {
+        -webkit-transform:scaleX(1);
+        -moz-transform:scaleX(1);
+        -ms-transform:scaleX(1);
+        -o-transform:scaleX(1);
+        transform:scaleX(1)
+    }
+}
+@-moz-keyframes stats-bar {
+    from {
+        -webkit-transform:scaleX(0);
+        -moz-transform:scaleX(0);
+        -ms-transform:scaleX(0);
+        -o-transform:scaleX(0);
+        transform:scaleX(0)
+    }
+    to {
+        -webkit-transform:scaleX(1);
+        -moz-transform:scaleX(1);
+        -ms-transform:scaleX(1);
+        -o-transform:scaleX(1);
+        transform:scaleX(1)
+    }
+}
+@-ms-keyframes stats-bar {
+    from {
+        -webkit-transform:scaleX(0);
+        -moz-transform:scaleX(0);
+        -ms-transform:scaleX(0);
+        -o-transform:scaleX(0);
+        transform:scaleX(0)
+    }
+    to {
+        -webkit-transform:scaleX(1);
+        -moz-transform:scaleX(1);
+        -ms-transform:scaleX(1);
+        -o-transform:scaleX(1);
+        transform:scaleX(1)
+    }
+}
+@keyframes stats-bar {
+    from {
+        -webkit-transform:scaleX(0);
+        -moz-transform:scaleX(0);
+        -ms-transform:scaleX(0);
+        -o-transform:scaleX(0);
+        transform:scaleX(0)
+    }
+    to {
+        -webkit-transform:scaleX(1);
+        -moz-transform:scaleX(1);
+        -ms-transform:scaleX(1);
+        -o-transform:scaleX(1);
+        transform:scaleX(1)
+    }
 }

+ 14 - 0
template/profile_membership_stats.html

@@ -0,0 +1,14 @@
+<div class="bx-profile-membership-stats">
+    <div class="bx-pms-membership">__membership__</div>
+    <div class="bx-pms-stats bx-def-box bx-def-round-corners bx-def-color-bg-box bx-def-padding">
+        <bx_repeat:stat_items>
+            <div class="bx-pms-stat-item bx-def-margin-top-auto">
+                <div class="bx-pms-si-title">__title__</div>
+                <div class="bx-pms-si-graph bx-def-margin-thd-top">
+                    <div class="bx-pms-sig-bar bx-def-round-corners" style="width:__width__">&nbsp;</div>
+                    <div class="bx-pms-sig-text bx-def-padding-left bx-def-font-middle bx-def-font-grayed">__value__ (__percent__)</div>
+                </div>
+            </div>
+        </bx_repeat:stat_items>
+    </div>
+</div>

+ 36 - 0
template/scripts/BxBaseServiceProfiles.php

@@ -116,6 +116,42 @@ class BxBaseServiceProfiles extends BxDol
 		return BxDolAcl::getInstance()->getProfileMembership($iProfileId);
     }
 
+    public function serviceProfileMembershipStats ($iProfileId = 0)
+    {
+        if(!$iProfileId)
+            $iProfileId = bx_get_logged_profile_id();
+
+        $sTxtUnlimit = _t('_unlimit');
+        $sTxtFiles = _t('_sys_storage_files');
+        $aQuota = BxDolProfileQuery::getInstance()->getProfileQuota($iProfileId);
+
+        $aTmplVarsStats = array();
+        if(!empty($aQuota['quota_size'])) {
+            $iWidth = (int)round(100 * $aQuota['current_size']/$aQuota['quota_size']);
+            $sPercent = $iWidth . '%';
+        }
+        else {
+            $iWidth = 0;
+            $sPercent = $sTxtUnlimit;
+        }
+        $aTmplVarsStats[] = array('title' => _t('_sys_profile_storage_quota_size'), 'width' => $iWidth, 'value' => _t_format_size($aQuota['current_size']), 'percent' => $sPercent);
+
+        if(!empty($aQuota['quota_number'])) {
+            $iWidth = (int)round(100 * $aQuota['current_number']/$aQuota['quota_number']);
+            $sPercent = $iWidth . '%';
+        }
+        else {
+            $iWidth = 0;
+            $sPercent = $sTxtUnlimit;
+        } 
+        $aTmplVarsStats[] = array('title' => _t('_sys_profile_storage_quota_number'), 'width' => $iWidth, 'value' => $aQuota['current_number'] . ' ' . $sTxtFiles, 'percent' => $sPercent);
+
+        return BxDolTemplate::getInstance()->parseHtmlByName('profile_membership_stats.html', array(
+            'membership' => BxDolAcl::getInstance()->getProfileMembership($iProfileId),
+            'bx_repeat:stat_items' => $aTmplVarsStats
+        ));
+    }
+
     /**
      * @page service Service Calls
      * @section bx_system_general System Services