Browse Source

Ticket #258 - Sunscriptions in Market module.

AntonLV 10 years ago
parent
commit
2fbea10c83

+ 6 - 1
modules/boonex/market/classes/BxMarketConfig.php

@@ -37,10 +37,12 @@ class BxMarketConfig extends BxBaseModTextConfig
             'FIELD_AUTHOR' => 'author',
             'FIELD_AUTHOR' => 'author',
             'FIELD_ADDED' => 'added',
             'FIELD_ADDED' => 'added',
             'FIELD_CHANGED' => 'changed',
             'FIELD_CHANGED' => 'changed',
+        	'FIELD_NAME' => 'name',
             'FIELD_TITLE' => 'title',
             'FIELD_TITLE' => 'title',
             'FIELD_TEXT' => 'text',
             'FIELD_TEXT' => 'text',
             'FIELD_TEXT_ID' => 'product-text',
             'FIELD_TEXT_ID' => 'product-text',
-        	'FIELD_PRICE' => 'price',
+        	'FIELD_PRICE_SINGLE' => 'price_single',
+        	'FIELD_PRICE_RECURRING' => 'price_recurring',
             'FIELD_ALLOW_VIEW_TO' => 'allow_view_to',
             'FIELD_ALLOW_VIEW_TO' => 'allow_view_to',
 			'FIELD_ALLOW_PURCHASE_TO' => 'allow_purchase_to',
 			'FIELD_ALLOW_PURCHASE_TO' => 'allow_purchase_to',
 			'FIELD_ALLOW_COMMENT_TO' => 'allow_comment_to',
 			'FIELD_ALLOW_COMMENT_TO' => 'allow_comment_to',
@@ -112,6 +114,9 @@ class BxMarketConfig extends BxBaseModTextConfig
                 'bx_market_view_popup' => $aMenuItems2Methods,
                 'bx_market_view_popup' => $aMenuItems2Methods,
             ),
             ),
 
 
+            // global settings
+			'OPTION_ENABLE_RECURRING' => 'bx_market_enable_recurring',
+
             // some language keys
             // some language keys
             'T' => array (
             'T' => array (
                 'txt_sample_single' => '_bx_market_txt_sample_single',
                 'txt_sample_single' => '_bx_market_txt_sample_single',

+ 6 - 12
modules/boonex/market/classes/BxMarketDb.php

@@ -112,29 +112,23 @@ class BxMarketDb extends BxBaseModTextDb
     /**
     /**
      * Integration with Payment based modules.  
      * Integration with Payment based modules.  
      */
      */
-    public function isCustomer ($iClientId, $iProductId)
+    public function hasLicense ($iClientId, $iProductId)
     {
     {
-    	$sQuery = $this->prepare("SELECT `id` FROM `" . $this->_sPrefix . "customers` WHERE `client_id` = ? AND `product_id` = ? LIMIT 1", $iClientId, $iProductId);
+    	$sQuery = $this->prepare("SELECT `id` FROM `" . $this->_sPrefix . "licenses` WHERE `client_id` = ? AND `product_id` = ? LIMIT 1", $iClientId, $iProductId);
         return (int)$this->getOne($sQuery) > 0;
         return (int)$this->getOne($sQuery) > 0;
     }
     }
 
 
-	public function registerCustomer($iClientId, $iProductId, $sOrderId, $iCount, $iDate)
+	public function registerLicense($iClientId, $iProductId, $iCount, $sOrder, $sLicense)
     {
     {
-    	$sQuery = $this->prepare("INSERT INTO `" . $this->_sPrefix . "customers`(`client_id`, `product_id`, `order_id`, `count`, `date`) VALUES(?, ?, ?, ?, ?)", $iClientId, $iProductId, $sOrderId, $iCount, $iDate);
+    	$sQuery = $this->prepare("INSERT INTO `" . $this->_sPrefix . "licenses`(`client_id`, `product_id`, `count`, `order`, `license`, `date`) VALUES(?, ?, ?, ?, ?, UNIX_TIMESTAMP())", $iClientId, $iProductId, $iCount, $sOrder, $sLicense);
         return (int)$this->query($sQuery) > 0;
         return (int)$this->query($sQuery) > 0;
     }
     }
 
 
-    public function unregisterCustomer($iClientId, $iProductId, $sOrderId)
+    public function unregisterLicense($iClientId, $iProductId, $sOrder, $sLicense)
     {
     {
-    	$sQuery = $this->prepare("DELETE FROM `" . $this->_sPrefix . "customers` WHERE `client_id` = ? AND `product_id` = ? AND `order_id` = ?", $iClientId, $iProductId, $sOrderId);
+    	$sQuery = $this->prepare("DELETE FROM `" . $this->_sPrefix . "licenses` WHERE `client_id` = ? AND `product_id` = ? AND `order` = ? AND `license` = ?", $iClientId, $iProductId, $sOrder, $sLicense);
         return (int)$this->query($sQuery) > 0;
         return (int)$this->query($sQuery) > 0;
     }
     }
-
-    function isPurchasedEntry ($iClientId, $iProductId)
-    {
-    	$sQuery = $this->prepare("SELECT `id` FROM `" . $this->_sPrefix . "customers` WHERE `client_id` = ? AND `product_id` = ? LIMIT 1", $iClientId, $iProductId);
-        return (int)$this->getOne($sQuery) > 0;
-    }
 }
 }
 
 
 /** @} */
 /** @} */

+ 14 - 2
modules/boonex/market/classes/BxMarketFormEntry.php

@@ -21,7 +21,14 @@ class BxMarketFormEntry extends BxBaseModTextFormEntry
 
 
         $CNF = &$this->_oModule->_oConfig->CNF;
         $CNF = &$this->_oModule->_oConfig->CNF;
 
 
-	    if (isset($this->aInputs[$CNF['FIELD_FILE']])) {
+        if(isset($this->aInputs[$CNF['FIELD_TITLE']], $this->aInputs[$CNF['FIELD_NAME']])) {
+        	$sJsObject = $this->_oModule->_oConfig->getJsObject('entry');
+
+        	$this->aInputs[$CNF['FIELD_TITLE']]['attrs']['onblur'] = "javascript:" . $sJsObject . ".checkName('" . $CNF['FIELD_TITLE'] . "', '" . $CNF['FIELD_NAME'] . "');";
+        	$this->aInputs[$CNF['FIELD_TITLE']]['attrs']['onkeyup'] = "javascript:" . $sJsObject . ".updateName('" . $CNF['FIELD_TITLE'] . "', '" . $CNF['FIELD_NAME'] . "');";
+        }
+
+	    if(isset($this->aInputs[$CNF['FIELD_FILE']])) {
             $this->aInputs[$CNF['FIELD_FILE']]['storage_object'] = $CNF['OBJECT_STORAGE_FILES'];
             $this->aInputs[$CNF['FIELD_FILE']]['storage_object'] = $CNF['OBJECT_STORAGE_FILES'];
             $this->aInputs[$CNF['FIELD_FILE']]['uploaders'] = $CNF['OBJECT_UPLOADERS'];
             $this->aInputs[$CNF['FIELD_FILE']]['uploaders'] = $CNF['OBJECT_UPLOADERS'];
             $this->aInputs[$CNF['FIELD_FILE']]['images_transcoder'] = '';
             $this->aInputs[$CNF['FIELD_FILE']]['images_transcoder'] = '';
@@ -31,7 +38,12 @@ class BxMarketFormEntry extends BxBaseModTextFormEntry
             $this->aInputs[$CNF['FIELD_FILE']]['ghost_template'] = '';
             $this->aInputs[$CNF['FIELD_FILE']]['ghost_template'] = '';
         }
         }
 
 
-		if (isset($this->aInputs[$CNF['FIELD_ALLOW_PURCHASE_TO']]))
+        if($this->_oModule->_oDb->getParam($CNF['OPTION_ENABLE_RECURRING']) != 'on') {
+			$this->aInputs[$CNF['FIELD_PRICE_RECURRING']]['type'] = 'hidden';
+			$this->aInputs[$CNF['FIELD_PRICE_RECURRING']]['value'] = 0;
+        }
+        
+		if(isset($this->aInputs[$CNF['FIELD_ALLOW_PURCHASE_TO']]))
 			$this->aInputs[$CNF['FIELD_ALLOW_PURCHASE_TO']] = BxDolPrivacy::getGroupChooser($CNF['OBJECT_PRIVACY_PURCHASE']);
 			$this->aInputs[$CNF['FIELD_ALLOW_PURCHASE_TO']] = BxDolPrivacy::getGroupChooser($CNF['OBJECT_PRIVACY_PURCHASE']);
 
 
 		$iOwnerId = bx_get_logged_profile_id();
 		$iOwnerId = bx_get_logged_profile_id();

+ 33 - 6
modules/boonex/market/classes/BxMarketMenuView.php

@@ -20,14 +20,41 @@ class BxMarketMenuView extends BxBaseModTextMenuView
         parent::__construct($aObject, $oTemplate);
         parent::__construct($aObject, $oTemplate);
     }
     }
 
 
-	public function getCode()
+    protected function _isVisible ($a)
     {
     {
-    	list($sJsCode, $sJsMethod) = BxDolPayments::getInstance()->getAddToCartJs($this->_aContentInfo['author'], $this->MODULE, $this->_aContentInfo['id'], 1);
-        $this->addMarkers(array(
-        	'add_to_cart_onclick' => $sJsMethod
-        ));
+    	$CNF = &$this->_oModule->_oConfig->CNF;
 
 
-        return $sJsCode . parent::getCode();
+		if(!parent::_isVisible($a))
+			return false;
+
+		$oPayment = BxDolPayments::getInstance();
+
+		$bResult = true;
+		switch ($a['name']) {
+			case 'add-to-cart':
+				$bResult = (float)$this->_aContentInfo[$CNF['FIELD_PRICE_SINGLE']] != 0;
+				if(!$bResult) 
+					break;
+
+				list($sJsCode, $sJsMethod) = $oPayment->getAddToCartJs($this->_aContentInfo['author'], $this->MODULE, $this->_aContentInfo['id'], 1);
+				$this->addMarkers(array(
+		        	'add_to_cart_onclick' => $sJsMethod
+		        ));
+				break;
+
+			case 'subscribe':
+				$bResult = (float)$this->_aContentInfo[$CNF['FIELD_PRICE_RECURRING']] != 0;
+				if(!$bResult) 
+					break;
+
+				list($sJsCode, $sJsMethod) = $oPayment->getSubscribeJs($this->_aContentInfo['author'], $this->MODULE, $this->_aContentInfo['id'], 1);
+				$this->addMarkers(array(
+		        	'subscribe_onclick' => $sJsMethod
+		        )); 
+				break;
+		}
+
+		return $bResult;
     }
     }
 }
 }
 
 

+ 64 - 25
modules/boonex/market/classes/BxMarketModule.php

@@ -19,6 +19,27 @@ class BxMarketModule extends BxBaseModTextModule
         parent::__construct($aModule);
         parent::__construct($aModule);
     }
     }
 
 
+    public function actionCheckName()
+    {
+    	$CNF = &$this->_oConfig->CNF;
+
+    	$sTitle = strtolower(bx_process_input(bx_get('title')));
+    	if(empty($sTitle))
+    		return echoJson(array());
+
+    	echoJson(array(
+    		'title' => $sTitle,
+    		'name' => uriGenerate($sTitle, $CNF['TABLE_ENTRIES'], $CNF['FIELD_NAME'])
+    	));
+    }
+
+    public function serviceEntityCreate ()
+    {
+    	$this->_oTemplate->addJs(array('entry.js'));
+
+    	return $this->_oTemplate->getJsCode('entry') . parent::serviceEntityCreate();
+    }
+
     public function serviceEntityDownload ($iContentId = 0)
     public function serviceEntityDownload ($iContentId = 0)
     {
     {
     	$CNF = &$this->_oConfig->CNF;
     	$CNF = &$this->_oConfig->CNF;
@@ -39,25 +60,6 @@ class BxMarketModule extends BxBaseModTextModule
         return $this->_oTemplate->entryAttachmentsByStorage($CNF['OBJECT_STORAGE_FILES'], $aContentInfo);
         return $this->_oTemplate->entryAttachmentsByStorage($CNF['OBJECT_STORAGE_FILES'], $aContentInfo);
     }
     }
 
 
-    public function checkAllowedDownload($aDataEntry, $isPerformAction = false)
-    {
-        $CNF = &$this->_oConfig->CNF;
-
-        // moderator and owner always have access
-        if ($aDataEntry[$CNF['FIELD_AUTHOR']] == $this->_iProfileId || $this->_isModerator($isPerformAction))
-            return CHECK_ACTION_RESULT_ALLOWED;
-
-        // check ACL
-        $aCheck = checkActionModule($this->_iProfileId, 'download entry', $this->getName(), $isPerformAction);
-        if($aCheck[CHECK_ACTION_RESULT] !== CHECK_ACTION_RESULT_ALLOWED)
-			return $aCheck[CHECK_ACTION_MESSAGE];
-
-		if(!$this->_oDb->isPurchasedEntry($this->_iProfileId, $aDataEntry[$CNF['FIELD_ID']]))
-            return true;
-
-        return CHECK_ACTION_RESULT_ALLOWED;
-    }
-
 	public function serviceEntityInfo ($iContentId = 0)
 	public function serviceEntityInfo ($iContentId = 0)
     {
     {
         return $this->_serviceTemplateFunc ('entryInfo', $iContentId);
         return $this->_serviceTemplateFunc ('entryInfo', $iContentId);
@@ -108,10 +110,12 @@ class BxMarketModule extends BxBaseModTextModule
 		return array (
 		return array (
 			'id' => $aItem[$CNF['FIELD_ID']],
 			'id' => $aItem[$CNF['FIELD_ID']],
 			'author_id' => $aItem[$CNF['FIELD_AUTHOR']],
 			'author_id' => $aItem[$CNF['FIELD_AUTHOR']],
+			'name' => $aItem[$CNF['FIELD_NAME']],
 			'title' => $aItem[$CNF['FIELD_TITLE']],
 			'title' => $aItem[$CNF['FIELD_TITLE']],
 			'description' => $aItem[$CNF['FIELD_TEXT']],
 			'description' => $aItem[$CNF['FIELD_TEXT']],
 			'url' => BX_DOL_URL_ROOT . BxDolPermalinks::getInstance()->permalink('page.php?i=view-product&id=' . $aItem[$CNF['FIELD_ID']]),
 			'url' => BX_DOL_URL_ROOT . BxDolPermalinks::getInstance()->permalink('page.php?i=view-product&id=' . $aItem[$CNF['FIELD_ID']]),
-			'price' => $aItem[$CNF['FIELD_PRICE']],
+			'price_single' => $aItem[$CNF['FIELD_PRICE_SINGLE']],
+			'price_recurring' => $aItem[$CNF['FIELD_PRICE_RECURRING']],
         );
         );
     }
     }
 
 
@@ -130,30 +134,46 @@ class BxMarketModule extends BxBaseModTextModule
             $aResult[] = array(
             $aResult[] = array(
 				'id' => $aItem[$CNF['FIELD_ID']],
 				'id' => $aItem[$CNF['FIELD_ID']],
 				'author_id' => $aItem[$CNF['FIELD_AUTHOR']],
 				'author_id' => $aItem[$CNF['FIELD_AUTHOR']],
+            	'name' => $aItem[$CNF['FIELD_NAME']],
 				'title' => $aItem[$CNF['FIELD_TITLE']],
 				'title' => $aItem[$CNF['FIELD_TITLE']],
 				'description' => $aItem[$CNF['FIELD_TEXT']],
 				'description' => $aItem[$CNF['FIELD_TEXT']],
 				'url' => BX_DOL_URL_ROOT . BxDolPermalinks::getInstance()->permalink('page.php?i=view-product&id=' . $aItem[$CNF['FIELD_ID']]),
 				'url' => BX_DOL_URL_ROOT . BxDolPermalinks::getInstance()->permalink('page.php?i=view-product&id=' . $aItem[$CNF['FIELD_ID']]),
-				'price' => $aItem[$CNF['FIELD_PRICE']],
+				'price' => $aItem[$CNF['FIELD_PRICE_SINGLE']],
            );
            );
 
 
         return $aResult;
         return $aResult;
     }
     }
 
 
-    public function serviceRegisterCartItem($iClientId, $iSellerId, $iItemId, $iItemCount, $sOrderId)
+    public function serviceRegisterCartItem($iClientId, $iSellerId, $iItemId, $iItemCount, $sOrder, $sLicense)
     {
     {
         $aItem = $this->serviceGetCartItem($iItemId);
         $aItem = $this->serviceGetCartItem($iItemId);
         if(empty($aItem) || !is_array($aItem))
         if(empty($aItem) || !is_array($aItem))
 			return array();
 			return array();
 
 
-        if(!$this->_oDb->registerCustomer($iClientId, $iItemId, $sOrderId, $iItemCount, time()))
+        if(!$this->_oDb->registerLicense($iClientId, $iItemId, $iItemCount, $sOrder, $sLicense))
             return array();
             return array();
 
 
         return $aItem;
         return $aItem;
     }
     }
 
 
-    public function serviceUnregisterCartItem($iClientId, $iSellerId, $iItemId, $iItemCount, $sOrderId)
+    public function serviceRegisterSubscriptionItem($iClientId, $iSellerId, $iItemId, $iItemCount, $sOrder, $sLicense)
     {
     {
-        return $this->_oDb->unregisterCustomer($iClientId, $iItemId, $sOrderId);
+		return $this->serviceRegisterCartItem($iClientId, $iSellerId, $iItemId, $iItemCount, $sOrder, $sLicense);
+    }
+
+    public function serviceUnregisterCartItem($iClientId, $iSellerId, $iItemId, $iItemCount, $sOrder, $sLicense)
+    {
+        return $this->_oDb->unregisterLicense($iClientId, $iItemId, $sOrder, $sLicense);
+    }
+
+    public function serviceUnregisterSubscriptionItem($iClientId, $iSellerId, $iItemId, $iItemCount, $sOrder, $sLicense)
+    {
+    	return $this->serviceUnregisterCartItem($iClientId, $iSellerId, $iItemId, $iItemCount, $sOrder, $sLicense); 
+    }
+
+	public function serviceCancelSubscriptionItem($iClientId, $iSellerId, $iItemId, $iItemCount, $sOrder)
+    {
+    	//TODO: Do something if it's necessary. 
     }
     }
 
 
     public function getGhostTemplateVars($aFile, $iProfileId, $iContentId, $oStorage, $oImagesTranscoder)
     public function getGhostTemplateVars($aFile, $iProfileId, $iContentId, $oStorage, $oImagesTranscoder)
@@ -187,6 +207,25 @@ class BxMarketModule extends BxBaseModTextModule
 		);
 		);
     }
     }
 
 
+	public function checkAllowedDownload($aDataEntry, $isPerformAction = false)
+    {
+        $CNF = &$this->_oConfig->CNF;
+
+        // moderator and owner always have access
+        if ($aDataEntry[$CNF['FIELD_AUTHOR']] == $this->_iProfileId || $this->_isModerator($isPerformAction))
+            return CHECK_ACTION_RESULT_ALLOWED;
+
+        // check ACL
+        $aCheck = checkActionModule($this->_iProfileId, 'download entry', $this->getName(), $isPerformAction);
+        if($aCheck[CHECK_ACTION_RESULT] !== CHECK_ACTION_RESULT_ALLOWED)
+			return $aCheck[CHECK_ACTION_MESSAGE];
+
+		if(!$this->_oDb->hasLicense($this->_iProfileId, $aDataEntry[$CNF['FIELD_ID']]))
+            return true;
+
+        return CHECK_ACTION_RESULT_ALLOWED;
+    }
+
     protected function _getContentInfo($iContentId = 0)
     protected function _getContentInfo($iContentId = 0)
     {
     {
     	if(!$iContentId)
     	if(!$iContentId)

+ 1 - 1
modules/boonex/market/classes/BxMarketPrivacy.php

@@ -38,7 +38,7 @@ class BxMarketPrivacy extends BxTemplPrivacy
         if($mixedGroupId != 'c')
         if($mixedGroupId != 'c')
         	return false; 
         	return false; 
 
 
-        return $this->_oModule->_oDb->isCustomer($iViewerId, $iObjectId);
+        return $this->_oModule->_oDb->hasLicense($iViewerId, $iObjectId);
     }
     }
 }
 }
 
 

+ 1 - 1
modules/boonex/market/classes/BxMarketSearchResult.php

@@ -21,7 +21,7 @@ class BxMarketSearchResult extends BxBaseModTextSearchResult
             'object_metatags' => 'bx_market',
             'object_metatags' => 'bx_market',
             'title' => _t('_bx_market_page_title_browse'),
             'title' => _t('_bx_market_page_title_browse'),
             'table' => 'bx_market_products',
             'table' => 'bx_market_products',
-            'ownFields' => array('id', 'title', 'text', 'price', 'thumb', 'author', 'added'),
+            'ownFields' => array('id', 'title', 'text', 'price_single', 'price_recurring', 'thumb', 'author', 'added'),
             'searchFields' => array('title', 'text'),
             'searchFields' => array('title', 'text'),
             'restriction' => array(
             'restriction' => array(
                 'author' => array('value' => '', 'field' => 'author', 'operator' => '='),
                 'author' => array('value' => '', 'field' => 'author', 'operator' => '='),

+ 60 - 7
modules/boonex/market/classes/BxMarketTemplate.php

@@ -77,14 +77,49 @@ class BxMarketTemplate extends BxBaseModTextTemplate
                 $sThumbUrl = $oImagesTranscoder->getFileUrl($aData[$CNF['FIELD_THUMB']]);
                 $sThumbUrl = $oImagesTranscoder->getFileUrl($aData[$CNF['FIELD_THUMB']]);
         }
         }
 
 
-        list($sBuyCode, $sBuyOnclick) = BxDolPayments::getInstance()->getAddToCartJs($aData[$CNF['FIELD_AUTHOR']], $this->_oConfig->getName(), $aData[$CNF['FIELD_ID']], 1);
+        $sJsCode = '';
+        $oPayment = BxDolPayments::getInstance();
+
+        $aTmplVarsSingle = array();
+        $bSingle = (float)$aData[$CNF['FIELD_PRICE_SINGLE']] != 0;
+        if($bSingle) {
+        	list($sJsCode, $sBuyOnclick) = $oPayment->getAddToCartJs($aData[$CNF['FIELD_AUTHOR']], $this->_oConfig->getName(), $aData[$CNF['FIELD_ID']], 1);
+
+        	$aTmplVarsSingle = array(
+        		'buy_onclick' => $sBuyOnclick,
+    			'buy' => _t('_bx_market_txt_get_for_single', $this->_aCurrency['sign'], $aData[$CNF['FIELD_PRICE_SINGLE']]),
+        	);
+        }
+        
+        
+        $aTmplVarsRecurring = array();
+        $bRecurring = $this->_oDb->getParam($CNF['OPTION_ENABLE_RECURRING']) == 'on' && (float)$aData[$CNF['FIELD_PRICE_RECURRING']] != 0;
+        if($bRecurring) {
+        	list($sJsCode, $sRecurringOnclick) = $oPayment->getSubscribeJs($aData[$CNF['FIELD_AUTHOR']], $this->_oConfig->getName(), $aData[$CNF['FIELD_ID']], 1);
+
+        	$aTmplVarsRecurring = array(
+        		'recurring_onclick' => $sRecurringOnclick,
+        		'recurring' => _t('_bx_market_txt_get_for_recurring', $this->_aCurrency['sign'], $aData[$CNF['FIELD_PRICE_RECURRING']]),
+        	);
+        }
 
 
     	return $this->parseHtmlByContent(parent::entryText($aData), array(
     	return $this->parseHtmlByContent(parent::entryText($aData), array(
     		'title_attr' => bx_html_attribute(isset($aData[$CNF['FIELD_TITLE']]) ? $aData[$CNF['FIELD_TITLE']] : ''),
     		'title_attr' => bx_html_attribute(isset($aData[$CNF['FIELD_TITLE']]) ? $aData[$CNF['FIELD_TITLE']] : ''),
     		'thumb_url' => $sThumbUrl,
     		'thumb_url' => $sThumbUrl,
-    		'buy_onclick' => $sBuyOnclick,
-    		'buy' => _t('_bx_market_txt_get_for_fixed', $this->_aCurrency['sign'], $aData[$CNF['FIELD_PRICE']]),
-    		'screenshots' => $this->getScreenshots($aData)
+    		'bx_if:show_single' => array(
+    			'condition' => $bSingle,
+    			'content' => $aTmplVarsSingle
+    		),
+    		'bx_if:show_recurring' => array(
+    			'condition' => $bRecurring,
+    			'content' => $aTmplVarsRecurring
+    		),
+    		'bx_if:show_free' => array(
+    			'condition' => !$bSingle && !$bRecurring,
+    			'content' => array()
+    		),
+    		'screenshots' => $this->getScreenshots($aData),
+    		'js_code' => $sJsCode
     	));
     	));
     }
     }
 
 
@@ -129,9 +164,27 @@ class BxMarketTemplate extends BxBaseModTextTemplate
 
 
     	$aUnit = parent::getUnit($aData, $aParams);
     	$aUnit = parent::getUnit($aData, $aParams);
 
 
-    	$aUnit['entry_price'] = $aData[$CNF['FIELD_PRICE']];
-    	$aUnit['currency_sign'] = $this->_aCurrency['sign'];
-    	$aUnit['currency_code'] = $this->_aCurrency['code'];
+    	$bSingle = (float)$aData[$CNF['FIELD_PRICE_SINGLE']] != 0;
+    	$bRecurring = (float)$aData[$CNF['FIELD_PRICE_RECURRING']] != 0;
+    	
+    	$aUnit = array_merge($aUnit, array(
+    		'bx_if:show_single' => array(
+    			'condition' => $bSingle,
+    			'content' => array(
+    				'entry_price_single' => _t('_bx_market_txt_price_single', $this->_aCurrency['sign'], $aData[$CNF['FIELD_PRICE_SINGLE']])
+    			)
+    		),
+    		'bx_if:show_recurring' => array(
+    			'condition' => $bRecurring,
+    			'content' => array(
+    				'entry_price_recurring' => _t('_bx_market_txt_price_recurring', $this->_aCurrency['sign'], $aData[$CNF['FIELD_PRICE_RECURRING']])
+    			)
+    		),
+    		'bx_if:show_free' => array(
+    			'condition' => !$bSingle && !$bRecurring,
+    			'content' => array()
+    		),
+    	));
 
 
     	return $aUnit;
     	return $aUnit;
     }
     }

+ 19 - 5
modules/boonex/market/install/langs/en.xml

@@ -4,6 +4,7 @@
 	<string name="_bx_market"><![CDATA[Market]]></string>
 	<string name="_bx_market"><![CDATA[Market]]></string>
 	<string name="_bx_market_cmts"><![CDATA[Market's Reviews]]></string>
 	<string name="_bx_market_cmts"><![CDATA[Market's Reviews]]></string>
 
 
+	<string name="_bx_market_option_enable_recurring"><![CDATA[Allow to sell subscriptions]]></string>
 	<string name="_bx_market_option_summary_chars"><![CDATA[Number of characters in auto-cropped product summary]]></string>
 	<string name="_bx_market_option_summary_chars"><![CDATA[Number of characters in auto-cropped product summary]]></string>
 	<string name="_bx_market_option_plain_summary_chars"><![CDATA[Number of characters in plain product description when product hasn't thumb]]></string>
 	<string name="_bx_market_option_plain_summary_chars"><![CDATA[Number of characters in plain product description when product hasn't thumb]]></string>
 	<string name="_bx_market_option_per_page_browse"><![CDATA[Number of items per page]]></string>
 	<string name="_bx_market_option_per_page_browse"><![CDATA[Number of items per page]]></string>
@@ -21,12 +22,18 @@
 	<string name="_bx_market_form_entry_input_sys_title"><![CDATA[Title]]></string>
 	<string name="_bx_market_form_entry_input_sys_title"><![CDATA[Title]]></string>
 	<string name="_bx_market_form_entry_input_title"><![CDATA[Title]]></string>
 	<string name="_bx_market_form_entry_input_title"><![CDATA[Title]]></string>
 	<string name="_bx_market_form_entry_input_title_err"><![CDATA[Title is essential. Please, fill in this field]]></string>
 	<string name="_bx_market_form_entry_input_title_err"><![CDATA[Title is essential. Please, fill in this field]]></string>
+	<string name="_bx_market_form_entry_input_sys_name"><![CDATA[Name]]></string>
+	<string name="_bx_market_form_entry_input_name"><![CDATA[Name]]></string>
+	<string name="_bx_market_form_entry_input_name_err"><![CDATA[Name should be unique and is needed for internal usage. Please, fill in this field]]></string>
 	<string name="_bx_market_form_entry_input_sys_cat"><![CDATA[Category]]></string>
 	<string name="_bx_market_form_entry_input_sys_cat"><![CDATA[Category]]></string>
 	<string name="_bx_market_form_entry_input_cat"><![CDATA[Category]]></string>
 	<string name="_bx_market_form_entry_input_cat"><![CDATA[Category]]></string>
     <string name="_bx_market_form_entry_input_cat_err"><![CDATA[Please select category]]></string>
     <string name="_bx_market_form_entry_input_cat_err"><![CDATA[Please select category]]></string>
-    <string name="_bx_market_form_entry_input_sys_price"><![CDATA[Monthly price]]></string>
-	<string name="_bx_market_form_entry_input_price"><![CDATA[Monthly price]]></string>
-    <string name="_bx_market_form_entry_input_price_err"><![CDATA[Please select price]]></string>
+    <string name="_bx_market_form_entry_input_sys_price_single"><![CDATA[Price]]></string>
+	<string name="_bx_market_form_entry_input_price_single"><![CDATA[Price]]></string>
+    <string name="_bx_market_form_entry_input_price_single_inf"><![CDATA[Leave empty to make the product free.]]></string>
+    <string name="_bx_market_form_entry_input_sys_price_recurring"><![CDATA[Monthly price]]></string>
+	<string name="_bx_market_form_entry_input_price_recurring"><![CDATA[Monthly price]]></string>
+    <string name="_bx_market_form_entry_input_price_recurring_inf"><![CDATA[Leave empty to make the product free.]]></string>
 	<string name="_bx_market_form_entry_input_sys_text"><![CDATA[Text]]></string>
 	<string name="_bx_market_form_entry_input_sys_text"><![CDATA[Text]]></string>
 	<string name="_bx_market_form_entry_input_text"><![CDATA[Text]]></string>
 	<string name="_bx_market_form_entry_input_text"><![CDATA[Text]]></string>
 	<string name="_bx_market_form_entry_input_text_err"><![CDATA[Text field can't be empty]]></string>
 	<string name="_bx_market_form_entry_input_text_err"><![CDATA[Text field can't be empty]]></string>
@@ -140,6 +147,8 @@
     <string name="_bx_market_menu_item_title_delete_entry"><![CDATA[Delete Product]]></string>
     <string name="_bx_market_menu_item_title_delete_entry"><![CDATA[Delete Product]]></string>
     <string name="_bx_market_menu_item_title_system_add_to_cart"><![CDATA[Add to Cart]]></string>
     <string name="_bx_market_menu_item_title_system_add_to_cart"><![CDATA[Add to Cart]]></string>
     <string name="_bx_market_menu_item_title_add_to_cart"><![CDATA[Add to Cart]]></string>
     <string name="_bx_market_menu_item_title_add_to_cart"><![CDATA[Add to Cart]]></string>
+    <string name="_bx_market_menu_item_title_system_subscribe"><![CDATA[Subscribe]]></string>
+    <string name="_bx_market_menu_item_title_subscribe"><![CDATA[Subscribe]]></string>
     <string name="_bx_market_menu_item_title_system_download"><![CDATA[Download]]></string>
     <string name="_bx_market_menu_item_title_system_download"><![CDATA[Download]]></string>
     <string name="_bx_market_menu_item_title_download"><![CDATA[Download]]></string>
     <string name="_bx_market_menu_item_title_download"><![CDATA[Download]]></string>
     <string name="_bx_market_menu_item_title_system_view_entry"><![CDATA[View Product]]></string>
     <string name="_bx_market_menu_item_title_system_view_entry"><![CDATA[View Product]]></string>
@@ -228,6 +237,7 @@
     <string name="_bx_market_cat_video"><![CDATA[Video]]></string>
     <string name="_bx_market_cat_video"><![CDATA[Video]]></string>
 
 
     <string name="_bx_market_pre_lists_prices"><![CDATA[Product prices]]></string>
     <string name="_bx_market_pre_lists_prices"><![CDATA[Product prices]]></string>
+    <string name="_bx_market_cat_price_0"><![CDATA[None]]></string>
     <string name="_bx_market_cat_price_1"><![CDATA[1]]></string>
     <string name="_bx_market_cat_price_1"><![CDATA[1]]></string>
     <string name="_bx_market_cat_price_2"><![CDATA[2]]></string>
     <string name="_bx_market_cat_price_2"><![CDATA[2]]></string>
     <string name="_bx_market_cat_price_3"><![CDATA[3]]></string>
     <string name="_bx_market_cat_price_3"><![CDATA[3]]></string>
@@ -249,6 +259,10 @@
     <string name="_bx_market_txt_updated"><![CDATA[Updated:]]></string>
     <string name="_bx_market_txt_updated"><![CDATA[Updated:]]></string>
     <string name="_bx_market_txt_joined"><![CDATA[Joined:]]></string>
     <string name="_bx_market_txt_joined"><![CDATA[Joined:]]></string>
     <string name="_bx_market_txt_last_active"><![CDATA[Last Active:]]></string>
     <string name="_bx_market_txt_last_active"><![CDATA[Last Active:]]></string>
-    <string name="_bx_market_txt_get_for_fixed"><![CDATA[Get for {0}{1}]]></string>
-    <string name="_bx_market_txt_get_for_per_month"><![CDATA[Get for {0}{1}/month]]></string>
+    <string name="_bx_market_txt_get_for_single"><![CDATA[Get for {0}{1}]]></string>
+    <string name="_bx_market_txt_price_single"><![CDATA[{0}{1}]]></string>
+    <string name="_bx_market_txt_get_for_recurring"><![CDATA[Get for {0}{1}/month]]></string>
+    <string name="_bx_market_txt_price_recurring"><![CDATA[{0}{1}/mo]]></string>
+    <string name="_bx_market_txt_or"><![CDATA[or]]></string>
+    <string name="_bx_market_txt_get_for_free"><![CDATA[Free]]></string>
 </resources>
 </resources>

+ 7 - 5
modules/boonex/market/install/sql/enable.sql

@@ -10,10 +10,11 @@ VALUES (@iTypeId, 'bx_market', '_bx_market', 1);
 SET @iCategId = LAST_INSERT_ID();
 SET @iCategId = LAST_INSERT_ID();
 
 
 INSERT INTO `sys_options` (`name`, `value`, `category_id`, `caption`, `type`, `check`, `check_error`, `extra`, `order`) VALUES
 INSERT INTO `sys_options` (`name`, `value`, `category_id`, `caption`, `type`, `check`, `check_error`, `extra`, `order`) VALUES
-('bx_market_summary_chars', '700', @iCategId, '_bx_market_option_summary_chars', 'digit', '', '', '', 1),
-('bx_market_plain_summary_chars', '240', @iCategId, '_bx_market_option_plain_summary_chars', 'digit', '', '', '', 2),
-('bx_market_per_page_browse', '12', @iCategId, '_bx_market_option_per_page_browse', 'digit', '', '', '', 10),
-('bx_market_rss_num', '10', @iCategId, '_bx_market_option_rss_num', 'digit', '', '', '', 20);
+('bx_market_enable_recurring', 'on', @iCategId, '_bx_market_option_enable_recurring', 'checkbox', '', '', '', 1),
+('bx_market_summary_chars', '700', @iCategId, '_bx_market_option_summary_chars', 'digit', '', '', '', 10),
+('bx_market_plain_summary_chars', '240', @iCategId, '_bx_market_option_plain_summary_chars', 'digit', '', '', '', 11),
+('bx_market_per_page_browse', '12', @iCategId, '_bx_market_option_per_page_browse', 'digit', '', '', '', 20),
+('bx_market_rss_num', '10', @iCategId, '_bx_market_option_rss_num', 'digit', '', '', '', 21);
 
 
 -- PAGE: create entry
 -- PAGE: create entry
 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 
 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 
@@ -174,7 +175,8 @@ INSERT INTO `sys_menu_items`(`set_name`, `module`, `name`, `title_system`, `titl
 ('bx_market_view', 'bx_market', 'edit-product', '_bx_market_menu_item_title_system_edit_entry', '_bx_market_menu_item_title_edit_entry', 'page.php?i=edit-product&id={content_id}', '', '', 'pencil', '', 2147483647, 1, 0, 1),
 ('bx_market_view', 'bx_market', 'edit-product', '_bx_market_menu_item_title_system_edit_entry', '_bx_market_menu_item_title_edit_entry', 'page.php?i=edit-product&id={content_id}', '', '', 'pencil', '', 2147483647, 1, 0, 1),
 ('bx_market_view', 'bx_market', 'delete-product', '_bx_market_menu_item_title_system_delete_entry', '_bx_market_menu_item_title_delete_entry', 'page.php?i=delete-product&id={content_id}', '', '', 'remove', '', 2147483647, 1, 0, 2),
 ('bx_market_view', 'bx_market', 'delete-product', '_bx_market_menu_item_title_system_delete_entry', '_bx_market_menu_item_title_delete_entry', 'page.php?i=delete-product&id={content_id}', '', '', 'remove', '', 2147483647, 1, 0, 2),
 ('bx_market_view', 'bx_market', 'download', '_bx_market_menu_item_title_system_download', '_bx_market_menu_item_title_download', 'page.php?i=download-product&id={content_id}', '', '', 'download', '', 2147483647, 1, 0, 3),
 ('bx_market_view', 'bx_market', 'download', '_bx_market_menu_item_title_system_download', '_bx_market_menu_item_title_download', 'page.php?i=download-product&id={content_id}', '', '', 'download', '', 2147483647, 1, 0, 3),
-('bx_market_view', 'bx_market', 'add-to-cart', '_bx_market_menu_item_title_system_add_to_cart', '_bx_market_menu_item_title_add_to_cart', 'javascript:void(0);', 'javascript:{add_to_cart_onclick}', '', 'cart-plus', '', 2147483647, 1, 0, 4);
+('bx_market_view', 'bx_market', 'add-to-cart', '_bx_market_menu_item_title_system_add_to_cart', '_bx_market_menu_item_title_add_to_cart', 'javascript:void(0);', 'javascript:{add_to_cart_onclick}', '', 'cart-plus', '', 2147483647, 1, 0, 4),
+('bx_market_view', 'bx_market', 'subscribe', '_bx_market_menu_item_title_system_subscribe', '_bx_market_menu_item_title_subscribe', 'javascript:void(0);', 'javascript:{subscribe_onclick}', '', 'rss', '', 2147483647, 1, 0, 5);
 
 
 
 
 -- MENU: actions menu for my entries
 -- MENU: actions menu for my entries

+ 51 - 36
modules/boonex/market/install/sql/install.sql

@@ -1,16 +1,18 @@
 
 
 -- TABLE: entries
 -- TABLE: entries
 CREATE TABLE IF NOT EXISTS `bx_market_products` (
 CREATE TABLE IF NOT EXISTS `bx_market_products` (
-  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
-  `author` int(10) unsigned NOT NULL,
-  `added` int(11) NOT NULL,
-  `changed` int(11) NOT NULL,
-  `thumb` int(11) NOT NULL,
-  `package` int(11) NOT NULL,
+  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
+  `author` int(11) unsigned NOT NULL default '0',
+  `added` int(11) NOT NULL default '0',
+  `changed` int(11) NOT NULL default '0',
+  `thumb` int(11) NOT NULL default '0',
+  `package` int(11) NOT NULL default '0',
+  `name` varchar(255) NOT NULL,
   `title` varchar(255) NOT NULL,
   `title` varchar(255) NOT NULL,
   `text` text NOT NULL,
   `text` text NOT NULL,
   `cat` int(11) NOT NULL,
   `cat` int(11) NOT NULL,
-  `price` int(11) NOT NULL,
+  `price_single` float NOT NULL default '0',
+  `price_recurring` int(11) NOT NULL default '0',
   `views` int(11) NOT NULL default '0',
   `views` int(11) NOT NULL default '0',
   `rate` float NOT NULL default '0',
   `rate` float NOT NULL default '0',
   `votes` int(11) NOT NULL default '0',
   `votes` int(11) NOT NULL default '0',
@@ -22,16 +24,18 @@ CREATE TABLE IF NOT EXISTS `bx_market_products` (
   `allow_vote_to` varchar(32) NOT NULL DEFAULT 'c',
   `allow_vote_to` varchar(32) NOT NULL DEFAULT 'c',
   `status` enum('active','hidden') NOT NULL DEFAULT 'active',
   `status` enum('active','hidden') NOT NULL DEFAULT 'active',
   PRIMARY KEY (`id`),
   PRIMARY KEY (`id`),
+  UNIQUE KEY `name` (`name`),
   FULLTEXT KEY `title_text` (`title`,`text`)
   FULLTEXT KEY `title_text` (`title`,`text`)
 );
 );
 
 
--- TABLE: customers
-CREATE TABLE IF NOT EXISTS `bx_market_customers` (
+-- TABLE: licenses
+CREATE TABLE IF NOT EXISTS `bx_market_licenses` (
   `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
   `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
   `client_id` int(11) unsigned NOT NULL default '0',
   `client_id` int(11) unsigned NOT NULL default '0',
   `product_id` int(11) unsigned NOT NULL default '0',
   `product_id` int(11) unsigned NOT NULL default '0',
-  `order_id` varchar(32) collate utf8_unicode_ci NOT NULL default '',
   `count` int(11) unsigned NOT NULL default '0',
   `count` int(11) unsigned NOT NULL default '0',
+  `order` varchar(32) collate utf8_unicode_ci NOT NULL default '',
+  `license` varchar(32) collate utf8_unicode_ci NOT NULL default '',
   `date` int(11) unsigned NOT NULL default '0',
   `date` int(11) unsigned NOT NULL default '0',
   PRIMARY KEY (`id`),
   PRIMARY KEY (`id`),
   KEY `product_id` (`product_id`,`client_id`)
   KEY `product_id` (`product_id`,`client_id`)
@@ -234,32 +238,38 @@ INSERT INTO `sys_form_inputs`(`object`, `module`, `name`, `value`, `values`, `ch
 ('bx_market', 'bx_market', 'files', '', '', 0, 'files', '_bx_market_form_entry_input_sys_files', '_bx_market_form_entry_input_files', '', 0, 0, 0, '', '', '', '', '', '', '', '', 1, 0),
 ('bx_market', 'bx_market', 'files', '', '', 0, 'files', '_bx_market_form_entry_input_sys_files', '_bx_market_form_entry_input_files', '', 0, 0, 0, '', '', '', '', '', '', '', '', 1, 0),
 ('bx_market', 'bx_market', 'text', '', '', 0, 'textarea', '_bx_market_form_entry_input_sys_text', '_bx_market_form_entry_input_text', '', 1, 0, 2, '', '', '', 'Avail', '', '_bx_market_form_entry_input_text_err', 'XssHtml', '', 1, 0),
 ('bx_market', 'bx_market', 'text', '', '', 0, 'textarea', '_bx_market_form_entry_input_sys_text', '_bx_market_form_entry_input_text', '', 1, 0, 2, '', '', '', 'Avail', '', '_bx_market_form_entry_input_text_err', 'XssHtml', '', 1, 0),
 ('bx_market', 'bx_market', 'title', '', '', 0, 'text', '_bx_market_form_entry_input_sys_title', '_bx_market_form_entry_input_title', '', 1, 0, 0, '', '', '', 'Avail', '', '_bx_market_form_entry_input_title_err', 'Xss', '', 1, 0),
 ('bx_market', 'bx_market', 'title', '', '', 0, 'text', '_bx_market_form_entry_input_sys_title', '_bx_market_form_entry_input_title', '', 1, 0, 0, '', '', '', 'Avail', '', '_bx_market_form_entry_input_title_err', 'Xss', '', 1, 0),
+('bx_market', 'bx_market', 'name', '', '', 0, 'text', '_bx_market_form_entry_input_sys_name', '_bx_market_form_entry_input_name', '', 1, 0, 0, '', '', '', 'Avail', '', '_bx_market_form_entry_input_name_err', 'Xss', '', 1, 0),
 ('bx_market', 'bx_market', 'cat', '', '#!bx_market_cats', 0, 'select', '_bx_market_form_entry_input_sys_cat', '_bx_market_form_entry_input_cat', '', 1, 0, 0, '', '', '', 'avail', '', '_bx_market_form_entry_input_cat_err', 'Xss', '', 1, 0),
 ('bx_market', 'bx_market', 'cat', '', '#!bx_market_cats', 0, 'select', '_bx_market_form_entry_input_sys_cat', '_bx_market_form_entry_input_cat', '', 1, 0, 0, '', '', '', 'avail', '', '_bx_market_form_entry_input_cat_err', 'Xss', '', 1, 0),
-('bx_market', 'bx_market', 'price', '', '#!bx_market_prices', 0, 'radio_set', '_bx_market_form_entry_input_sys_price', '_bx_market_form_entry_input_price', '', 1, 0, 0, '', '', '', 'avail', '', '_bx_market_form_entry_input_price_err', 'Xss', '', 1, 0);
+('bx_market', 'bx_market', 'price_single', '', '', 0, 'text', '_bx_market_form_entry_input_sys_price_single', '_bx_market_form_entry_input_price_single', '_bx_market_form_entry_input_price_single_inf', 0, 0, 0, '', '', '', '', '', '', 'Float', '', 1, 0),
+('bx_market', 'bx_market', 'price_recurring', '', '#!bx_market_prices', 0, 'radio_set', '_bx_market_form_entry_input_sys_price_recurring', '_bx_market_form_entry_input_price_recurring', '_bx_market_form_entry_input_price_recurring_inf', 0, 0, 0, '', '', '', '', '', '', 'Float', '', 1, 0);
 
 
 INSERT INTO `sys_form_display_inputs`(`display_name`, `input_name`, `visible_for_levels`, `active`, `order`) VALUES 
 INSERT INTO `sys_form_display_inputs`(`display_name`, `input_name`, `visible_for_levels`, `active`, `order`) VALUES 
 ('bx_market_entry_add', 'delete_confirm', 2147483647, 0, 1),
 ('bx_market_entry_add', 'delete_confirm', 2147483647, 0, 1),
 ('bx_market_entry_add', 'title', 2147483647, 1, 2),
 ('bx_market_entry_add', 'title', 2147483647, 1, 2),
-('bx_market_entry_add', 'cat', 2147483647, 1, 3),
-('bx_market_entry_add', 'text', 2147483647, 1, 4),
-('bx_market_entry_add', 'pictures', 2147483647, 1, 5),
-('bx_market_entry_add', 'files', 2147483647, 1, 6),
-('bx_market_entry_add', 'price', 2147483647, 1, 7),
-('bx_market_entry_add', 'allow_view_to', 2147483647, 1, 8),
-('bx_market_entry_add', 'allow_purchase_to', 2147483647, 1, 9),
-('bx_market_entry_add', 'allow_comment_to', 2147483647, 1, 10),
-('bx_market_entry_add', 'allow_vote_to', 2147483647, 1, 11),
-('bx_market_entry_add', 'location', 2147483647, 1, 12),
-('bx_market_entry_add', 'do_submit', 2147483647, 0, 13),
-('bx_market_entry_add', 'do_publish', 2147483647, 1, 14),
+('bx_market_entry_add', 'name', 2147483647, 1, 3),
+('bx_market_entry_add', 'cat', 2147483647, 1, 4),
+('bx_market_entry_add', 'text', 2147483647, 1, 5),
+('bx_market_entry_add', 'pictures', 2147483647, 1, 6),
+('bx_market_entry_add', 'files', 2147483647, 1, 7),
+('bx_market_entry_add', 'price_single', 2147483647, 1, 8),
+('bx_market_entry_add', 'price_recurring', 2147483647, 1, 9),
+('bx_market_entry_add', 'allow_view_to', 2147483647, 1, 10),
+('bx_market_entry_add', 'allow_purchase_to', 2147483647, 1, 11),
+('bx_market_entry_add', 'allow_comment_to', 2147483647, 1, 12),
+('bx_market_entry_add', 'allow_vote_to', 2147483647, 1, 13),
+('bx_market_entry_add', 'location', 2147483647, 1, 14),
+('bx_market_entry_add', 'do_submit', 2147483647, 0, 15),
+('bx_market_entry_add', 'do_publish', 2147483647, 1, 16),
 ('bx_market_entry_delete', 'location', 2147483647, 0, 0),
 ('bx_market_entry_delete', 'location', 2147483647, 0, 0),
 ('bx_market_entry_delete', 'cat', 2147483647, 0, 0),
 ('bx_market_entry_delete', 'cat', 2147483647, 0, 0),
-('bx_market_entry_delete', 'price', 2147483647, 0, 0),
+('bx_market_entry_delete', 'price_single', 2147483647, 0, 0),
+('bx_market_entry_delete', 'price_recurring', 2147483647, 0, 0),
 ('bx_market_entry_delete', 'pictures', 2147483647, 0, 0),
 ('bx_market_entry_delete', 'pictures', 2147483647, 0, 0),
 ('bx_market_entry_delete', 'files', 2147483647, 0, 0),
 ('bx_market_entry_delete', 'files', 2147483647, 0, 0),
 ('bx_market_entry_delete', 'text', 2147483647, 0, 0),
 ('bx_market_entry_delete', 'text', 2147483647, 0, 0),
 ('bx_market_entry_delete', 'do_publish', 2147483647, 0, 0),
 ('bx_market_entry_delete', 'do_publish', 2147483647, 0, 0),
 ('bx_market_entry_delete', 'title', 2147483647, 0, 0),
 ('bx_market_entry_delete', 'title', 2147483647, 0, 0),
+('bx_market_entry_delete', 'name', 2147483647, 0, 0),
 ('bx_market_entry_delete', 'allow_view_to', 2147483647, 0, 0),
 ('bx_market_entry_delete', 'allow_view_to', 2147483647, 0, 0),
 ('bx_market_entry_delete', 'allow_purchase_to', 2147483647, 0, 0),
 ('bx_market_entry_delete', 'allow_purchase_to', 2147483647, 0, 0),
 ('bx_market_entry_delete', 'allow_comment_to', 2147483647, 0, 0),
 ('bx_market_entry_delete', 'allow_comment_to', 2147483647, 0, 0),
@@ -269,26 +279,30 @@ INSERT INTO `sys_form_display_inputs`(`display_name`, `input_name`, `visible_for
 ('bx_market_entry_edit', 'do_publish', 2147483647, 0, 1),
 ('bx_market_entry_edit', 'do_publish', 2147483647, 0, 1),
 ('bx_market_entry_edit', 'delete_confirm', 2147483647, 0, 2),
 ('bx_market_entry_edit', 'delete_confirm', 2147483647, 0, 2),
 ('bx_market_entry_edit', 'title', 2147483647, 1, 3),
 ('bx_market_entry_edit', 'title', 2147483647, 1, 3),
-('bx_market_entry_edit', 'cat', 2147483647, 1, 4),
-('bx_market_entry_edit', 'text', 2147483647, 1, 5),
-('bx_market_entry_edit', 'pictures', 2147483647, 1, 6),
-('bx_market_entry_edit', 'files', 2147483647, 1, 7),
-('bx_market_entry_edit', 'price', 2147483647, 1, 8),
-('bx_market_entry_edit', 'allow_view_to', 2147483647, 1, 9),
-('bx_market_entry_edit', 'allow_purchase_to', 2147483647, 1, 10),
-('bx_market_entry_edit', 'allow_comment_to', 2147483647, 1, 11),
-('bx_market_entry_edit', 'allow_vote_to', 2147483647, 1, 12),
-('bx_market_entry_edit', 'location', 2147483647, 1, 13),
-('bx_market_entry_edit', 'do_submit', 2147483647, 1, 14),
+('bx_market_entry_edit', 'name', 2147483647, 1, 4),
+('bx_market_entry_edit', 'cat', 2147483647, 1, 5),
+('bx_market_entry_edit', 'text', 2147483647, 1, 6),
+('bx_market_entry_edit', 'pictures', 2147483647, 1, 7),
+('bx_market_entry_edit', 'files', 2147483647, 1, 8),
+('bx_market_entry_edit', 'price_single', 2147483647, 1, 9),
+('bx_market_entry_edit', 'price_recurring', 2147483647, 1, 10),
+('bx_market_entry_edit', 'allow_view_to', 2147483647, 1, 11),
+('bx_market_entry_edit', 'allow_purchase_to', 2147483647, 1, 12),
+('bx_market_entry_edit', 'allow_comment_to', 2147483647, 1, 13),
+('bx_market_entry_edit', 'allow_vote_to', 2147483647, 1, 14),
+('bx_market_entry_edit', 'location', 2147483647, 1, 15),
+('bx_market_entry_edit', 'do_submit', 2147483647, 1, 16),
 ('bx_market_entry_view', 'location', 2147483647, 0, 0),
 ('bx_market_entry_view', 'location', 2147483647, 0, 0),
 ('bx_market_entry_view', 'cat', 2147483647, 0, 0),
 ('bx_market_entry_view', 'cat', 2147483647, 0, 0),
-('bx_market_entry_view', 'price', 2147483647, 0, 0),
+('bx_market_entry_view', 'price_single', 2147483647, 0, 0),
+('bx_market_entry_view', 'price_recurring', 2147483647, 0, 0),
 ('bx_market_entry_view', 'pictures', 2147483647, 0, 0),
 ('bx_market_entry_view', 'pictures', 2147483647, 0, 0),
 ('bx_market_entry_view', 'files', 2147483647, 0, 0),
 ('bx_market_entry_view', 'files', 2147483647, 0, 0),
 ('bx_market_entry_view', 'delete_confirm', 2147483647, 0, 0),
 ('bx_market_entry_view', 'delete_confirm', 2147483647, 0, 0),
 ('bx_market_entry_view', 'text', 2147483647, 1, 0),
 ('bx_market_entry_view', 'text', 2147483647, 1, 0),
 ('bx_market_entry_view', 'do_publish', 2147483647, 0, 0),
 ('bx_market_entry_view', 'do_publish', 2147483647, 0, 0),
 ('bx_market_entry_view', 'title', 2147483647, 0, 0),
 ('bx_market_entry_view', 'title', 2147483647, 0, 0),
+('bx_market_entry_view', 'name', 2147483647, 0, 0),
 ('bx_market_entry_view', 'do_submit', 2147483647, 0, 0),
 ('bx_market_entry_view', 'do_submit', 2147483647, 0, 0),
 ('bx_market_entry_view', 'allow_view_to', 2147483647, 0, 0),
 ('bx_market_entry_view', 'allow_view_to', 2147483647, 0, 0),
 ('bx_market_entry_view', 'allow_purchase_to', 2147483647, 0, 0),
 ('bx_market_entry_view', 'allow_purchase_to', 2147483647, 0, 0),
@@ -342,6 +356,7 @@ INSERT INTO `sys_form_pre_values`(`Key`, `Value`, `Order`, `LKey`, `LKey2`) VALU
 ('bx_market_cats', '38', 38, '_bx_market_cat_translations', ''),
 ('bx_market_cats', '38', 38, '_bx_market_cat_translations', ''),
 ('bx_market_cats', '39', 39, '_bx_market_cat_video', ''),
 ('bx_market_cats', '39', 39, '_bx_market_cat_video', ''),
 
 
+('bx_market_prices', '0', 0, '_bx_market_cat_price_0', ''),
 ('bx_market_prices', '1', 1, '_bx_market_cat_price_1', ''),
 ('bx_market_prices', '1', 1, '_bx_market_cat_price_1', ''),
 ('bx_market_prices', '2', 2, '_bx_market_cat_price_2', ''),
 ('bx_market_prices', '2', 2, '_bx_market_cat_price_2', ''),
 ('bx_market_prices', '3', 3, '_bx_market_cat_price_3', ''),
 ('bx_market_prices', '3', 3, '_bx_market_cat_price_3', ''),

+ 1 - 1
modules/boonex/market/install/sql/uninstall.sql

@@ -1,6 +1,6 @@
 
 
 -- TABLES
 -- TABLES
-DROP TABLE IF EXISTS `bx_market_products`, `bx_market_customers`, `bx_market_files`, `bx_market_files2products`, `bx_market_photos`, `bx_market_photos2products`, `bx_market_photos_resized`, `bx_market_cmts`, `bx_market_votes`, `bx_market_votes_track`, `bx_market_views_track`, `bx_market_meta_keywords`, `bx_market_meta_locations`, `bx_market_reports`, `bx_market_reports_track`;
+DROP TABLE IF EXISTS `bx_market_products`, `bx_market_licenses`, `bx_market_files`, `bx_market_files2products`, `bx_market_photos`, `bx_market_photos2products`, `bx_market_photos_resized`, `bx_market_cmts`, `bx_market_votes`, `bx_market_votes_track`, `bx_market_views_track`, `bx_market_meta_keywords`, `bx_market_meta_locations`, `bx_market_reports`, `bx_market_reports_track`;
 
 
 -- STORAGES & TRANSCODERS
 -- STORAGES & TRANSCODERS
 DELETE FROM `sys_objects_storage` WHERE `object` IN('bx_market_files', 'bx_market_photos', 'bx_market_photos_resized');
 DELETE FROM `sys_objects_storage` WHERE `object` IN('bx_market_files', 'bx_market_photos', 'bx_market_photos_resized');

+ 35 - 2
modules/boonex/market/js/entry.js

@@ -14,9 +14,42 @@ function BxMarketEntry(oOptions) {
     });
     });
 }
 }
 
 
+BxMarketEntry.prototype.updateName = function(sTitleId, sNameId) {
+	var sTitle = jQuery("[name='" + sTitleId + "']").val();
+	sTitle = sTitle.replace(/[^A-Za-z0-9_]/g, '-');
+	sTitle = sTitle.replace(/[-]{2,}/g, '-');
+
+	jQuery("[name='" + sNameId + "']").val(sTitle.toLowerCase());
+};
+
+BxMarketEntry.prototype.checkName = function(sTitleId, sNameId) {
+	var oDate = new Date();
+
+	var sTitle = jQuery("[name='" + sTitleId + "']").val();
+	if(sTitle.length == 0)
+		return;
+
+	jQuery.get(
+		this._sActionsUrl + 'check_name',
+		{
+			title: sTitle,
+    		_t: oDate.getTime()
+    	},
+    	function(oData) {
+    		if(!oData || oData.name == undefined)
+    			return;
+
+    		jQuery("[name='" + sNameId + "']").val(oData.name);
+    	},
+    	'json'
+	);
+};
+
 BxMarketEntry.prototype.initScreenshots = function() {
 BxMarketEntry.prototype.initScreenshots = function() {
 	var oItems = jQuery(".bx-market-screenshots .bx-market-ss-item");
 	var oItems = jQuery(".bx-market-screenshots .bx-market-ss-item");
-	
+	if(oItems.length == 0)
+		return;
+
 	var iWidth = oItems.width();
 	var iWidth = oItems.width();
 	var iWidthOuter = oItems.outerWidth();
 	var iWidthOuter = oItems.outerWidth();
 	var bBusy = false;
 	var bBusy = false;
@@ -30,7 +63,7 @@ BxMarketEntry.prototype.initScreenshots = function() {
 
 
 	if(oItems.length <= 2)
 	if(oItems.length <= 2)
 		return;
 		return;
-	console.log(iWidth, iWidthOuter);
+
 	jQuery(".bx-market-ss-left").bind('click', function() {
 	jQuery(".bx-market-ss-left").bind('click', function() {
 		if(bBusy || parseInt(jQuery(".bx-market-ss-cnt").css('left')) >= 0)
 		if(bBusy || parseInt(jQuery(".bx-market-ss-cnt").css('left')) >= 0)
 			return;
 			return;

+ 6 - 1
modules/boonex/market/template/css/entry.css

@@ -25,7 +25,12 @@ div.bx-market-ech-info-cnt {
 div.bx-market-ech-info .bx-market-ech-title {
 div.bx-market-ech-info .bx-market-ech-title {
 	margin: 0px;
 	margin: 0px;
 }
 }
-
+div.bx-market-ech-info .bx-market-ech-paid {
+	display: inline-block;
+	float: none;
+	vertical-align: top;
+}
+div.bx-market-ech-info .bx-market-ech-free {}
 
 
 /*--- Entry Screenshots ---*/
 /*--- Entry Screenshots ---*/
 div.bx-market-screenshots {
 div.bx-market-screenshots {

+ 5 - 2
modules/boonex/market/template/css/main.css

@@ -13,12 +13,15 @@ div.bx-market-ui-cell {
 	vertical-align: top;
 	vertical-align: top;
 }
 }
 div.bx-market-uic-wide {
 div.bx-market-uic-wide {
-	width: 68%;
+	width: 49%;
 }
 }
 div.bx-market-uic-narrow {
 div.bx-market-uic-narrow {
-	width: 30%;
+	width: 49%;
 	text-align: right;
 	text-align: right;
 }
 }
+.bx-market-ui-price-or:first-child {
+	display: none;
+}
 
 
 /*--- Defaults ---*/
 /*--- Defaults ---*/
 .bx-market-thumb-size {
 .bx-market-thumb-size {

+ 12 - 3
modules/boonex/market/template/entry-text.html

@@ -6,12 +6,21 @@
     	<div class="bx-market-ech-info bx-market-thumb-size-min-height bx-market-thumb-size-left-indent">
     	<div class="bx-market-ech-info bx-market-thumb-size-min-height bx-market-thumb-size-left-indent">
     		<div class="bx-market-ech-info-cnt">
     		<div class="bx-market-ech-info-cnt">
 	    		<h1 class="bx-market-ech-title">__title__</h1>
 	    		<h1 class="bx-market-ech-title">__title__</h1>
-	    		<div class="bx-def-margin-sec-top">
-	    			<a class="bx-btn" href="javascript:void(0)" onclick="javascript:__buy_onclick__">__buy__</a>
+	    		<div class="bx-market-ech-price bx-def-margin-sec-top">
+	    			<bx_if:show_single>
+	    				<a class="bx-market-ech-paid bx-btn bx-def-margin-sec-right" href="javascript:void(0)" onclick="javascript:__buy_onclick__">__buy__</a>
+	    			</bx_if:show_single>
+	    			<bx_if:show_recurring>
+						<a class="bx-market-ech-paid bx-btn" href="javascript:void(0)" onclick="javascript:__recurring_onclick__">__recurring__</a>
+		    		</bx_if:show_recurring>
+		    		<bx_if:show_free>
+		    			<span class="bx-market-ech-free bx-def-font-bold col-green3"><bx_text:_bx_market_txt_get_for_free /></span>
+		    		</bx_if:show_free>
 	    		</div>
 	    		</div>
 	    	</div>
 	    	</div>
     	</div>
     	</div>
     </div>
     </div>
     <div class="bx-market-ec-slideshow bx-def-margin-top">__screenshots__</div>
     <div class="bx-market-ec-slideshow bx-def-margin-top">__screenshots__</div>
     <div class="bx-market-ec-description bx-def-margin-top">__text__</div>
     <div class="bx-market-ec-description bx-def-margin-top">__text__</div>
-</div>
+</div>
+__js_code__

+ 10 - 1
modules/boonex/market/template/unit_gallery.html

@@ -31,7 +31,16 @@
 			        -->
 			        -->
 		        </div>
 		        </div>
 		        <div class="bx-market-ui-cell bx-market-uic-narrow">
 		        <div class="bx-market-ui-cell bx-market-uic-narrow">
-		        	<span class="bx-market-ui-price bx-def-font-semibold col-green3">__currency_sign____entry_price__</span>
+		        	<bx_if:show_single>
+		        		<span class="bx-market-ui-price col-green3">__entry_price_single__</span>
+		        	</bx_if:show_single>
+		        	<bx_if:show_recurring>
+		        		<span class="bx-market-ui-price-or bx-def-font-grayed"><bx_text:_bx_market_txt_or /></span>
+		        		<span class="bx-market-ui-price col-green3">__entry_price_recurring__</span>
+		        	</bx_if:show_recurring>
+		        	<bx_if:show_free>
+		        		<span class="bx-market-ui-price bx-def-font-semibold col-green3"><bx_text:_bx_market_txt_get_for_free /></span>
+		        	</bx_if:show_free>
 		        </div>
 		        </div>
 		    </div>
 		    </div>
 		</div>
 		</div>