AntonLV 5 лет назад
Родитель
Сommit
e8fb28df5a
26 измененных файлов с 1884 добавлено и 0 удалено
  1. 46 0
      modules/boonex/donations/classes/BxDonationsAlertsResponse.php
  2. 133 0
      modules/boonex/donations/classes/BxDonationsConfig.php
  3. 164 0
      modules/boonex/donations/classes/BxDonationsDb.php
  4. 108 0
      modules/boonex/donations/classes/BxDonationsFormType.php
  5. 36 0
      modules/boonex/donations/classes/BxDonationsGridList.php
  6. 60 0
      modules/boonex/donations/classes/BxDonationsGridListAll.php
  7. 169 0
      modules/boonex/donations/classes/BxDonationsGridTypes.php
  8. 252 0
      modules/boonex/donations/classes/BxDonationsModule.php
  9. 34 0
      modules/boonex/donations/classes/BxDonationsPageList.php
  10. 51 0
      modules/boonex/donations/classes/BxDonationsStudioPage.php
  11. 134 0
      modules/boonex/donations/classes/BxDonationsTemplate.php
  12. 71 0
      modules/boonex/donations/install/config.php
  13. 20 0
      modules/boonex/donations/install/installer.php
  14. 116 0
      modules/boonex/donations/install/langs/en.xml
  15. 30 0
      modules/boonex/donations/install/sql/disable.sql
  16. 112 0
      modules/boonex/donations/install/sql/enable.sql
  17. 102 0
      modules/boonex/donations/install/sql/install.sql
  18. 24 0
      modules/boonex/donations/install/sql/uninstall.sql
  19. 48 0
      modules/boonex/donations/js/form.js
  20. 33 0
      modules/boonex/donations/js/main.js
  21. 18 0
      modules/boonex/donations/request.php
  22. 24 0
      modules/boonex/donations/template/block_make.html
  23. 49 0
      modules/boonex/donations/template/css/main.css
  24. 30 0
      modules/boonex/donations/template/images/icons/std-icon.svg
  25. 1 0
      modules/boonex/donations/template/link.html
  26. 19 0
      modules/boonex/donations/template/popup_type.html

+ 46 - 0
modules/boonex/donations/classes/BxDonationsAlertsResponse.php

@@ -0,0 +1,46 @@
+<?php defined('BX_DOL') or die('hack attempt');
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ *
+ * @defdroup    Donations Donations
+ * @indroup     UnaModules
+ *
+ * @{
+ */
+
+class BxDonationsAlertsResponse extends BxDolAlertsResponse
+{
+    protected $_sModule;
+    protected $_oModule;
+
+    protected $_bLog;
+    protected $_oLog;
+
+    public function __construct()
+    {
+        parent::__construct();
+
+        $this->_sModule = 'bx_donations';
+        $this->_oModule = BxDolModule::getInstance($this->_sModule);
+
+        $this->_bLog = false;
+        $this->_oLog = BxDolLog::getInstance();
+        $this->_oLog->setName('donations');
+    }
+
+    public function response($oAlert)
+    {
+        parent::response($oAlert);
+
+        $sMethod = '_process' . bx_gen_method_name($oAlert->sUnit . '_' . $oAlert->sAction);           	
+        if(method_exists($this, $sMethod))
+            $this->$sMethod($oAlert);
+    }
+
+    protected function _processSystemGetBadges($oAlert)
+    {
+    }
+}
+
+/** @} */

+ 133 - 0
modules/boonex/donations/classes/BxDonationsConfig.php

@@ -0,0 +1,133 @@
+<?php defined('BX_DOL') or die('hack attempt');
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ *
+ * @defgroup    Donations Donations
+ * @ingroup     UnaModules
+ *
+ * @{
+ */
+
+class BxDonationsConfig extends BxBaseModGeneralConfig
+{
+    protected $_oDb;
+    protected $_aHtmlIds;
+
+    protected $_iOwner;
+    protected $_bShowTitle;
+    protected $_aBillingTypes;
+    protected $_aPeriodUnits;
+
+    public function __construct($aModule)
+    {
+        parent::__construct($aModule);
+
+        $this->CNF = array (
+            // module icon
+            'ICON' => 'donate col-blue3',
+
+            // database tables
+            'TABLE_ENTRIES' => $aModule['db_prefix'] . 'entries',
+            'TABLE_ENTRIES_DELETED' => $aModule['db_prefix'] . 'entries_deleted',
+            'TABLE_TYPES' => $aModule['db_prefix'] . 'types',
+
+            // database fields
+            'FIELD_ID' => 'id',
+            'FIELD_NAME' => 'name',
+            'FIELD_TITLE' => 'title',
+            'FIELD_PERIOD' => 'period',
+            'FIELD_PERIOD_UNIT' => 'period_unit',
+            'FIELD_PRICE' => 'price',
+
+            // page URIs
+            'URL_MAKE' => 'page.php?i=donations-make',
+            'URL_LIST' => 'page.php?i=donations-list',
+            'URL_LIST_ALL' => 'page.php?i=donations-list-all',
+
+            // some params
+            'PARAM_SHOW_TITLE' => 'bx_donations_show_title',
+
+            // objects 
+            'OBJECT_GRID_LIST' => 'bx_donations_list',
+            'OBJECT_GRID_LIST_ALL' => 'bx_donations_list_all',
+            'OBJECT_GRID_TYPES' => 'bx_donations_types',
+            'OBJECT_FORM_TYPE' => 'bx_donations_type',
+            'OBJECT_FORM_TYPE_DISPLAY_ADD' => 'bx_donations_type_add',
+            'OBJECT_FORM_TYPE_DISPLAY_EDIT' => 'bx_donations_type_edit',
+            'OBJECT_FORM_PRELISTS_PERIOD_UNITS' => 'bx_donations_period_units',
+            'OBJECT_MENU_LIST_SUBMENU' => 'bx_donations_list_submenu',
+
+            // email templates
+            'ETEMPLATE_DONATED' => 'bx_donations_donated',
+        );
+
+        $this->_aJsClasses = array(
+            'main' => 'BxDonationsMain',
+            'form' => 'BxDonationsForm',
+        );
+
+        $this->_aJsObjects = array(
+            'main' => 'oBxDonationsMain',
+            'form' => 'oBxDonationsForm',
+        );
+
+        $sHtmlPrefix = str_replace('_', '-', $this->_sName);
+        $this->_aHtmlIds = array(
+            'popup_type' => $sHtmlPrefix . '-popup-type',
+            'menu_billing_types' => $sHtmlPrefix . '-menu-billing_types',
+            'link_billing_type' => $sHtmlPrefix . '-link-billing-',
+        );
+
+        $oPayments = BxDolPayments::getInstance();
+        $this->_iOwner = (int)$oPayments->getOption('site_admin');
+
+        $this->_aBillingTypes = array(
+            BX_DONATIONS_BTYPE_SINGLE,
+            BX_DONATIONS_BTYPE_RECURRING
+        );
+
+        $this->_aPeriodUnits = BxDolForm::getDataItems($this->CNF['OBJECT_FORM_PRELISTS_PERIOD_UNITS']);
+    }
+
+    public function init(&$oDb)
+    {
+        $this->_oDb = &$oDb;
+
+        $this->_bShowTitle = $this->_oDb->getParam($this->CNF['PARAM_SHOW_TITLE']) == 'on';
+    }
+
+    public function getHtmlIds($sKey = '')
+    {
+        if(empty($sKey))
+            return $this->_aHtmlIds;
+
+        return isset($this->_aHtmlIds[$sKey]) ? $this->_aHtmlIds[$sKey] : '';
+    }
+
+    public function getOwner()
+    {
+    	return $this->_iOwner;
+    }
+
+    public function isShowTitle()
+    {
+        return $this->_bShowTitle;
+    }
+    public function getBillingTypes()
+    {
+        return $this->_aBillingTypes;
+    }
+
+    public function getPeriodUnits()
+    {
+        return $this->_aPeriodUnits;
+    }
+
+    public function getTypeName($sName)
+    {
+        return uriGenerate($sName, $this->CNF['TABLE_TYPES'], $this->CNF['FIELD_NAME']);
+    }
+}
+
+/** @} */

+ 164 - 0
modules/boonex/donations/classes/BxDonationsDb.php

@@ -0,0 +1,164 @@
+<?php defined('BX_DOL') or die('hack attempt');
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ *
+ * @defgroup    Donations Donations
+ * @ingroup     UnaModules
+ *
+ * @{
+ */
+
+class BxDonationsDb extends BxDolModuleDb
+{
+    protected $_oConfig;
+
+    public function __construct(&$oConfig)
+    {
+        parent::__construct($oConfig);
+
+        $this->_oConfig = $oConfig;
+    }
+
+    public function getTypeById($iId)
+    {
+        return $this->getTypes(array('type' => 'by_id', 'value' => $iId));
+    }
+
+    public function getTypes($aParams)
+    {
+        $CNF = &$this->_oConfig->CNF;
+
+        $aMethod = array('name' => 'getAll', 'params' => array(0 => 'query'));
+
+        $sSelectClause = "`tt`.*";
+        $sJoinClause = $sWhereClause = $sOrderClause = $sLimitClause = "";
+
+        switch($aParams['type']) {
+            case 'by_id':
+                $aMethod['name'] = 'getRow';
+                $aMethod['params'][1] = array(
+                    'id' => $aParams['value']
+                );
+
+                $sWhereClause .= "AND `tt`.`id`=:id";
+                break;
+
+            case 'by_name':
+                $aMethod['name'] = 'getRow';
+                $aMethod['params'][1] = array(
+                    'name' => $aParams['value']
+                );
+
+                $sWhereClause .= "AND `tt`.`name`=:name";
+                break;
+
+            case 'by_duration_price':
+                $aMethod['name'] = 'getRow';
+                $aMethod['params'][1] = array(
+                    'period' => $aParams['period'],
+                    'period_unit' => $aParams['period_unit'],
+                    'price' => $aParams['price'],
+                );
+
+                $sWhereClause .= "AND `tt`.`period`=:period AND `tt`.`period_unit`=:period_unit AND `tt`.`price`=:price";
+                break;
+            
+            case 'by_btype_single':
+            case 'by_btype_recurring':
+                $aMethod['params'][1] = array(
+                    'period' => 0,
+                );
+
+                $sWhereClause .= "AND `tt`.`period`" . ($aParams['type'] == 'by_btype_single' ? '=' : '<>') . ":period";
+                break;
+
+            case 'conditions':
+                if(empty($aParams['conditions']))
+                    break;
+
+                if(is_array($aParams['conditions']))
+                    $sWhereClause .= $this->arrayToSQL($aParams['conditions'], ' AND ');
+                else if(is_string($aParams['conditions']) && !empty($aParams['bindings']) && is_array($aParams['bindings'])) {
+                    $sWhereClause .= $aParams['conditions'];
+                    
+                    if(!is_array($aMethod['params'][1]))
+                        $aMethod['params'][1] = array();
+
+                    $aMethod['params'][1] = array_merge($aMethod['params'][1], $aParams['bindings']);
+                }
+                break;
+
+            case 'all':
+                break;
+        }
+
+        if(!empty($sOrderClause))
+            $sOrderClause = ' ORDER BY ' . $sOrderClause;
+
+        if(!empty($sLimitClause))
+            $sLimitClause = ' LIMIT ' . $sLimitClause;
+
+        $aMethod['params'][0] = "SELECT " . $sSelectClause . " FROM `" . $CNF['TABLE_TYPES'] . "` AS `tt` " . $sJoinClause . " WHERE 1 " . $sWhereClause . $sOrderClause . $sLimitClause;
+        return call_user_func_array(array($this, $aMethod['name']), $aMethod['params']);
+    }
+
+    public function getTypeOrderMax()
+    {
+        $CNF = &$this->_oConfig->CNF;
+
+        return (int)$this->getOne("SELECT MAX(`order`) FROM `" . $CNF['TABLE_TYPES'] . "` WHERE 1");
+    }
+
+    public function deleteTypes($aWhere)
+    {
+        $CNF = &$this->_oConfig->CNF;
+
+        return (int)$this->query("DELETE FROM `" . $CNF['TABLE_TYPES'] . "` WHERE " . $this->arrayToSQL($aWhere, " AND ")) > 0;
+    }
+
+    public function registerEntry($iProfileId, $aTypeId, $iCount, $sOrder, $sLicense)
+    {
+    	$CNF = &$this->_oConfig->CNF;
+
+        $iProcessed = 0;
+        for($i = 0; $i < $iCount; $i++) {
+            $aQueryParams = array(
+                'profile_id' => $iProfileId,
+                'type_id' => $aTypeId,
+                'order' => $sOrder,
+                'license' => $sLicense
+            );
+
+            if((int)$this->query("INSERT INTO `" . $CNF['TABLE_ENTRIES'] . "` SET " . $this->arrayToSQL($aQueryParams) . ", `added`=UNIX_TIMESTAMP()") == 0)
+                continue;
+
+            $iProcessed += 1;
+        }
+
+        return $iCount == $iProcessed;
+    }
+
+    public function unregisterEntry($iProfileId, $aTypeId, $sOrder, $sLicense)
+    {
+        $CNF = &$this->_oConfig->CNF;
+
+        $aBindings = array(
+            'profile_id' => $iProfileId,
+            'type_id' => $aTypeId,
+            'order' => $sOrder,
+            'license' => $sLicense
+    	);
+
+    	$sWhereClause = "`profile_id`=:profile_id AND `type_id`=:type_id AND `order`=:order AND `license`=:license";
+
+        //--- Move to deleted entries table with 'refund' as reason.
+    	$sQuery = "INSERT IGNORE INTO `" . $CNF['TABLE_ENTRIES_DELETED'] . "` SELECT *, 'refund' AS `reason`, UNIX_TIMESTAMP() AS `deleted` FROM `" . $CNF['TABLE_ENTRIES'] . "` WHERE " . $sWhereClause;
+        $this->query($sQuery, $aBindings);
+
+    	$sQuery = "DELETE FROM `" . $CNF['TABLE_ENTRIES'] . "` WHERE " . $sWhereClause;
+        return $this->query($sQuery, $aBindings) !== false;
+    }
+}
+
+/** @} */

+ 108 - 0
modules/boonex/donations/classes/BxDonationsFormType.php

@@ -0,0 +1,108 @@
+<?php defined('BX_DOL') or die('hack attempt');
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ *
+ * @defgroup    Donations Donations
+ * @ingroup     UnaModules
+ * 
+ * @{
+ */
+
+class BxDonationsFormType extends BxTemplStudioFormView
+{
+    protected $_sModule;
+    protected $_oModule;
+
+    public function __construct($aInfo, $oTemplate = false)
+    {
+        $this->_sModule = 'bx_donations';
+        $this->_oModule = BxDolModule::getInstance($this->_sModule);
+
+        parent::__construct($aInfo, $oTemplate);
+
+        $CNF = &$this->_oModule->_oConfig->CNF;
+
+        if(isset($this->aInputs[$CNF['FIELD_NAME']])) {
+            $sJsObject = $this->_oModule->_oConfig->getJsObject('form');
+
+            $iId = $this->getId();
+            $aMask = array('mask' => "javascript:%s.checkName('%s');", $sJsObject, $CNF['FIELD_NAME']);
+            if(!empty($iId) && $this->aParams['display'] == $CNF['OBJECT_FORM_TYPE_DISPLAY_EDIT']) {
+                $aMask['mask'] = "javascript:%s.checkName('%s', %d);";
+                $aMask[] = $iId;
+            }
+
+            $sOnBlur = call_user_func_array('sprintf', array_values($aMask)); 
+            $this->aInputs[$CNF['FIELD_NAME']]['attrs']['onblur'] = $sOnBlur;
+        }
+    }
+
+    public function setAction($sAction)
+    {
+        $this->aFormAttrs['action'] = $sAction;
+    }
+
+    public function getCode($bDynamicMode = false)
+    {
+    	$sJs = $this->_oModule->_oTemplate->addJs(array('form.js'), $bDynamicMode);
+
+        $sCode = '';
+        if($bDynamicMode)
+            $sCode .= $sJs;
+
+        $sCode .= $this->_oModule->_oTemplate->getJsCode('form');
+        $sCode .= parent::getCode($bDynamicMode);
+
+        return $sCode;
+    }
+    
+    public function insert ($aValsToAdd = array(), $isIgnore = false)
+    {
+        $CNF = &$this->_oModule->_oConfig->CNF;
+
+        if(isset($this->aInputs[$CNF['FIELD_NAME']])) {
+            $sName = BxDolForm::getSubmittedValue($CNF['FIELD_NAME'], $this->aFormAttrs['method'], $this->_aSpecificValues);
+            $sName = $this->_oModule->_oConfig->getTypeName($sName);
+            BxDolForm::setSubmittedValue($CNF['FIELD_NAME'], $sName, $this->aFormAttrs['method'], $this->_aSpecificValues);
+        }
+
+        return parent::insert ($aValsToAdd, $isIgnore);
+    }
+
+    function update ($iContentId, $aValsToAdd = array(), &$aTrackTextFieldsChanges = null)
+    {
+        $CNF = &$this->_oModule->_oConfig->CNF;
+
+        $sNameKey = $CNF['FIELD_NAME'];
+        if(isset($this->aInputs[$sNameKey])) {
+            $sName = $this->getCleanValue($sNameKey);
+            $aContentInfo = $this->_oModule->_oDb->getTypes(array('type' => 'by_id', 'value' => $iContentId));
+
+            if($aContentInfo[$sNameKey] != $sName) {
+                $sName = $this->_oModule->_oConfig->getTypeName($sName);
+                BxDolForm::setSubmittedValue($sNameKey, $sName, $this->aFormAttrs['method'], $this->_aSpecificValues);
+            }
+        }
+
+        return parent::update ($iContentId, $aValsToAdd, $aTrackTextFieldsChanges);
+    }
+
+    public function getId()
+    {
+        $iResult = 0;
+
+        $aIds = bx_get('ids');
+        if(!$aIds || !is_array($aIds)) {
+            $sId = bx_get('id');
+            if(!empty($sId))
+                $iResult = $sId;
+        }
+        else
+            $iResult = array_shift($aIds);
+
+        return (int)$iResult;
+    }
+}
+
+/** @} */

+ 36 - 0
modules/boonex/donations/classes/BxDonationsGridList.php

@@ -0,0 +1,36 @@
+<?php defined('BX_DOL') or die('hack attempt');
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ *
+ * @defgroup    Donations Donations
+ * @ingroup     UnaModules
+ *
+ * @{
+ */
+
+require_once('BxDonationsGridListAll.php');
+
+class BxDonationsGridList extends BxDonationsGridListAll
+{
+    public function __construct ($aOptions, $oTemplate = false)
+    {
+        parent::__construct ($aOptions, $oTemplate);
+
+        $iProfileId = bx_get_logged_profile_id();
+        if($iProfileId !== false)
+            $this->_aQueryAppend['profile_id'] = (int)$iProfileId;
+    }
+
+    protected function _getDataSql($sFilter, $sOrderField, $sOrderDir, $iStart, $iPerPage)
+    {
+        if(empty($this->_aQueryAppend['profile_id']))
+            return array();
+
+        $this->_aOptions['source'] .= $this->_oModule->_oDb->prepareAsString(" AND `te`.`profile_id`=?", $this->_aQueryAppend['profile_id']);
+
+        return parent::_getDataSql($sFilter, $sOrderField, $sOrderDir, $iStart, $iPerPage);
+    }
+}
+
+/** @} */

+ 60 - 0
modules/boonex/donations/classes/BxDonationsGridListAll.php

@@ -0,0 +1,60 @@
+<?php defined('BX_DOL') or die('hack attempt');
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ *
+ * @defgroup    Donations Donations
+ * @ingroup     UnaModules
+ *
+ * @{
+ */
+
+class BxDonationsGridListAll extends BxTemplGrid
+{
+    protected $_sModule;
+    protected $_oModule;
+
+    public function __construct ($aOptions, $oTemplate = false)
+    {
+    	$this->_sModule = 'bx_donations';
+    	$this->_oModule = BxDolModule::getInstance($this->_sModule);
+    	if(!$oTemplate)
+            $oTemplate = $this->_oModule->_oTemplate;
+
+        parent::__construct ($aOptions, $oTemplate);
+
+        $this->_sDefaultSortingOrder = 'DESC';
+        $this->_aQueryReset = array($this->_aOptions['order_get_field'], $this->_aOptions['order_get_dir'], $this->_aOptions['paginate_get_start'], $this->_aOptions['paginate_get_per_page']);
+    }
+
+    protected function _getCellProfileId($mixedValue, $sKey, $aField, $aRow)
+    {
+        return parent::_getCellDefault($this->_oModule->_oTemplate->getProfileLink($mixedValue), $sKey, $aField, $aRow);
+    }
+
+    protected function _getCellEntry($mixedValue, $sKey, $aField, $aRow)
+    {
+        $sTitlekey = '_bx_donations_txt_amount_' . ($this->_oModule->_oConfig->isShowTitle() ? 'with' : 'wo') . '_title';
+
+        $sAmount = _t_format_currency($aRow['type_price']);
+        $sAmount = _t('_bx_donations_txt_amount_single', $sAmount);
+
+        return parent::_getCellDefault(_t($sTitlekey, $sAmount, _t($aRow['type_title'])), $sKey, $aField, $aRow);
+    }
+
+    protected function _getCellBillingType($mixedValue, $sKey, $aField, $aRow)
+    {
+        $mixedValue = BX_DONATIONS_BTYPE_SINGLE;
+        if(!empty($aRow['type_period']) && !empty($aRow['type_period_unit']))
+            $mixedValue = BX_DONATIONS_BTYPE_RECURRING;
+
+        return parent::_getCellDefault(_t('_bx_donations_txt_btype_' . $mixedValue), $sKey, $aField, $aRow);
+    }
+    
+    protected function _getCellAdded($mixedValue, $sKey, $aField, $aRow)
+    {
+        return parent::_getCellDefault(bx_time_js($mixedValue, BX_FORMAT_DATE, true), $sKey, $aField, $aRow);
+    }
+}
+
+/** @} */

+ 169 - 0
modules/boonex/donations/classes/BxDonationsGridTypes.php

@@ -0,0 +1,169 @@
+<?php defined('BX_DOL') or die('hack attempt');
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ *
+ * @defgroup    Donations Donations
+ * @ingroup     UnaModules
+ * 
+ * @{
+ */
+
+class BxDonationsGridTypes extends BxTemplGrid
+{
+    protected $_sModule;
+    protected $_oModule;
+    
+    protected $_aPeriodUnits;
+
+    public function __construct ($aOptions, $oTemplate = false)
+    {
+        $this->_sModule = 'bx_donations';
+    	$this->_oModule = BxDolModule::getInstance($this->_sModule);
+
+        parent::__construct ($aOptions, $oTemplate);
+
+        $this->_aPeriodUnits = $this->_oModule->_oConfig->getPeriodUnits();
+    }
+
+    public function performActionAdd()
+    {
+    	$CNF = &$this->_oModule->_oConfig->CNF;
+
+    	$sAction = 'add';
+
+    	$oForm = BxDolForm::getObjectInstance($CNF['OBJECT_FORM_TYPE'], $CNF['OBJECT_FORM_TYPE_DISPLAY_ADD']);
+        $oForm->setAction(BX_DOL_URL_ROOT . 'grid.php?o=' . $this->_sObject . '&a=' . $sAction);
+
+        $oForm->initChecker();
+        if($oForm->isSubmittedAndValid()) {
+            $iPeriod = $oForm->getCleanValue('period');
+            $bPeriod = !empty($iPeriod);
+
+            $sPeriodUnit = $oForm->getCleanValue('period_unit');
+            $bPeriodUnit = !empty($sPeriodUnit);
+
+            if(!$bPeriod && $bPeriodUnit) 
+                return echoJson(array('msg' => _t('_bx_donations_form_type_input_err_period')));
+            if($bPeriod && !$bPeriodUnit) 
+                return echoJson(array('msg' => _t('_bx_donations_form_type_input_err_period_unit')));
+
+            $iPrice = $oForm->getCleanValue('price');
+            $aType = $this->_oModule->_oDb->getTypes(array('type' => 'by_duration_price', 'period' => $iPeriod, 'period_unit' => $sPeriodUnit, 'price' => $iPrice));
+            if(!empty($aType) && is_array($aType))
+                return echoJson(array('msg' => _t('_bx_donations_err_price_duplicate')));
+
+            $iId = (int)$oForm->insert(array('order' => $this->_oModule->_oDb->getTypeOrderMax() + 1));
+            if($iId != 0)
+                $aRes = array('grid' => $this->getCode(false), 'blink' => $iId);
+            else
+                $aRes = array('msg' => _t('_bx_donations_err_cannot_perform'));
+
+            echoJson($aRes);
+            return;
+        }
+
+        bx_import('BxTemplStudioFunctions');
+        $sContent = BxTemplStudioFunctions::getInstance()->popupBox($this->_oModule->_oConfig->getHtmlIds('popup_type'), _t('_bx_donations_popup_title_price_add'), $this->_oModule->_oTemplate->parseHtmlByName('popup_type.html', array(
+            'form_id' => $oForm->aFormAttrs['id'],
+            'form' => $oForm->getCode(true),
+            'object' => $this->_sObject,
+            'action' => $sAction
+        )));
+
+        echoJson(array('popup' => array('html' => $sContent, 'options' => array('closeOnOuterClick' => false, 'removeOnClose' => true))));
+    }
+
+    public function performActionEdit()
+    {
+    	$CNF = &$this->_oModule->_oConfig->CNF;
+
+        $sAction = 'edit';
+
+        $iId = $this->_getId();
+        if($iId === false)
+            return echoJson(array());
+
+        $aItem = $this->_oModule->_oDb->getTypes(array('type' => 'by_id', 'value' => $iId));
+        if(!is_array($aItem) || empty($aItem))
+            return echoJson(array());
+
+        $oForm = BxDolForm::getObjectInstance($CNF['OBJECT_FORM_TYPE'], $CNF['OBJECT_FORM_TYPE_DISPLAY_EDIT']);
+        $oForm->setAction(BX_DOL_URL_ROOT . 'grid.php?o=' . $this->_sObject . '&a=' . $sAction . '&id=' . $iId);
+
+        $oForm->initChecker($aItem);
+        if($oForm->isSubmittedAndValid()) {
+            if($oForm->update($aItem['id']) !== false)
+                $aRes = array('grid' => $this->getCode(false), 'blink' => $aItem['id']);
+            else
+                $aRes = array('msg' => _t('_bx_donations_err_cannot_perform'));
+
+            return echoJson($aRes);
+        }
+
+        bx_import('BxTemplStudioFunctions');
+        $sContent = BxTemplStudioFunctions::getInstance()->popupBox($this->_oModule->_oConfig->getHtmlIds('popup_type'), _t('_bx_donations_popup_title_price_edit'), $this->_oModule->_oTemplate->parseHtmlByName('popup_type.html', array(
+            'form_id' => $oForm->aFormAttrs['id'],
+            'form' => $oForm->getCode(true),
+            'object' => $this->_sObject,
+            'action' => $sAction
+        )));
+
+        echoJson(array('popup' => array('html' => $sContent, 'options' => array('closeOnOuterClick' => false, 'removeOnClose' => true))));
+    }
+
+    protected function _delete ($mixedId)
+    {
+        $CNF = &$this->_oModule->_oConfig->CNF;
+
+        $aItem = $this->_oModule->_oDb->getTypes(array('type' => 'by_id', 'value' => (int)$mixedId));
+        if(!empty($aItem) && is_array($aItem))
+            BxDolStudioLanguagesUtils::getInstance()->deleteLanguageString($aItem[$CNF['FIELD_TITLE']]);
+
+        return parent::_delete($mixedId);
+    }
+
+    protected function _getCellPeriod($mixedValue, $sKey, $aField, $aRow)
+    {
+        if((int)$mixedValue == 0)
+            $mixedValue = _t('_bx_donations_txt_btype_single');
+        else
+            $mixedValue = _t('_bx_donations_txt_n_unit', $mixedValue, _t($this->_aPeriodUnits[$aRow['period_unit']]));
+
+        return parent::_getCellDefault($mixedValue, $sKey, $aField, $aRow);
+    }
+
+    protected function _getCellPrice($mixedValue, $sKey, $aField, $aRow)
+    {
+        return parent::_getCellDefault(_t_format_currency($mixedValue), $sKey, $aField, $aRow);
+    }
+
+    protected function _addJsCss()
+    {
+        parent::_addJsCss();
+        $this->_oModule->_oTemplate->addStudioJs(array('jquery.form.min.js'));
+
+        $oForm = new BxTemplFormView(array());
+        $oForm->addCssJs();
+    }
+
+    protected function _isVisibleGrid ($a)
+    {
+        return isAdmin();
+    }
+
+    protected function _getId()
+    {
+        $aIds = bx_get('ids');
+        if(!empty($aIds) && is_array($aIds)) 
+            return (int)array_shift($aIds);
+
+        $iId = bx_get('id');
+        if($iId !== false) 
+            return (int)$iId;
+
+        return false;
+    }
+}
+
+/** @} */

+ 252 - 0
modules/boonex/donations/classes/BxDonationsModule.php

@@ -0,0 +1,252 @@
+<?php defined('BX_DOL') or die('hack attempt');
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ *
+ * @defgroup    Donations Donations
+ * @ingroup     UnaModules
+ *
+ * @{
+ */
+
+define('BX_DONATIONS_BTYPE_SINGLE', 'single');
+define('BX_DONATIONS_BTYPE_RECURRING', 'recurring');
+
+class BxDonationsModule extends BxBaseModGeneralModule
+{
+    function __construct($aModule)
+    {
+        parent::__construct($aModule);
+
+        $this->_oConfig->init($this->_oDb);
+    }
+
+    /**
+     * ACTION METHODS
+     */
+    public function actionCheckName()
+    {
+        $CNF = &$this->_oConfig->CNF;
+
+    	$sName = bx_process_input(bx_get('name'));
+    	if(empty($sName))
+            return echoJson(array());
+
+        $sResult = '';
+
+        $iId = (int)bx_get('id');
+        if(!empty($iId)) {
+            $aPrice = $this->_oDb->getTypes(array('type' => 'by_id', 'value' => $iId)); 
+            if(strcmp($sName, $aPrice[$CNF['FIELD_NAME']]) == 0) 
+                $sResult = $sName;
+        }
+
+    	echoJson(array(
+            'name' => !empty($sResult) ? $sResult : $this->_oConfig->getTypeName($sName)
+    	));
+    }
+
+
+    /**
+     * SERVICE METHODS
+     */
+    public function serviceGetTypesBy($aParams)
+    {
+    	return $this->_oDb->getTypes($aParams);
+    }
+
+    public function serviceIncludeCssJs()
+    {
+        return $this->_oTemplate->getIncludeCssJs();
+    }
+
+    public function serviceGetBlockMake()
+    {
+        return $this->_oTemplate->getBlockMake();
+    }
+
+    public function serviceGetBlockList()
+    {
+        return $this->_getBlockList();
+    }
+
+    public function serviceGetBlockListAll()
+    {
+        return $this->_getBlockList('all');
+    }
+
+    public function serviceGetPaymentData()
+    {
+        $CNF = &$this->_oConfig->CNF;
+
+        $oPermalink = BxDolPermalinks::getInstance();
+
+        $aResult = $this->_aModule;
+        $aResult['url_browse_order_common'] = BX_DOL_URL_ROOT . $oPermalink->permalink($CNF['URL_LIST'], array('filter' => '{order}'));
+        $aResult['url_browse_order_administration'] = BX_DOL_URL_ROOT . $oPermalink->permalink($CNF['URL_LIST_ALL'], array('filter' => '{order}'));
+
+        return $aResult;
+    }
+
+    public function serviceGetCartItem($mixedItemId)
+    {
+    	$CNF = &$this->_oConfig->CNF;
+
+        if(!$mixedItemId)
+            return array();
+
+        $aItem = $this->_oDb->getTypes(array(
+            'type' => 'by_' . (is_numeric($mixedItemId) ? 'id' : 'name'), 
+            'value' => $mixedItemId
+        ));
+
+        if(empty($aItem) || !is_array($aItem))
+            return array();
+
+        return array (
+            'id' => $aItem[$CNF['FIELD_ID']],
+            'author_id' => $this->_oConfig->getOwner(),
+            'name' => $aItem[$CNF['FIELD_NAME']],
+            'title' => _t($this->_oConfig->isShowTitle() ? $aItem[$CNF['FIELD_TITLE']] : '_bx_donations_txt_cart_item_title'),
+            'description' => '',
+            'url' => BX_DOL_URL_ROOT . BxDolPermalinks::getInstance()->permalink($CNF['URL_MAKE']),
+            'price_single' => $aItem[$CNF['FIELD_PRICE']],
+            'price_recurring' => $aItem[$CNF['FIELD_PRICE']],
+            'period_recurring' => $aItem[$CNF['FIELD_PERIOD']],
+            'period_unit_recurring' => $aItem[$CNF['FIELD_PERIOD_UNIT']],
+            'trial_recurring' => ''
+        );
+    }
+
+    public function serviceGetCartItems($iSellerId)
+    {
+    	$CNF = &$this->_oConfig->CNF;
+
+        $iSellerId = (int)$iSellerId;
+        if(empty($iSellerId))
+            return array();
+
+        $aItems = $this->_oDb->getTypes(array('type' => 'all'));
+        if(empty($aItems) || !is_array($aItems))
+            return array();
+
+        $bShowTitle = $this->_oConfig->isShowTitle();
+
+        $aResult = array();
+        foreach($aItems as $aItem)
+            $aResult[] = array(
+                'id' => $aItem[$CNF['FIELD_ID']],
+                'author_id' => $this->_oConfig->getOwner(),
+                'name' => $aItem[$CNF['FIELD_NAME']],
+                'title' => _t($bShowTitle ? $aItem[$CNF['FIELD_TITLE']] : '_bx_donations_txt_cart_item_title'),
+                'description' => '',
+                'url' => BX_DOL_URL_ROOT . BxDolPermalinks::getInstance()->permalink($CNF['URL_MAKE']),
+                'price_single' => $aItem[$CNF['FIELD_PRICE']],
+                'price_recurring' => $aItem[$CNF['FIELD_PRICE']],
+                'period_recurring' => $aItem[$CNF['FIELD_PERIOD']],
+                'period_unit_recurring' => $aItem[$CNF['FIELD_PERIOD_UNIT']],
+                'trial_recurring' => ''
+            );
+
+        return $aResult;
+    }
+
+    public function serviceRegisterCartItem($iClientId, $iSellerId, $iItemId, $iItemCount, $sOrder, $sLicense)
+    {
+        return $this->_serviceRegisterItem($iClientId, $iSellerId, $iItemId, $iItemCount, $sOrder, $sLicense, BX_DONATIONS_BTYPE_SINGLE);
+    }
+
+    public function serviceRegisterSubscriptionItem($iClientId, $iSellerId, $iItemId, $iItemCount, $sOrder, $sLicense)
+    {
+        return $this->_serviceRegisterItem($iClientId, $iSellerId, $iItemId, $iItemCount, $sOrder, $sLicense, BX_DONATIONS_BTYPE_RECURRING);
+    }
+
+    public function serviceReregisterCartItem($iClientId, $iSellerId, $iItemIdOld, $iItemIdNew, $sOrder)
+    {
+        return array();
+    }
+
+    public function serviceReregisterSubscriptionItem($iClientId, $iSellerId, $iItemIdOld, $iItemIdNew, $sOrder)
+    {
+        return array();
+    }
+
+    public function serviceUnregisterCartItem($iClientId, $iSellerId, $iItemId, $iItemCount, $sOrder, $sLicense)
+    {
+        return $this->_serviceUnregisterItem($iClientId, $iSellerId, $iItemId, $iItemCount, $sOrder, $sLicense, BX_DONATIONS_BTYPE_SINGLE);
+    }
+
+    public function serviceUnregisterSubscriptionItem($iClientId, $iSellerId, $iItemId, $iItemCount, $sOrder, $sLicense)
+    {
+        return $this->_serviceUnregisterItem($iClientId, $iSellerId, $iItemId, $iItemCount, $sOrder, $sLicense, BX_DONATIONS_BTYPE_RECURRING); 
+    }
+
+    public function serviceCancelSubscriptionItem($iClientId, $iSellerId, $iItemId, $iItemCount, $sOrder)
+    {
+        return true;
+    }
+
+    protected function _serviceRegisterItem($iClientId, $iSellerId, $iItemId, $iItemCount, $sOrder, $sLicense, $sType)
+    {
+        $CNF = &$this->_oConfig->CNF;
+
+    	$aItem = $this->serviceGetCartItem($iItemId);
+        if(empty($aItem) || !is_array($aItem))
+            return array();
+
+        $aType = $this->_oDb->getTypeById($iItemId);
+        if(empty($aType) || !is_array($aType))
+            return array();
+
+        if(!$this->_oDb->registerEntry($iClientId, $iItemId, $iItemCount, $sOrder, $sLicense))
+            return array();
+
+        bx_alert($this->getName(), 'donation_register', 0, false, array(
+            'donation_id' => $iItemId,
+            'profile_id' => $iClientId,
+            'order' => $sOrder,
+            'type' => $sType,
+            'count' => $iItemCount
+        ));
+
+        $oClient = BxDolProfile::getInstanceMagic($iClientId);
+        sendMailTemplate($CNF['ETEMPLATE_DONATED'], 0, $iClientId, array(
+            'client_name' => $oClient->getDisplayName(),
+        ));
+
+        return $aItem;
+    }
+
+    protected function _serviceUnregisterItem($iClientId, $iSellerId, $iItemId, $iItemCount, $sOrder, $sLicense, $sType)
+    {
+    	if(!$this->_oDb->unregisterEntry($iClientId, $iItemId, $sOrder, $sLicense))
+            return false;
+
+        bx_alert($this->getName(), 'donation_unregister', 0, false, array(
+            'donation_id' => $iItemId,
+            'profile_id' => $iClientId,
+            'order' => $sOrder,
+            'type' => $sType,
+            'count' => $iItemCount
+        ));
+
+    	return true;
+    }
+
+    /*
+     * INTERNAL METHODS
+     */
+    protected function _getBlockList($sType = '') 
+    {
+        $CNF = &$this->_oConfig->CNF;
+
+        $sGrid = $CNF['OBJECT_GRID_LIST' . (!empty($sType) ? '_' . strtoupper($sType) : '')];
+        $oGrid = BxDolGrid::getObjectInstance($sGrid);
+        if(!$oGrid)
+            return '';
+
+        return $oGrid->getCode();
+    }
+}
+
+/** @} */

+ 34 - 0
modules/boonex/donations/classes/BxDonationsPageList.php

@@ -0,0 +1,34 @@
+<?php defined('BX_DOL') or die('hack attempt');
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ *
+ * @defgroup    Donations Donations
+ * @ingroup     UnaModules
+ *
+ * @{
+ */
+
+class BxDonationsPageList extends BxTemplPage
+{
+    protected $_sModule;
+    protected $_oModule;
+
+    public function __construct($aObject, $oTemplate = false)
+    {
+        $this->_sModule = 'bx_donations';
+        $this->_oModule = BxDolModule::getInstance($this->_sModule);
+
+        parent::__construct($aObject, $oTemplate);
+
+        $oMenuSubmenu = BxDolMenu::getObjectInstance('sys_site_submenu');
+        if($oMenuSubmenu) {
+            $sMenuSubmenu = 'sys_account_dashboard';
+            $oMenuSubmenu->setObjectSubmenu($sMenuSubmenu, array('title' => _t('_sys_menu_item_title_account_dashboard'), 'link' => '', 'icon' => ''));
+
+            BxDolMenu::getObjectInstance($sMenuSubmenu)->setSelected($this->_sModule, 'dashboard-donations-list');
+        }
+    }
+}
+
+/** @} */

+ 51 - 0
modules/boonex/donations/classes/BxDonationsStudioPage.php

@@ -0,0 +1,51 @@
+<?php defined('BX_DOL') or die('hack attempt');
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ *
+ * @defgroup    Donations Donations
+ * @ingroup     UnaModules
+ *
+ * @{
+ */
+
+class BxDonationsStudioPage extends BxTemplStudioModule
+{
+    protected $_sModule;
+    protected $_oModule;
+
+    function __construct($sModule, $mixedPageName, $sPage = "")
+    {
+    	$this->_sModule = 'bx_donations';
+    	$this->_oModule = BxDolModule::getInstance($this->_sModule);
+
+        parent::__construct($sModule, $mixedPageName, $sPage);
+
+        $this->aMenuItems['manage'] = array('name' => 'manage', 'icon' => 'wrench', 'title' => '_bx_donations_lmi_cpt_manage');
+    }
+
+    protected function getManage()
+    {
+        if (!isAdmin()) {
+            $this->_oTemplate->displayAccessDenied();
+            return;
+        }
+
+        $CNF = &$this->_oModule->_oConfig->CNF;
+
+        $sGrid = $CNF['OBJECT_GRID_TYPES'];
+        $oGrid = BxDolGrid::getObjectInstance($sGrid, BxDolStudioTemplate::getInstance());
+        if(!$oGrid)
+            return '';
+
+        $sContent = '';
+        if($this->_oModule->_oConfig->getOwner() == 0)
+            $sContent .= $this->_oModule->_oTemplate->displayEmptyOwner();
+
+        $sContent .= $oGrid->getCode();
+
+        return $sContent;
+    }
+}
+
+/** @} */

+ 134 - 0
modules/boonex/donations/classes/BxDonationsTemplate.php

@@ -0,0 +1,134 @@
+<?php defined('BX_DOL') or die('hack attempt');
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ *
+ * @defgroup    Donations Donations
+ * @ingroup     UnaModules
+ *
+ * @{
+ */
+
+class BxDonationsTemplate extends BxBaseModGeneralTemplate
+{
+    function __construct(&$oConfig, &$oDb)
+    {
+        parent::__construct($oConfig, $oDb);
+
+        $this->aMethodsToCallAddJsCss[] = 'getBlockMake';
+    }
+
+    public function addCssJs()
+    {
+        parent::addCssJs();
+
+        $this->addJs(array('main.js'));
+    }
+
+    public function getIncludeCssJs()
+    {
+        return '';
+    }
+
+    public function getBlockMake($sSelected = 'single')
+    {
+        $CNF = &$this->_oConfig->CNF;
+
+        $oPayment = BxDolPayments::getInstance();
+        $iPaymentSeller = $this->_oConfig->getOwner();
+        $sPaymentModule = $this->_oConfig->getName();
+
+        $sJsCode = '';
+        $sJsObject = $this->_oConfig->getJsObject('main');
+        $sHtmlIdBTypeLink = $this->_oConfig->getHtmlIds('link_billing_type');
+
+        $bShowTitle = $this->_oConfig->isShowTitle();
+        $aPeriodUnits = $this->_oConfig->getPeriodUnits();
+
+        $aMenuBillingTypes = array();
+        $aTmplVarsBillingTypes = array();
+        
+        $aBillingTypes = $this->_oConfig->getBillingTypes();
+        foreach($aBillingTypes as $sBillingType) {
+            $aMenuBillingTypes[] = array('name' => $sHtmlIdBTypeLink . $sBillingType, 'class' => '', 'link' => 'javascript:void(0)', 'onclick' => 'javascript:' . $sJsObject . ".changeType(this, '" . $sBillingType . "')", 'target' => '_self', 'title' => _t('_bx_donations_txt_do_' . $sBillingType));
+
+            $aTmplVarsTypes = array();
+
+            $aTypes = $this->_oDb->getTypes(array('type' => 'by_btype_' . $sBillingType));
+            foreach($aTypes as $aType) {
+                $sDuration = '';
+
+                switch($sBillingType) {
+                    case BX_DONATIONS_BTYPE_SINGLE:
+                        $aJs = $oPayment->getAddToCartJs($iPaymentSeller, $sPaymentModule, $aType[$CNF['FIELD_ID']], 1, true);
+                        if(empty($aJs) || !is_array($aJs))
+                            continue 2;
+                        break;
+
+                    case BX_DONATIONS_BTYPE_RECURRING:
+                        $aJs = $oPayment->getSubscribeJs($iPaymentSeller, '', $sPaymentModule, $aType[$CNF['FIELD_ID']], 1);
+                        if(empty($aJs) || !is_array($aJs))
+                            continue 2;
+
+                        if((int)$aType[$CNF['FIELD_PERIOD']] > 1)
+                            $sDuration .= $aType[$CNF['FIELD_PERIOD']] . ' ';
+                        $sDuration .= _t($aPeriodUnits[$aType[$CNF['FIELD_PERIOD_UNIT']]]);
+                        break;
+                }
+
+                list($sJsCode, $sOnclick) = $aJs;
+
+                $sAmount = _t_format_currency($aType[$CNF['FIELD_PRICE']]);
+                $sAmount = _t('_bx_donations_txt_amount_' . $sBillingType, $sAmount, $sDuration);
+
+                $aTmplVarsTypes[] = array(
+                    'onclick' => $sOnclick,
+                    'bx_if:show_title' => array(
+                        'condition' => $bShowTitle,
+                        'content' => array(
+                            'title' => _t($aType[$CNF['FIELD_TITLE']])
+                        )
+                    ),
+                    'amount' => $sAmount
+                );
+            }
+
+            $aTmplVarsBillingTypes[] = array(
+                'class' => $sBillingType . ($sBillingType == $sSelected ? ' active' : ''),
+                'bx_repeat:types' => $aTmplVarsTypes
+            );
+        }
+
+        $oMenuBillingTypes = new BxTemplMenu(array('template' => 'menu_buttons_hor.html', 'menu_id'=> $this->_oConfig->getHtmlIds('menu_billing_types'), 'menu_items' => $aMenuBillingTypes));
+        $oMenuBillingTypes->setSelected('', $sHtmlIdBTypeLink . $sSelected);
+
+        $sTmplName = 'block_make.html';
+        $aTmplVars = array(
+            'menu_billing_type' => $oMenuBillingTypes->getCode(),
+            'bx_repeat:billing_types' => $aTmplVarsBillingTypes,
+            'js_code' => $sJsCode . $this->getJsCode('main')
+        );
+
+        $sResult = null;
+        bx_alert($this->_oConfig->getName(), 'donate', 0, 0, array(
+            'tmpl_name' => &$sTmplName,
+            'tmpl_vars' => &$aTmplVars,
+            'override_result' => &$sResult
+        ));
+        if($sResult !== null)
+            return $sResult;
+
+        return $this->parseHtmlByName($sTmplName, $aTmplVars);
+    }
+
+    public function getJsCode($sType, $aParams = array(), $bWrap = true)
+    {
+        $aParams = array_merge(array(
+            'aHtmlIds' => $this->_oConfig->getHtmlIds()
+        ), $aParams);
+
+        return parent::getJsCode($sType, $aParams, $bWrap);
+    }
+}
+
+/** @} */

+ 71 - 0
modules/boonex/donations/install/config.php

@@ -0,0 +1,71 @@
+<?php
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ *
+ * @defgroup    Donations Donations
+ * @ingroup     UnaModules
+ *
+ * @{
+ */
+
+$aConfig = array(
+    /**
+     * Main Section.
+     */
+    'type' => BX_DOL_MODULE_TYPE_MODULE,
+    'name' => 'bx_donations',
+    'title' => 'Donations',
+    'note' => 'Donations custom module.',
+    'version' => '12.0.0',
+    'vendor' => 'BoonEx',
+    'help_url' => 'http://feed.una.io/?section={module_name}',
+
+    'compatible_with' => array(
+        '12.x.x'
+    ),
+
+    /**
+     * 'home_dir' and 'home_uri' - should be unique. Don't use spaces in 'home_uri' and the other special chars.
+     */
+    'home_dir' => 'boonex/donations/',
+    'home_uri' => 'donations',
+
+    'db_prefix' => 'bx_donations_',
+    'class_prefix' => 'BxDonations',
+
+    /**
+     * Category for language keys.
+     */
+    'language_category' => 'Donations',
+
+    /**
+     * Installation/Uninstallation Section.
+     */
+    'install' => array(
+        'execute_sql' => 1,
+        'update_languages' => 1,
+        'clear_db_cache' => 1,
+    ),
+    'uninstall' => array (
+        'execute_sql' => 1,
+        'update_languages' => 1,
+        'clear_db_cache' => 1,
+    ),
+    'enable' => array(
+        'execute_sql' => 1,
+        'clear_db_cache' => 1,
+    ),
+    'disable' => array (
+        'execute_sql' => 1,
+        'clear_db_cache' => 1,
+    ),
+
+    /**
+     * Dependencies Section
+     */
+    'dependencies' => array(),
+
+);
+
+/** @} */

+ 20 - 0
modules/boonex/donations/install/installer.php

@@ -0,0 +1,20 @@
+<?php defined('BX_DOL') or die('hack attempt');
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ *
+ * @defgroup    Donations Donations
+ * @ingroup     UnaModules
+ *
+ * @{
+ */
+
+class BxDonationsInstaller extends BxDolStudioInstaller
+{
+    function __construct($aConfig)
+    {
+        parent::__construct($aConfig);
+    }
+}
+
+/** @} */

+ 116 - 0
modules/boonex/donations/install/langs/en.xml

@@ -0,0 +1,116 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources name="en" flag="gb" title="English">
+    <string name="_bx_donations"><![CDATA[Donations]]></string>
+
+    <!-- Settings -->
+    <string name="_bx_donations_option_show_title"><![CDATA[Show donation title in addition to amount]]></string>
+    <string name="_bx_donations_option_recurring_reserve"><![CDATA[Reserve (in days) to accept and process recurring payment notification]]></string>
+
+    <!-- Forms -->
+    <string name="_bx_donations_form_type"><![CDATA[Type]]></string>
+    <string name="_bx_donations_form_type_display_add"><![CDATA[Add]]></string>
+    <string name="_bx_donations_form_type_display_edit"><![CDATA[Edit]]></string>
+    <string name="_bx_donations_form_type_input_sys_name"><![CDATA[Name]]></string>
+    <string name="_bx_donations_form_type_input_name"><![CDATA[Name]]></string>
+    <string name="_bx_donations_form_type_input_inf_name"><![CDATA[Unique value which will be used in back end and API calls.]]></string>
+    <string name="_bx_donations_form_type_input_err_name"><![CDATA[You need to enter a unique value here]]></string>
+    <string name="_bx_donations_form_type_input_sys_title"><![CDATA[Title]]></string>
+    <string name="_bx_donations_form_type_input_err_title"><![CDATA[You need to enter a title here.]]></string>
+    <string name="_bx_donations_form_type_input_title"><![CDATA[Title]]></string>
+    <string name="_bx_donations_form_type_input_sys_period"><![CDATA[Period]]></string>
+    <string name="_bx_donations_form_type_input_period"><![CDATA[Period]]></string>
+    <string name="_bx_donations_form_type_input_inf_period"><![CDATA[Leave empty for single time donation.]]></string>
+    <string name="_bx_donations_form_type_input_err_period"><![CDATA[You need to select a period here.]]></string>
+    <string name="_bx_donations_form_type_input_sys_period_unit"><![CDATA[Period unit]]></string>
+    <string name="_bx_donations_form_type_input_period_unit"><![CDATA[Period unit]]></string>
+    <string name="_bx_donations_form_type_input_inf_period_unit"><![CDATA[Leave empty for single time donation.]]></string>
+    <string name="_bx_donations_form_type_input_err_period_unit"><![CDATA[You need to select a period unit here.]]></string>
+    <string name="_bx_donations_form_type_input_sys_price"><![CDATA[Price]]></string>
+    <string name="_bx_donations_form_type_input_price"><![CDATA[Price]]></string>
+    <string name="_bx_donations_form_type_input_err_price"><![CDATA[You need to enter a price here.]]></string>
+    
+    <string name="_bx_donations_form_type_input_sys_do_submit"><![CDATA[Submit]]></string>
+    <string name="_bx_donations_form_type_input_do_submit"><![CDATA[Submit]]></string>
+    <string name="_bx_donations_form_type_input_sys_do_cancel"><![CDATA[Cancel]]></string>
+    <string name="_bx_donations_form_type_input_do_cancel"><![CDATA[Cancel]]></string>
+
+    <!-- Pre Lists -->
+    <string name="_bx_donations_pre_lists_period_units"><![CDATA[Billing Interval]]></string>
+    <string name="_bx_donations_pre_values_day"><![CDATA[day]]></string>
+    <string name="_bx_donations_pre_values_week"><![CDATA[week]]></string>
+    <string name="_bx_donations_pre_values_month"><![CDATA[month]]></string>
+    <string name="_bx_donations_pre_values_year"><![CDATA[year]]></string>
+
+    <!-- Pages -->
+    <string name="_bx_donations_page_title_sys_make"><![CDATA[Make Donation]]></string>
+    <string name="_bx_donations_page_title_make"><![CDATA[Donations]]></string>
+    <string name="_bx_donations_page_block_title_system_make"><![CDATA[Make Donation]]></string>
+    <string name="_bx_donations_page_block_title_make"><![CDATA[Make Donation]]></string>
+    <string name="_bx_donations_page_title_sys_list"><![CDATA[My Donations]]></string>
+    <string name="_bx_donations_page_title_list"><![CDATA[Donations]]></string>
+    <string name="_bx_donations_page_block_title_system_list"><![CDATA[My Donations]]></string>
+    <string name="_bx_donations_page_block_title_list"><![CDATA[My Donations]]></string>
+    <string name="_bx_donations_page_title_sys_list_all"><![CDATA[All Donations]]></string>
+    <string name="_bx_donations_page_title_list_all"><![CDATA[Donations]]></string>
+    <string name="_bx_donations_page_block_title_system_list_all"><![CDATA[All Donations]]></string>
+    <string name="_bx_donations_page_block_title_list_all"><![CDATA[All Donations]]></string>
+
+    <!-- Menus -->
+    <string name="_bx_donations_lmi_cpt_manage"><![CDATA[Manage]]></string>
+    <string name="_bx_donations_menu_item_title_system_make"><![CDATA[Donate]]></string>
+    <string name="_bx_donations_menu_item_title_make"><![CDATA[Donate]]></string>
+    <string name="_bx_donations_menu_item_title_system_list"><![CDATA[Donations]]></string>
+    <string name="_bx_donations_menu_item_title_list"><![CDATA[Donations]]></string>
+
+    <string name="_bx_donations_menu_title_list_submenu"><![CDATA[List Submenu]]></string>
+    <string name="_bx_donations_menu_set_title_list_submenu"><![CDATA[List Submenu]]></string>
+    <string name="_bx_donations_menu_item_title_system_list_submenu_list_all"><![CDATA[All Donations]]></string>
+    <string name="_bx_donations_menu_item_title_list_submenu_list_all"><![CDATA[All Donations]]></string>
+    <string name="_bx_donations_menu_item_title_system_list_submenu_list"><![CDATA[My Donations]]></string>
+    <string name="_bx_donations_menu_item_title_list_submenu_list"><![CDATA[My Donations]]></string>
+
+    <!-- Grids -->
+    <string name="_bx_donations_grid_column_name"><![CDATA[Name]]></string>
+    <string name="_bx_donations_grid_column_title"><![CDATA[Title]]></string>
+    <string name="_bx_donations_grid_column_period"><![CDATA[Period]]></string>
+    <string name="_bx_donations_grid_column_price"><![CDATA[Price]]></string>
+    <string name="_bx_donations_grid_column_title_lst_profile_id"><![CDATA[Profile]]></string>
+    <string name="_bx_donations_grid_column_title_lst_entry"><![CDATA[Donation]]></string>
+    <string name="_bx_donations_grid_column_title_lst_billing_type"><![CDATA[Billing]]></string>
+    <string name="_bx_donations_grid_column_title_lst_transaction"><![CDATA[Order]]></string>
+    <string name="_bx_donations_grid_column_title_lst_added"><![CDATA[Date]]></string>
+
+    <string name="_bx_donations_grid_action_add"><![CDATA[Add]]></string>
+    <string name="_bx_donations_grid_action_edit"><![CDATA[Edit]]></string>
+    <string name="_bx_donations_grid_action_delete"><![CDATA[Delete]]></string>
+
+    <string name="_bx_donations_popup_title_price_add"><![CDATA[Add Donation Plan]]></string>
+    <string name="_bx_donations_popup_title_price_edit"><![CDATA[Edit Donation Plan]]></string>
+
+    <!-- Email Templates -->
+    <string name="_bx_donations_et_txt_name_donated"><![CDATA[Donation was made.]]></string>
+    <string name="_bx_donations_et_txt_subject_donated"><![CDATA[You've made a donation.]]></string>
+    <string name="_bx_donations_et_txt_body_donated"><![CDATA[{email_header}
+<p>Hello, {client_name}.</p>
+<p>You've made a donation.<br />Thank you!</p>
+{email_footer}]]></string>
+
+    <!-- Messages/Errors -->
+    <string name="_bx_donations_msg_empty_owner"><![CDATA['Main seller' is empty. You need to mark some profile as 'Main seller' in Settings of currently active Payment app.]]></string>
+    <string name="_bx_donations_msg_performed"><![CDATA[The action was successfully performed.]]></string>
+    <string name="_bx_donations_err_price_duplicate"><![CDATA[Similar donation plan is already exists.]]></string>
+    <string name="_bx_donations_err_cannot_perform"><![CDATA[An error appeared. Please report.]]></string>
+
+    <!-- Other -->
+    <string name="_bx_donations_txt_btype_single"><![CDATA[one-time]]></string>
+    <string name="_bx_donations_txt_btype_recurring"><![CDATA[subscription]]></string>
+    <string name="_bx_donations_txt_n_unit"><![CDATA[{0} ({1})]]></string>
+    <string name="_bx_donations_txt_amount_single"><![CDATA[{0}]]></string>
+    <string name="_bx_donations_txt_amount_recurring"><![CDATA[{0} / {1}]]></string>
+    <string name="_bx_donations_txt_amount_with_title"><![CDATA[{1} ({0})]]></string>
+    <string name="_bx_donations_txt_do_title"><![CDATA[Select an Option Below to Donate]]></string>
+    <string name="_bx_donations_txt_do_notes"><![CDATA[Some notes here]]></string>
+    <string name="_bx_donations_txt_do_single"><![CDATA[One-Time Donations]]></string>
+    <string name="_bx_donations_txt_do_recurring"><![CDATA[Recurring Donations]]></string>
+    <string name="_bx_donations_txt_cart_item_title"><![CDATA[Donation]]></string>
+</resources>

+ 30 - 0
modules/boonex/donations/install/sql/disable.sql

@@ -0,0 +1,30 @@
+SET @sName = 'bx_donations';
+
+
+-- SETTINGS
+DELETE FROM `tot`, `toc`, `to` USING `sys_options_types` AS `tot` LEFT JOIN `sys_options_categories` AS `toc` ON `tot`.`id`=`toc`.`type_id` LEFT JOIN `sys_options` AS `to` ON `toc`.`id`=`to`.`category_id` WHERE `tot`.`name`=@sName;
+
+
+-- PAGES
+DELETE FROM `sys_objects_page` WHERE `module` = @sName;
+DELETE FROM `sys_pages_blocks` WHERE `module` = @sName OR `object` IN ('bx_donations_make', 'bx_donations_list', 'bx_donations_list_all');
+
+
+-- MENU
+DELETE FROM `sys_objects_menu` WHERE `module` = @sName;
+DELETE FROM `sys_menu_sets` WHERE `module` = @sName;
+DELETE FROM `sys_menu_items` WHERE `module` = @sName OR `set_name` IN ('bx_donations_list_submenu');
+
+
+-- GRIDS
+DELETE FROM `sys_objects_grid` WHERE `object` LIKE 'bx_donations_%';
+DELETE FROM `sys_grid_fields` WHERE `object` LIKE 'bx_donations_%';
+DELETE FROM `sys_grid_actions` WHERE `object` LIKE 'bx_donations_%';
+
+
+-- INJECTIONS
+DELETE FROM `sys_injections` WHERE `name`=@sName;
+
+
+-- EMAIL TEMPLATES
+DELETE FROM `sys_email_templates` WHERE `Module` = @sName;

+ 112 - 0
modules/boonex/donations/install/sql/enable.sql

@@ -0,0 +1,112 @@
+SET @sName = 'bx_donations';
+
+
+-- SETTINGS
+SET @iTypeOrder = (SELECT MAX(`order`) FROM `sys_options_types` WHERE `group` = 'modules');
+INSERT INTO `sys_options_types`(`group`, `name`, `caption`, `icon`, `order`) VALUES 
+('modules', @sName, '_bx_donations', 'bx_donations@modules/boonex/donations/|std-icon.svg', IF(ISNULL(@iTypeOrder), 1, @iTypeOrder + 1));
+SET @iTypeId = LAST_INSERT_ID();
+
+INSERT INTO `sys_options_categories` (`type_id`, `name`, `caption`, `order`)
+VALUES (@iTypeId, @sName, '_bx_donations', 10);
+SET @iCategId = LAST_INSERT_ID();
+
+INSERT INTO `sys_options` (`name`, `value`, `category_id`, `caption`, `type`, `extra`, `check`, `check_error`, `order`) VALUES
+('bx_donations_show_title', '', @iCategId, '_bx_donations_option_show_title', 'checkbox', '', '', '', 1),
+('bx_donations_recurring_reserve', '2', @iCategId, '_bx_donations_option_recurring_reserve', 'digit', '', '', '', 10);
+
+
+-- PAGE: make
+INSERT INTO `sys_objects_page`(`object`, `title_system`, `title`, `module`, `layout_id`, `visible_for_levels`, `visible_for_levels_editable`, `uri`, `url`, `meta_description`, `meta_keywords`, `meta_robots`, `cache_lifetime`, `cache_editable`, `deletable`, `override_class_name`, `override_class_file`) VALUES 
+('bx_donations_make', '_bx_donations_page_title_sys_make', '_bx_donations_page_title_make', @sName, 5, 2147483647, 1, 'donations-make', 'page.php?i=donations-make', '', '', '', 0, 1, 0, '', '');
+
+INSERT INTO `sys_pages_blocks`(`object`, `cell_id`, `module`, `title_system`, `title`, `designbox_id`, `visible_for_levels`, `type`, `content`, `deletable`, `copyable`, `order`) VALUES 
+('bx_donations_make', 1, @sName, '_bx_donations_page_block_title_system_make', '_bx_donations_page_block_title_make', 13, 2147483647, 'service', 'a:2:{s:6:"module";s:12:"bx_donations";s:6:"method";s:14:"get_block_make";}', 0, 1, 1);
+
+-- PAGE: list own
+INSERT INTO `sys_objects_page`(`object`, `title_system`, `title`, `module`, `layout_id`, `visible_for_levels`, `visible_for_levels_editable`, `uri`, `url`, `meta_description`, `meta_keywords`, `meta_robots`, `cache_lifetime`, `cache_editable`, `deletable`, `override_class_name`, `override_class_file`) VALUES 
+('bx_donations_list', '_bx_donations_page_title_sys_list', '_bx_donations_page_title_list', @sName, 5, 2147483647, 1, 'donations-list', '', '', '', '', 0, 1, 0, 'BxDonationsPageList', 'modules/boonex/donations/classes/BxDonationsPageList.php');
+
+INSERT INTO `sys_pages_blocks`(`object`, `cell_id`, `module`, `title_system`, `title`, `designbox_id`, `submenu`, `tabs`, `visible_for_levels`, `type`, `content`, `deletable`, `copyable`, `active`, `order`) VALUES 
+('bx_donations_list', 1, @sName, '', '_bx_donations_page_block_title_list', 11, 'bx_donations_list_submenu', 1, 2147483647, 'service', 'a:2:{s:6:"module";s:12:"bx_donations";s:6:"method";s:14:"get_block_list";}', 0, 0, 1, 1);
+
+-- PAGE: list all
+INSERT INTO `sys_objects_page`(`object`, `title_system`, `title`, `module`, `layout_id`, `visible_for_levels`, `visible_for_levels_editable`, `uri`, `url`, `meta_description`, `meta_keywords`, `meta_robots`, `cache_lifetime`, `cache_editable`, `deletable`, `override_class_name`, `override_class_file`) VALUES 
+('bx_donations_list_all', '_bx_donations_page_title_sys_list_all', '_bx_donations_page_title_list_all', @sName, 5, 192, 1, 'donations-list-all', '', '', '', '', 0, 1, 0, 'BxDonationsPageList', 'modules/boonex/donations/classes/BxDonationsPageList.php');
+
+INSERT INTO `sys_pages_blocks`(`object`, `cell_id`, `module`, `title_system`, `title`, `designbox_id`, `submenu`, `tabs`, `visible_for_levels`, `type`, `content`, `deletable`, `copyable`, `active`, `order`) VALUES 
+('bx_donations_list_all', 1, @sName, '', '_bx_donations_page_block_title_list_all', 11, 'bx_donations_list_submenu', 1, 192, 'service', 'a:2:{s:6:"module";s:12:"bx_donations";s:6:"method";s:18:"get_block_list_all";}', 0, 0, 1, 0);
+
+
+-- MENU: licenses submenu
+INSERT INTO `sys_objects_menu`(`object`, `title`, `set_name`, `module`, `template_id`, `deletable`, `active`, `override_class_name`, `override_class_file`) VALUES 
+('bx_donations_list_submenu', '_bx_donations_menu_title_list_submenu', 'bx_donations_list_submenu', @sName, 25, 0, 1, '', '');
+
+INSERT INTO `sys_menu_sets`(`set_name`, `module`, `title`, `deletable`) VALUES 
+('bx_donations_list_submenu', @sName, '_bx_donations_menu_set_title_list_submenu', 0);
+
+INSERT INTO `sys_menu_items`(`set_name`, `module`, `name`, `title_system`, `title`, `link`, `onclick`, `target`, `icon`, `addon`, `submenu_object`, `visible_for_levels`, `active`, `copyable`, `editable`, `order`) VALUES 
+('bx_donations_list_submenu', @sName, 'donations-list-all', '_bx_donations_menu_item_title_system_list_submenu_list_all', '_bx_donations_menu_item_title_list_submenu_list_all', 'page.php?i=donations-list-all', '', '_self', '', '', '', 192, 1, 0, 1, 1),
+('bx_donations_list_submenu', @sName, 'donations-list', '_bx_donations_menu_item_title_system_list_submenu_list', '_bx_donations_menu_item_title_list_submenu_list', 'page.php?i=donations-list', '', '_self', '', '', '', 2147483646, 1, 0, 1, 2);
+
+-- MENU: add to site menu
+SET @iSiteMenuOrder = (SELECT `order` FROM `sys_menu_items` WHERE `set_name` = 'sys_site' AND `active` = 1 AND `order` < 9999 ORDER BY `order` DESC LIMIT 1);
+INSERT INTO `sys_menu_items` (`set_name`, `module`, `name`, `title_system`, `title`, `link`, `onclick`, `target`, `icon`, `submenu_object`, `visible_for_levels`, `active`, `copyable`, `order`) VALUES 
+('sys_site', @sName, 'donations-make', '_bx_donations_menu_item_title_system_make', '_bx_donations_menu_item_title_make', 'page.php?i=donations-make', '', '', 'donate col-blue3', '', 2147483647, 1, 1, IFNULL(@iSiteMenuOrder, 0) + 1);
+
+-- MENU: add to homepage menu
+SET @iHomepageMenuOrder = (SELECT `order` FROM `sys_menu_items` WHERE `set_name` = 'sys_homepage' AND `active` = 1 ORDER BY `order` DESC LIMIT 1);
+INSERT INTO `sys_menu_items` (`set_name`, `module`, `name`, `title_system`, `title`, `link`, `onclick`, `target`, `icon`, `submenu_object`, `visible_for_levels`, `active`, `copyable`, `order`) VALUES 
+('sys_homepage', @sName, 'donations-make', '_bx_donations_menu_item_title_system_make', '_bx_donations_menu_item_title_make', 'page.php?i=donations-make', '', '', 'donate col-blue3', '', 2147483647, 1, 1, IFNULL(@iHomepageMenuOrder, 0) + 1);
+
+-- MENU: account dashboard
+SET @iDashboardMenuOrder = (SELECT IFNULL(MAX(`order`), 0) FROM `sys_menu_items` WHERE `set_name`='sys_account_dashboard' LIMIT 1);
+INSERT INTO `sys_menu_items` (`set_name`, `module`, `name`, `title_system`, `title`, `link`, `onclick`, `target`, `icon`, `addon`, `submenu_object`, `visible_for_levels`, `active`, `copyable`, `editable`, `order`) VALUES
+('sys_account_dashboard', @sName, 'dashboard-donations-list', '_bx_donations_menu_item_title_system_list', '_bx_donations_menu_item_title_list', 'page.php?i=donations-list', '', '', 'donate col-blue3', '', '', 2147483646, 1, 0, 1, @iDashboardMenuOrder + 1);
+
+
+-- GRIDS: types
+INSERT INTO `sys_objects_grid` (`object`, `source_type`, `source`, `table`, `field_id`, `field_order`, `field_active`, `paginate_url`, `paginate_per_page`, `paginate_simple`, `paginate_get_start`, `paginate_get_per_page`, `filter_fields`, `filter_fields_translatable`, `filter_mode`, `sorting_fields`, `sorting_fields_translatable`, `visible_for_levels`, `override_class_name`, `override_class_file`) VALUES
+('bx_donations_types', 'Sql', 'SELECT * FROM `bx_donations_types` WHERE 1 ', 'bx_donations_types', 'id', 'order', '', '', 100, NULL, 'start', '', 'name,period,period_unit,price', 'title', 'like', '', '', 192, 'BxDonationsGridTypes', 'modules/boonex/donations/classes/BxDonationsGridTypes.php');
+
+INSERT INTO `sys_grid_fields` (`object`, `name`, `title`, `width`, `translatable`, `chars_limit`, `params`, `order`) VALUES
+('bx_donations_types', 'checkbox', '_sys_select', '1%', 0, 0, '', 1),
+('bx_donations_types', 'order', '', '1%', 0, 0, '', 2),
+('bx_donations_types', 'name', '_bx_donations_grid_column_name', '24%', 0, 32, '', 3),
+('bx_donations_types', 'title', '_bx_donations_grid_column_title', '24%', 1, 32, '', 4),
+('bx_donations_types', 'price', '_bx_donations_grid_column_price', '15%', 0, 8, '', 5),
+('bx_donations_types', 'period', '_bx_donations_grid_column_period', '15%', 0, 8, '', 6),
+('bx_donations_types', 'actions', '', '20%', 0, '', '', 7);
+
+INSERT INTO `sys_grid_actions` (`object`, `type`, `name`, `title`, `icon`, `icon_only`, `confirm`, `order`) VALUES
+('bx_donations_types', 'independent', 'add', '_bx_donations_grid_action_add', '', 0, 0, 1),
+('bx_donations_types', 'single', 'edit', '_bx_donations_grid_action_edit', 'pencil-alt', 1, 0, 1),
+('bx_donations_types', 'single', 'delete', '_bx_donations_grid_action_delete', 'remove', 1, 1, 2),
+('bx_donations_types', 'bulk', 'delete', '_bx_donations_grid_action_delete', '', 0, 1, 1);
+
+-- GRIDS: entries list
+INSERT INTO `sys_objects_grid` (`object`, `source_type`, `source`, `table`, `field_id`, `field_order`, `field_active`, `paginate_url`, `paginate_per_page`, `paginate_simple`, `paginate_get_start`, `paginate_get_per_page`, `filter_fields`, `filter_fields_translatable`, `filter_mode`, `sorting_fields`, `sorting_fields_translatable`, `visible_for_levels`, `show_total_count`, `override_class_name`, `override_class_file`) VALUES
+('bx_donations_list_all', 'Sql', 'SELECT `te`.`id` AS `id`, `te`.`profile_id` AS `profile_id`, `te`.`type_id` AS `type_id`, `tt`.`title` AS `type_title`, `tt`.`price` AS `type_price`, `tt`.`period` AS `type_period`, `tt`.`period_unit` AS `type_period_unit`, `te`.`order` AS `transaction`, `te`.`added` AS `added` FROM `bx_donations_entries` AS `te` LEFT JOIN `bx_donations_types` AS `tt` ON `te`.`type_id`=`tt`.`id` WHERE 1 ', 'bx_donations_entries', 'id', 'added', '', '', 20, NULL, 'start', '', 'tt`.`name,tt`.`period,tt`.`period_unit,tt`.`price,te`.`order', 'tt`.`title', 'like', '', '', 192, 0, 'BxDonationsGridListAll', 'modules/boonex/donations/classes/BxDonationsGridListAll.php'),
+('bx_donations_list', 'Sql', 'SELECT `te`.`id` AS `id`, `te`.`profile_id` AS `profile_id`, `te`.`type_id` AS `type_id`, `tt`.`title` AS `type_title`, `tt`.`price` AS `type_price`, `tt`.`period` AS `type_period`, `tt`.`period_unit` AS `type_period_unit`, `te`.`order` AS `transaction`, `te`.`added` AS `added` FROM `bx_donations_entries` AS `te` LEFT JOIN `bx_donations_types` AS `tt` ON `te`.`type_id`=`tt`.`id` WHERE 1 ', 'bx_donations_entries', 'id', 'added', '', '', 20, NULL, 'start', '', 'tt`.`name,tt`.`period,tt`.`period_unit,tt`.`price,te`.`order', 'tt`.`title', 'like', '', '', 2147483647, 0, 'BxDonationsGridList', 'modules/boonex/donations/classes/BxDonationsGridList.php');
+
+INSERT INTO `sys_grid_fields` (`object`, `name`, `title`, `width`, `translatable`, `chars_limit`, `params`, `order`) VALUES
+('bx_donations_list_all', 'profile_id', '_bx_donations_grid_column_title_lst_profile_id', '20%', 0, 0, '', 1),
+('bx_donations_list_all', 'entry', '_bx_donations_grid_column_title_lst_entry', '30%', 0, 0, '', 2),
+('bx_donations_list_all', 'billing_type', '_bx_donations_grid_column_title_lst_billing_type', '10%', 0, 0, '', 3),
+('bx_donations_list_all', 'transaction', '_bx_donations_grid_column_title_lst_transaction', '30%', 0, 32, '', 4),
+('bx_donations_list_all', 'added', '_bx_donations_grid_column_title_lst_added', '10%', 0, 0, '', 5),
+
+('bx_donations_list', 'entry', '_bx_donations_grid_column_title_lst_entry', '45%', 0, 0, '', 1),
+('bx_donations_list', 'billing_type', '_bx_donations_grid_column_title_lst_billing_type', '10%', 0, 0, '', 2),
+('bx_donations_list', 'transaction', '_bx_donations_grid_column_title_lst_transaction', '35%', 0, 32, '', 3),
+('bx_donations_list', 'added', '_bx_donations_grid_column_title_lst_added', '10%', 0, 0, '', 4);
+
+
+-- INJECTIONS
+INSERT INTO `sys_injections` (`name`, `page_index`, `key`, `type`, `data`, `replace`, `active`) VALUES
+(@sName, 0, 'injection_head', 'service', 'a:2:{s:6:"module";s:12:"bx_donations";s:6:"method";s:14:"include_css_js";}', 0, 1);
+
+
+-- EMAIL TEMPLATES
+INSERT INTO `sys_email_templates` (`Module`, `NameSystem`, `Name`, `Subject`, `Body`) VALUES 
+(@sName, '_bx_donations_et_txt_name_donated', 'bx_donations_donated', '_bx_donations_et_txt_subject_donated', '_bx_donations_et_txt_body_donated');

+ 102 - 0
modules/boonex/donations/install/sql/install.sql

@@ -0,0 +1,102 @@
+SET @sName = 'bx_donations';
+
+
+-- TABLE: entries
+CREATE TABLE IF NOT EXISTS `bx_donations_entries` (
+  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
+  `profile_id` int(11) unsigned NOT NULL default '0',
+  `type_id` int(11) unsigned NOT NULL default '0',
+  `order` varchar(32) NOT NULL default '',
+  `license` varchar(32) NOT NULL default '',
+  `added` int(11) unsigned NOT NULL default '0',
+  PRIMARY KEY (`id`)
+);
+
+CREATE TABLE IF NOT EXISTS `bx_donations_entries_deleted` (
+  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
+  `profile_id` int(11) unsigned NOT NULL default '0',
+  `type_id` int(11) unsigned NOT NULL default '0',
+  `order` varchar(32) NOT NULL default '',
+  `license` varchar(32) NOT NULL default '',
+  `added` int(11) unsigned NOT NULL default '0',
+  `reason` varchar(16) NOT NULL default '',
+  `deleted` int(11) unsigned NOT NULL default '0',
+  PRIMARY KEY (`id`)
+);
+
+-- TABLES: types
+CREATE TABLE IF NOT EXISTS `bx_donations_types` (
+  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
+  `name` varchar(128) NOT NULL default '',
+  `title` varchar(128) NOT NULL default '',
+  `period` int(11) unsigned NOT NULL default '1',
+  `period_unit` varchar(32) NOT NULL default '',
+  `price` float unsigned NOT NULL default '1',
+  `order` int(11) NOT NULL,
+  PRIMARY KEY (`id`),
+  UNIQUE KEY `name` (`name`),
+  UNIQUE KEY `type` (`period`, `period_unit`, `price`)
+);
+
+
+-- FORMS
+INSERT INTO `sys_objects_form` (`object`, `module`, `title`, `action`, `form_attrs`, `submit_name`, `table`, `key`, `uri`, `uri_title`, `params`, `deletable`, `active`, `override_class_name`, `override_class_file`) VALUES
+('bx_donations_type', @sName, '_bx_donations_form_type', '', '', 'do_submit', 'bx_donations_types', 'id', '', '', '', 0, 1, 'BxDonationsFormType', 'modules/boonex/donations/classes/BxDonationsFormType.php');
+
+INSERT INTO `sys_form_displays` (`display_name`, `module`, `object`, `title`, `view_mode`) VALUES
+('bx_donations_type_add', @sName, 'bx_donations_type', '_bx_donations_form_type_display_add', 0),
+('bx_donations_type_edit', @sName, 'bx_donations_type', '_bx_donations_form_type_display_edit', 0);
+
+INSERT INTO `sys_form_inputs` (`object`, `module`, `name`, `value`, `values`, `checked`, `type`, `caption_system`, `caption`, `info`, `required`, `collapsed`, `html`, `attrs`, `attrs_tr`, `attrs_wrapper`, `checker_func`, `checker_params`, `checker_error`, `db_pass`, `db_params`, `editable`, `deletable`) VALUES
+('bx_donations_type', @sName, 'name', '', '', 0, 'text', '_bx_donations_form_type_input_sys_name', '_bx_donations_form_type_input_name', '_bx_donations_form_type_input_inf_name', 1, 0, 0, '', '', '', 'Avail', '', '_bx_donations_form_type_input_err_name', 'Xss', '', 1, 0),
+('bx_donations_type', @sName, 'title', '', '', 0, 'text_translatable', '_bx_donations_form_type_input_sys_title', '_bx_donations_form_type_input_title', '', 1, 0, 0, '', '', '', 'AvailTranslatable', 'a:1:{i:0;s:5:"title";}', '_bx_donations_form_type_input_err_title', 'Xss', '', 1, 0),
+('bx_donations_type', @sName, 'period', '', '', 0, 'text', '_bx_donations_form_type_input_sys_period', '_bx_donations_form_type_input_period', '_bx_donations_form_type_input_inf_period', 0, 0, 0, '', '', '', '', '', '', 'Int', '', 1, 0),
+('bx_donations_type', @sName, 'period_unit', '', '#!bx_donations_period_units', 0, 'select', '_bx_donations_form_type_input_sys_period_unit', '_bx_donations_form_type_input_period_unit', '_bx_donations_form_type_input_inf_period_unit', 0, 0, 0, '', '', '', '', '', '', 'Xss', '', 1, 0),
+('bx_donations_type', @sName, 'price', '', '', 0, 'text', '_bx_donations_form_type_input_sys_price', '_bx_donations_form_type_input_price', '', 1, 0, 0, '', '', '', 'Avail', '', '_bx_donations_form_type_input_err_price', 'Float', '', 1, 0),
+('bx_donations_type', @sName, 'controls', '', 'do_submit,do_cancel', 0, 'input_set', '', '', '', 0, 0, 0, '', '', '', '', '', '', '', '', 1, 0),
+('bx_donations_type', @sName, 'do_submit', '_bx_donations_form_type_input_do_submit', '', 0, 'submit', '_bx_donations_form_type_input_sys_do_submit', '', '', 0, 0, 0, '', '', '', '', '', '', '', '', 1, 0),
+('bx_donations_type', @sName, 'do_cancel', '_bx_donations_form_type_input_do_cancel', '', 0, 'button', '_bx_donations_form_type_input_sys_do_cancel', '', '', 0, 0, 0, 'a:2:{s:7:"onclick";s:45:"$(''.bx-popup-applied:visible'').dolPopupHide()";s:5:"class";s:22:"bx-def-margin-sec-left";}', '', '', '', '', '', '', '', 1, 0);
+
+INSERT INTO `sys_form_display_inputs` (`display_name`, `input_name`, `visible_for_levels`, `active`, `order`) VALUES
+('bx_donations_type_add', 'name', 2147483647, 1, 1),
+('bx_donations_type_add', 'title', 2147483647, 1, 2),
+('bx_donations_type_add', 'price', 2147483647, 1, 3),
+('bx_donations_type_add', 'period', 2147483647, 1, 4),
+('bx_donations_type_add', 'period_unit', 2147483647, 1, 5),
+('bx_donations_type_add', 'controls', 2147483647, 1, 6),
+('bx_donations_type_add', 'do_submit', 2147483647, 1, 7),
+('bx_donations_type_add', 'do_cancel', 2147483647, 1, 8),
+
+('bx_donations_type_edit', 'name', 2147483647, 1, 1),
+('bx_donations_type_edit', 'title', 2147483647, 1, 2),
+('bx_donations_type_edit', 'price', 2147483647, 1, 3),
+('bx_donations_type_edit', 'period', 2147483647, 1, 4),
+('bx_donations_type_edit', 'period_unit', 2147483647, 1, 5),
+('bx_donations_type_edit', 'controls', 2147483647, 1, 6),
+('bx_donations_type_edit', 'do_submit', 2147483647, 1, 7),
+('bx_donations_type_edit', 'do_cancel', 2147483647, 1, 8);
+
+
+-- PRE-VALUES
+INSERT INTO `sys_form_pre_lists`(`key`, `title`, `module`, `use_for_sets`) VALUES
+('bx_donations_period_units', '_bx_donations_pre_lists_period_units', @sName, '0');
+
+INSERT INTO `sys_form_pre_values`(`Key`, `Value`, `Order`, `LKey`, `LKey2`) VALUES
+('bx_donations_period_units', '', 0, '_sys_please_select', ''),
+('bx_donations_period_units', 'day', 1, '_bx_donations_pre_values_day', ''),
+('bx_donations_period_units', 'week', 2, '_bx_donations_pre_values_week', ''),
+('bx_donations_period_units', 'month', 3, '_bx_donations_pre_values_month', ''),
+('bx_donations_period_units', 'year', 4, '_bx_donations_pre_values_year', '');
+
+
+-- STUDIO PAGE & WIDGET
+INSERT INTO `sys_std_pages`(`index`, `name`, `header`, `caption`, `icon`) VALUES
+(3, @sName, '_bx_donations', '_bx_donations', 'bx_donations@modules/boonex/donations/|std-icon.svg');
+SET @iPageId = LAST_INSERT_ID();
+
+SET @iParentPageId = (SELECT `id` FROM `sys_std_pages` WHERE `name` = 'home');
+SET @iParentPageOrder = (SELECT MAX(`order`) FROM `sys_std_pages_widgets` WHERE `page_id` = @iParentPageId);
+INSERT INTO `sys_std_widgets` (`page_id`, `module`, `url`, `click`, `icon`, `caption`, `cnt_notices`, `cnt_actions`) VALUES
+(@iPageId, @sName, '{url_studio}module.php?name=bx_donations', '', 'bx_donations@modules/boonex/donations/|std-icon.svg', '_bx_donations', '', 'a:4:{s:6:"module";s:6:"system";s:6:"method";s:11:"get_actions";s:6:"params";a:0:{}s:5:"class";s:18:"TemplStudioModules";}');
+INSERT INTO `sys_std_pages_widgets` (`page_id`, `widget_id`, `order`) VALUES
+(@iParentPageId, LAST_INSERT_ID(), IF(ISNULL(@iParentPageOrder), 1, @iParentPageOrder + 1));

+ 24 - 0
modules/boonex/donations/install/sql/uninstall.sql

@@ -0,0 +1,24 @@
+SET @sName = 'bx_donations';
+
+
+-- TABLES
+DROP TABLE IF EXISTS `bx_donations_entries`, `bx_donations_entries_deleted`;
+DROP TABLE IF EXISTS `bx_donations_types`;
+
+
+-- FORMS
+DELETE FROM `sys_form_display_inputs` WHERE `display_name` IN (SELECT `display_name` FROM `sys_form_displays` WHERE `module` = @sName);
+DELETE FROM `sys_form_inputs` WHERE `module` = @sName;
+DELETE FROM `sys_form_displays` WHERE `module` = @sName;
+DELETE FROM `sys_objects_form` WHERE `module` = @sName;
+
+
+-- PRE-VALUES
+DELETE FROM `sys_form_pre_lists` WHERE `module` = @sName;
+DELETE FROM `sys_form_pre_values` WHERE `Key` IN('bx_donations_period_units');
+
+
+-- STUDIO PAGE & WIDGET
+DELETE FROM `tp`, `tw`, `tpw`
+USING `sys_std_pages` AS `tp`, `sys_std_widgets` AS `tw`, `sys_std_pages_widgets` AS `tpw`
+WHERE `tp`.`id` = `tw`.`page_id` AND `tw`.`id` = `tpw`.`widget_id` AND `tp`.`name` = @sName;

+ 48 - 0
modules/boonex/donations/js/form.js

@@ -0,0 +1,48 @@
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ *
+ * @defgroup    Donations Donations
+ * @ingroup     UnaModules
+ *
+ * @{
+ */
+
+function BxDonationsForm(oOptions) {
+    this._sActionsUri = oOptions.sActionUri;
+    this._sActionsUrl = oOptions.sActionUrl;
+    this._sObjName = oOptions.sObjName == undefined ? 'oBxDonationsForm' : oOptions.sObjName;
+    this._iOwnerId = oOptions.iOwnerId == undefined ? 0 : oOptions.iOwnerId;
+    this._sAnimationEffect = oOptions.sAnimationEffect == undefined ? 'slide' : oOptions.sAnimationEffect;
+    this._iAnimationSpeed = oOptions.iAnimationSpeed == undefined ? 'slow' : oOptions.iAnimationSpeed;
+    this._aHtmlIds = oOptions.aHtmlIds == undefined ? {} : oOptions.aHtmlIds;
+    this._oRequestParams = oOptions.oRequestParams == undefined ? {} : oOptions.oRequestParams;
+}
+
+BxDonationsForm.prototype.checkName = function(sNameId, iId) {
+    var oDate = new Date();
+
+    var oName = jQuery("[name='" + sNameId + "']");
+    var sName = oName.val();
+
+    if(!sName.length)
+        return;
+
+    jQuery.get(
+        this._sActionsUrl + 'check_name',
+        {
+            name: sName,
+            id: iId && parseInt(iId) > 0 ? iId : 0,
+            _t: oDate.getTime()
+        },
+        function(oData) {
+            if(!oData || oData.name == undefined)
+                return;
+
+            oName.val(oData.name);
+        },
+        'json'
+    );
+};
+
+/** @} */

+ 33 - 0
modules/boonex/donations/js/main.js

@@ -0,0 +1,33 @@
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ *
+ * @defgroup    Donations Donations
+ * @ingroup     UnaModules
+ *
+ * @{
+ */
+
+function BxDonationsMain(oOptions) {
+    this._sActionsUri = oOptions.sActionUri;
+    this._sActionsUrl = oOptions.sActionUrl;
+    this._sObjName = oOptions.sObjName == undefined ? 'oBxDonationsMain' : oOptions.sObjName;
+    this._iOwnerId = oOptions.iOwnerId == undefined ? 0 : oOptions.iOwnerId;
+    this._sAnimationEffect = oOptions.sAnimationEffect == undefined ? 'slide' : oOptions.sAnimationEffect;
+    this._iAnimationSpeed = oOptions.iAnimationSpeed == undefined ? 'slow' : oOptions.iAnimationSpeed;
+    this._aHtmlIds = oOptions.aHtmlIds == undefined ? {} : oOptions.aHtmlIds;
+    this._oRequestParams = oOptions.oRequestParams == undefined ? {} : oOptions.oRequestParams;
+}
+
+BxDonationsMain.prototype.changeType = function(oLink, sType) {
+    var sClsMi = 'bx-menu-item';
+    var sClsMa = 'bx-menu-tab-active';
+    
+    var sClsCi = 'bx-dnt-make-billing-type';
+    var sClsCa = 'active';
+
+    $(oLink).parents('.' + sClsMi + ':first').toggleClass(sClsMa, true).siblings('.' + sClsMi + '.' + sClsMa).toggleClass(sClsMa, false);
+    $(oLink).parents('.bx-dnt-make:first').find('.' + sClsCi + '.' + sType).toggleClass(sClsCa, true).siblings('.' + sClsCi + '.' + sClsCa).toggleClass(sClsCa, false);
+};
+
+/** @} */

+ 18 - 0
modules/boonex/donations/request.php

@@ -0,0 +1,18 @@
+<?php defined('BX_DOL') or die('hack attempt');
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ *
+ * @defgroup    Donation Donation
+ * @ingroup     UnaModules
+ *
+ * @{
+ */
+
+require_once(BX_DIRECTORY_PATH_INC . "design.inc.php");
+
+bx_import('BxDolLanguages');
+
+BxDolRequest::processAsAction($GLOBALS['aModule'], $GLOBALS['aRequest']);
+
+/** @} */

+ 24 - 0
modules/boonex/donations/template/block_make.html

@@ -0,0 +1,24 @@
+<div class="bx-dnt-make">
+    <div class="bx-dnt-make-cnt">
+        <div class="bx-dnt-make-title bx-def-font-h3 bx-def-font-align-center"><bx_text:_bx_donations_txt_do_title /></div>
+        <div class="bx-dnt-make-billing-types-menu bx-def-margin-top bx-def-padding-topbottom">__menu_billing_type__</div>
+        <div class="bx-dnt-make-billing-types bx-def-margin-topbottom">
+            <bx_repeat:billing_types>
+                <div class="bx-dnt-make-billing-type __class__">
+                    <bx_repeat:types>
+                        <div class="bx-dnt-make-type">
+                            <div class="bx-dnt-mt-cnt bx-def-padding">
+                                <bx_if:show_title>
+                                    <div class="bx-dnt-mt-title bx-def-margin-sec-bottom">__title__</div>
+                                </bx_if:show_title>
+                                <a class="bx-btn bx-dnt-mt-action" href="javascript:void(0)" onclick="javascript:__onclick__">__amount__</a>
+                            </div>
+                        </div>
+                    </bx_repeat:types>
+                </div>
+            </bx_repeat:billing_types>
+        </div>
+        <div class="bx-dnt-make-notes bx-def-padding-top bx-def-font-grayed bx-def-font-align-center"><bx_text:_bx_donations_txt_do_notes /></div>
+    </div>
+</div>
+__js_code__

+ 49 - 0
modules/boonex/donations/template/css/main.css

@@ -0,0 +1,49 @@
+/*-- Make block --*/
+.bx-dnt-make {
+    position: relative;
+}
+.bx-dnt-make-billing-types-menu {
+    display: -webkit-flex;
+    display: flex;
+    -webkit-align-items: center;
+    align-items: center;
+    -webkit-justify-content: center;
+    justify-content: center;
+}
+.bx-dnt-make-billing-types-menu .bx-menu-tab-active .bx-btn {
+    background-color: rgba(0, 0, 0, 0.05);
+}
+
+.bx-dnt-make-billing-types {
+    position: relative;
+}
+.bx-dnt-make-billing-type {
+    position: relative;
+    display: -webkit-flex;
+    display: flex;
+    -webkit-align-items: center;
+    align-items: center;
+    -webkit-justify-content: center;
+    justify-content: center;
+    -webkit-flex-wrap: wrap;
+    flex-wrap: wrap;
+}
+.bx-dnt-make-billing-type:not(.active) {
+    display: none;
+}
+.bx-dnt-make-type {
+    position: relative;
+    -webkit-flex: 2 1 auto;
+    flex: 2 1 auto;
+    width: 50%;
+
+    text-align: center;
+}
+.bx-media-phone .bx-dnt-make-type {
+    -webkit-flex-basis: 100%;
+    flex-basis: 100%;
+}
+.bx-dnt-make-type .bx-btn {
+    display: inline-block;
+    float: none;
+}

+ 30 - 0
modules/boonex/donations/template/images/icons/std-icon.svg

@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 20.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
+<svg version="1.1" id="Слой_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+	 viewBox="0 0 64 64" style="enable-background:new 0 0 64 64;" xml:space="preserve">
+<style type="text/css">
+	.st0{fill:#00B356;}
+	.st1{fill:#FFFFFF;}
+</style>
+<title>contact</title>
+<desc>Created with Sketch.</desc>
+<g id="Page-1">
+	<g id="Artboard" transform="translate(-826.000000, -430.000000)">
+		<g id="contact" transform="translate(826.000000, 430.000000)">
+			<g id="Path">
+				<path id="path-1_1_" class="st0" d="M32,64c14,0,21.8,0,26.9-5.1S64,46,64,32s0-21.8-5.1-26.9S46,0,32,0S10.2,0,5.1,5.1
+					S0,18,0,32s0,21.8,5.1,26.9S18,64,32,64z"/>
+			</g>
+		</g>
+	</g>
+</g>
+<path class="st1" d="M32,44.6c9,0,16.4-7.3,16.4-16.4S41,11.9,32,11.9s-16.4,7.3-16.4,16.4S23,44.6,32,44.6z M30.3,19.5v-1.3
+	c0-0.7,0.6-1.3,1.3-1.3h0.9c0.7,0,1.3,0.6,1.3,1.3v1.3c1.2,0.1,2.4,0.5,3.4,1.2c0.4,0.3,0.5,1,0.1,1.3l-1.3,1.2
+	c-0.3,0.3-0.7,0.3-1.1,0.1c-0.4-0.3-0.9-0.4-1.4-0.4h-3.1c-0.7,0-1.3,0.6-1.3,1.4c0,0.6,0.4,1.2,1,1.4l4.9,1.5
+	c2,0.6,3.4,2.5,3.4,4.7c0,2.7-2.1,4.8-4.6,4.9v1.3c0,0.7-0.6,1.3-1.3,1.3h-0.9c-0.7,0-1.3-0.6-1.3-1.3v-1.3
+	c-1.2-0.1-2.4-0.5-3.4-1.2c-0.4-0.3-0.5-1-0.1-1.3l1.3-1.2c0.3-0.3,0.7-0.3,1.1-0.1c0.4,0.3,0.9,0.4,1.4,0.4h3.1
+	c0.7,0,1.3-0.6,1.3-1.4c0-0.6-0.4-1.2-1-1.4L29,29.2c-2-0.6-3.4-2.5-3.4-4.7C25.6,21.8,27.7,19.6,30.3,19.5L30.3,19.5z M49.6,39.6
+	h-2.6c-1.5,2-3.5,3.8-5.7,5h5c0.4,0,0.8,0.3,0.8,0.6v1.3c0,0.3-0.3,0.6-0.8,0.6H17.7c-0.4,0-0.8-0.3-0.8-0.6v-1.3
+	c0-0.3,0.3-0.6,0.8-0.6h5c-2.2-1.3-4.2-3-5.7-5h-2.5c-1.4,0-2.5,1.1-2.5,2.5v7.6c0,1.4,1.1,2.5,2.5,2.5h35.2c1.4,0,2.5-1.1,2.5-2.5
+	v-7.6C52.1,40.7,51,39.6,49.6,39.6z"/>
+</svg>

+ 1 - 0
modules/boonex/donations/template/link.html

@@ -0,0 +1 @@
+<bx_include_base:../modules/base/general/template/link.html />

+ 19 - 0
modules/boonex/donations/template/popup_type.html

@@ -0,0 +1,19 @@
+<div class="bx-donations-type-form">
+    <div class="bx-donations-type-form-cnt">
+        __form__
+        <script language="javascript">
+            $(document).ready(function () {
+                $("#__form_id__").ajaxForm({ 
+                    dataType: "json",
+                    beforeSubmit: function (formData, jqForm, options) {
+                        bx_loading($("#__form_id__"), true);
+                    },
+                    success: function (data) {
+                        $(".bx-popup-applied:visible").dolPopupHide();
+                        glGrids.__object__.processJson(data, '__action__');
+                    }
+                });
+            });
+        </script>
+    </div>
+</div>