Просмотр исходного кода

Ticket #4397 - Groups: Add Recommended groups functionality.

AntonLV 3 лет назад
Родитель
Сommit
dad5571d14

+ 20 - 18
inc/classes/BxDolRecommendation.php

@@ -147,14 +147,8 @@ class BxDolRecommendation extends BxDolFactory implements iBxDolFactoryObject
 
         $aCriterionItems = [];
         foreach($this->_aCriteria as $sCriterion => $aCriterion) {
-            $iCriterionWeight = (float)$aCriterion['weight'];
-
-            $aParams = ['profile_id' => $iProfileId];
-            if(!empty($aCriterion['params'])) {
-                $aCriterionParams = unserialize($aCriterion['params']);
-                if(!empty($aCriterionParams) && is_array($aCriterionParams))
-                    $aParams = array_merge($aParams, $aCriterionParams);
-            }
+            $aCriterionParams = $this->_getCriterionParams($iProfileId, $aCriterion['params']);
+            $iCriterionWeight = (float)$aCriterion['weight'];           
 
             switch($aCriterion['source_type']) {
                 case 'sql':
@@ -163,7 +157,7 @@ class BxDolRecommendation extends BxDolFactory implements iBxDolFactoryObject
                     if(empty($aCriterion['source']))
                         break;
 
-                    $sQuery = bx_replace_markers($aCriterion['source'], $aParams);
+                    $sQuery = bx_replace_markers($aCriterion['source'], $aCriterionParams);
                     if($this->_aObject['countable'])
                         $sQuery .= ' ORDER BY `value` DESC';
                     $sQuery .= ' LIMIT ' . $iLimit;
@@ -217,6 +211,21 @@ class BxDolRecommendation extends BxDolFactory implements iBxDolFactoryObject
         return str_replace('sys_', 'recom_', $this->_sObject); 
     }
 
+    protected function _getCriterionParams($iProfileId, $aParams)
+    {
+        $aResult = ['profile_id' => $iProfileId];
+        if(empty($aParams))
+            return $aResult;
+
+        if(is_string($aParams))
+            $aParams = unserialize($aParams);
+
+        if(!empty($aParams) && is_array($aParams))
+            $aResult = array_merge($aResult, $aParams);
+
+        return $aResult;
+    }
+
     /**
      * The first variant. Isn't used.
      */
@@ -233,15 +242,8 @@ class BxDolRecommendation extends BxDolFactory implements iBxDolFactoryObject
 
         $aCriterionItems = [];
         foreach($this->_aCriteria as $sCriterion => $aCriterion) {
+            $aCriterionParams = $this->_getCriterionParams($iProfileId, $aCriterion['params']);
             $iCriterionWeight = (float)$aCriterion['weight'];
-
-            $aParams = ['profile_id' => $iProfileId];
-            if(!empty($aCriterion['params'])) {
-                $aCriterionParams = unserialize($aCriterion['params']);
-                if(!empty($aCriterionParams) && is_array($aCriterionParams))
-                    $aParams = array_merge($aParams, $aCriterionParams);
-            }
-
             $iCriterionStart = isset($aStarts[$sCriterion]) ? (int)$aStarts[$sCriterion] : $iStart * $iCriterionWeight;
 
             switch($aCriterion['source_type']) {
@@ -251,7 +253,7 @@ class BxDolRecommendation extends BxDolFactory implements iBxDolFactoryObject
                     if(empty($aCriterion['source']))
                         break;
 
-                    $sQuery = bx_replace_markers($aCriterion['source'], $aParams);
+                    $sQuery = bx_replace_markers($aCriterion['source'], $aCriterionParams);
                     if($this->_aObject['countable'])
                         $sQuery .= ' ORDER BY `value` DESC';
                     $sQuery .= ' LIMIT ' . $iCriterionStart . ', ' . $iPerPage;

+ 2 - 0
modules/base/general/classes/BxBaseModGeneralModule.php

@@ -20,6 +20,7 @@ bx_import('BxDolAcl');
  */
 class BxBaseModGeneralModule extends BxDolModule
 {
+    protected $_bIsApi;
     protected $_iProfileId;
     protected $_aSearchableNamesExcept;
     protected $_aFormParams;
@@ -28,6 +29,7 @@ class BxBaseModGeneralModule extends BxDolModule
     {
         parent::__construct($aModule);
 
+        $this->_bIsApi = bx_is_api();
         $this->_iProfileId = bx_get_logged_profile_id();
         $this->_aSearchableNamesExcept = array(
             'allow_view_to'

+ 10 - 0
modules/base/groups/classes/BxBaseModGroupsMenuSnippetMeta.php

@@ -72,6 +72,16 @@ class BxBaseModGroupsMenuSnippetMeta extends BxBaseModProfileMenuSnippetMeta
         return $this->_getMenuItemConnection($CNF['OBJECT_CONNECTIONS'], 'remove', $aItem);
     }
 
+    protected function _getMenuItemIgnoreJoin($aItem)
+    {
+        $CNF = &$this->_oModule->_oConfig->CNF;
+
+        if(empty($CNF['OBJECT_RECOMMENDATIONS_FANS']))
+            return false;
+
+        return $this->_getMenuItemRecommendation($CNF['OBJECT_RECOMMENDATIONS_FANS'], 'ignore', $aItem);
+    }
+
     protected function _getMenuItemPrivacy($aItem)
     {
         $CNF = &$this->_oModule->_oConfig->CNF;

+ 47 - 1
modules/base/groups/classes/BxBaseModGroupsModule.php

@@ -672,7 +672,53 @@ class BxBaseModGroupsModule extends BxBaseModProfileModule
 
         return $this->_serviceBrowse ('created_entries', array('author' => $iProfileId), BX_DB_PADDING_DEF, $bDisplayEmptyMsg);
     }
-    
+
+    public function serviceBrowseRecommendationsFans ($iProfileId = 0, $aParams = [])
+    {
+        $CNF = &$this->_oConfig->CNF;
+
+        if($this->_bIsApi)
+            $aParams = bx_api_get_browse_params($aParams, true);
+
+        if(!$iProfileId)
+            $iProfileId = bx_get_logged_profile_id();
+        if(!$iProfileId)
+            return '';
+
+        $aParams = array_merge([
+            'empty_message' => false,
+            'start' => 0,
+            'per_page' => 0
+        ], $aParams);
+
+        if(($iStartGet = bx_get('start')) !== false)
+            $aParams['start'] = (int)$iStartGet;
+
+        if(($iPerPageGet = bx_get('per_page')) !== false)
+            $aParams['per_page'] = (int)$iPerPageGet;
+
+        $oRecommendation = BxDolRecommendation::getObjectInstance($CNF['OBJECT_RECOMMENDATIONS_FANS']);
+        if(!$oRecommendation)
+            return false;
+
+        if($this->_bIsApi) {
+            $aData = $oRecommendation->getCodeAPI($iProfileId, $aParams['start'], $aParams['per_page']);
+            $aData = array_merge($aData, [
+                'module' => 'system',
+                'unit' => 'mixed', 
+                'request_url' => '/api.php?r=bx_groups/browse_recommendations_fans&params[]=' . $iProfileId . '&params[]='
+            ]);
+
+            return [bx_api_get_block('browse', $aData)];
+        }
+
+        $sCode = $oRecommendation->getCode($iProfileId, $aParams['start'], $aParams['per_page']);
+        if(!$sCode && $aParams['empty_message'])
+            $sCode = MsgBox(_t(!empty($aParams['empty_message_text']) ? $aParams['empty_message_text'] : '_Empty'));
+
+        return $sCode;
+    }
+
     public function serviceEntityPricing($iProfileId = 0)
     {
         $CNF = &$this->_oConfig->CNF;

+ 49 - 0
modules/base/groups/classes/BxBaseModGroupsRecommendationFans.php

@@ -0,0 +1,49 @@
+<?php defined('BX_DOL') or die('hack attempt');
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ *
+ * @defgroup    BaseGroups Base classes for groups modules
+ * @ingroup     UnaModules
+ * 
+ * @{
+ */
+
+
+class BxBaseModGroupsRecommendationFans extends BxTemplRecommendationProfile
+{
+    protected $_sModule;
+    protected $_oModule;
+
+    public function __construct ($aOptions, $oTemplate = false)
+    {
+    	$this->_oModule = BxDolModule::getInstance($this->_sModule);
+
+        parent::__construct ($aOptions, $oTemplate);
+    }
+
+    protected function _getContextName()
+    {
+        return str_replace('bx_', 'recom_', $this->_sObject); 
+    }
+
+    protected function _getCriterionParams($iProfileId, $aParams)
+    {
+        $aResult = parent::_getCriterionParams($iProfileId, $aParams);
+
+        if(isset($aResult['profile_types']) && empty($aResult['profile_types'])) {
+            $aModules = bx_srv('system', 'get_profiles_modules', [], 'TemplServiceProfiles');
+            if(!empty($aModules) && is_array($aModules)) {
+                $aTypes = [];
+                foreach($aModules as $aModule)
+                    $aTypes[] = $aModule['name'];
+                
+                $aResult['profile_types'] = $this->_oDb->implode_escape($aTypes);
+            }
+        }
+
+        return $aResult;
+    }
+}
+
+/** @} */

+ 1 - 0
modules/boonex/groups/classes/BxGroupsConfig.php

@@ -150,6 +150,7 @@ class BxGroupsConfig extends BxBaseModGroupsConfig
             'OBJECT_GRID_PRICES_MANAGE' => 'bx_groups_prices_manage',
             'OBJECT_GRID_PRICES_VIEW' => 'bx_groups_prices_view',
             'OBJECT_CONNECTIONS' => 'bx_groups_fans',
+            'OBJECT_RECOMMENDATIONS_FANS' => 'bx_groups_fans',
             'OBJECT_UPLOADERS_COVER' => array('bx_groups_cover_crop'),
             'OBJECT_UPLOADERS_PICTURE' => array('bx_groups_picture_crop'),
             'OBJECT_PRE_LIST_ROLES' => 'bx_groups_roles',

+ 22 - 0
modules/boonex/groups/classes/BxGroupsRecommendationFans.php

@@ -0,0 +1,22 @@
+<?php defined('BX_DOL') or die('hack attempt');
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ *
+ * @defgroup    Groups Groups
+ * @ingroup     UnaModules
+ *
+ * @{
+ */
+
+class BxGroupsRecommendationFans extends BxBaseModGroupsRecommendationFans
+{
+    public function __construct ($aOptions, $oTemplate = false)
+    {
+        $this->_sModule = 'bx_groups';
+
+        parent::__construct ($aOptions, $oTemplate);
+    }
+}
+
+/** @} */

+ 5 - 3
modules/boonex/groups/install/langs/en.xml

@@ -183,7 +183,7 @@
 	<string name="_bx_groups_page_block_title_system_manage_administration"><![CDATA[Manage All Groups]]></string>
 	<string name="_bx_groups_page_block_title_manage"><![CDATA[Manage Groups]]></string>
     <string name="_bx_groups_page_block_title_top_profiles"><![CDATA[Top Groups]]></string>
-  <string name="_bx_groups_page_block_title_joined_profiles"><![CDATA[Joined Groups]]></string>
+    <string name="_bx_groups_page_block_title_joined_profiles"><![CDATA[Joined Groups]]></string>
     <string name="_bx_groups_page_block_title_entry_all_actions"><![CDATA[All Actions]]></string>
     <string name="_bx_groups_page_block_title_entry_social_sharing"><![CDATA[Share]]></string>
     <string name="_bx_groups_page_block_title_categories"><![CDATA[Groups Categories]]></string>
@@ -204,9 +204,11 @@
     <string name="_bx_groups_page_block_title_labels_breadcrumbs"><![CDATA[Labels breadcrumbs]]></string>
     <string name="_bx_groups_page_block_title_sys_cover_block"><![CDATA[Cover]]></string>
     <string name="_bx_groups_page_block_title_cover_block"><![CDATA[Cover]]></string>
-    
+    <string name="_bx_groups_page_block_title_sys_recom_fans"><![CDATA[Recommended groups (Join)]]></string>
+    <string name="_bx_groups_page_block_title_recom_fans"><![CDATA[Group Suggestions]]></string>
+
 
-  <string name="_bx_groups_menu_title_submenu"><![CDATA[Groups Submenu]]></string>
+    <string name="_bx_groups_menu_title_submenu"><![CDATA[Groups Submenu]]></string>
     <string name="_bx_groups_menu_set_title_submenu"><![CDATA[Groups Submenu]]></string>
     <string name="_bx_groups_menu_set_title_view_profile_actions"><![CDATA[Group Actions]]></string>
     <string name="_bx_groups_menu_title_view_profile_actions"><![CDATA[Group Actions]]></string>

+ 6 - 0
modules/boonex/groups/install/sql/disable.sql

@@ -31,6 +31,12 @@ DELETE FROM `sys_objects_search` WHERE `ObjectName` = 'bx_groups';
 -- CONNECTIONS
 DELETE FROM `sys_objects_connection` WHERE `object` = 'bx_groups_fans';
 
+-- RECOMMENDATIONS
+SET @iRecFans = (SELECT `id` FROM `sys_objects_recommendation` WHERE `name`='bx_groups_fans' LIMIT 1);
+DELETE FROM `sys_objects_recommendation` WHERE `id`=@iRecFans;
+DELETE FROM `sys_recommendation_criteria` WHERE `object_id`=@iRecFans AND `name` IN ('by_friends', 'by_subscriptions', 'by_fans');
+DELETE FROM `sys_recommendation_data` WHERE `object_id`=@iRecFans;
+
 -- STATS
 DELETE FROM `sys_statistics` WHERE `name` LIKE 'bx_groups%';
 

+ 27 - 16
modules/boonex/groups/install/sql/enable.sql

@@ -215,7 +215,8 @@ INSERT INTO `sys_pages_blocks` (`object`, `cell_id`, `module`, `title_system`, `
 ('', 0, 'bx_groups', '_bx_groups_page_block_title_sys_labels_tree', '_bx_groups_page_block_title_labels_tree', 11, 2147483647, 'service', 'a:2:{s:6:"module";s:9:"bx_groups";s:6:"method";s:15:"get_lables_tree";}', 0, 1, 1, IFNULL(@iBlockOrder, 0) + 4),
 ('', 0, 'bx_groups', '_bx_groups_page_block_title_sys_groups_browse_by_label', '_bx_groups_page_block_title_groups_browse_by_label', 11, 2147483647, 'service', 'a:2:{s:6:"module";s:9:"bx_groups";s:6:"method";s:15:"browse_by_label";}', 0, 1, 1, IFNULL(@iBlockOrder, 0) + 5),
 ('', 0, 'bx_groups', '_bx_groups_page_block_title_sys_labels_breadcrumbs', '_bx_groups_page_block_title_labels_breadcrumbs', 11, 2147483647, 'service', 'a:2:{s:6:"module";s:9:"bx_groups";s:6:"method";s:22:"get_lables_breadcrumbs";}', 0, 1, 1, IFNULL(@iBlockOrder, 0) + 6),
-('', 0, 'bx_groups', '_bx_groups_page_block_title_sys_cover_block', '_bx_groups_page_block_title_cover_block', 3, 2147483647, 'service', 'a:2:{s:6:\"module\";s:9:\"bx_groups\";s:6:\"method\";s:12:\"entity_cover\";}', 0, 1, 1, IFNULL(@iBlockOrder, 0) + 7);
+('', 0, 'bx_groups', '_bx_groups_page_block_title_sys_cover_block', '_bx_groups_page_block_title_cover_block', 3, 2147483647, 'service', 'a:2:{s:6:\"module\";s:9:\"bx_groups\";s:6:\"method\";s:12:\"entity_cover\";}', 0, 1, 1, IFNULL(@iBlockOrder, 0) + 7),
+('', 0, 'bx_groups', '_bx_groups_page_block_title_sys_recom_fans', '_bx_groups_page_block_title_recom_fans', 11, 2147483647, 'service', 'a:2:{s:6:\"module\";s:9:\"bx_groups\";s:6:\"method\";s:27:\"browse_recommendations_fans\";}', 0, 1, 1, IFNULL(@iBlockOrder, 0) + 8);
 
  -- PAGES: add page block to profiles modules (trigger* page objects are processed separately upon modules enable/disable)
 INSERT INTO `sys_pages_blocks` (`object`, `cell_id`, `module`, `title`, `designbox_id`, `visible_for_levels`, `type`, `content`, `deletable`, `copyable`, `order`, `active`) VALUES
@@ -370,21 +371,22 @@ INSERT INTO `sys_objects_menu`(`object`, `title`, `set_name`, `module`, `templat
 INSERT INTO `sys_menu_sets`(`set_name`, `module`, `title`, `deletable`) VALUES 
 ('bx_groups_snippet_meta', 'bx_groups', '_sys_menu_set_title_snippet_meta', 0);
 
-INSERT INTO `sys_menu_items`(`set_name`, `module`, `name`, `title_system`, `title`, `link`, `onclick`, `target`, `icon`, `submenu_object`, `visible_for_levels`, `visibility_custom`, `active`, `copyable`, `editable`, `order`) VALUES
-('bx_groups_snippet_meta', 'bx_groups', 'privacy', '_bx_groups_menu_item_title_system_sm_privacy', '_bx_groups_menu_item_title_sm_privacy', '', '', '', '', '', 2147483647, '', 1, 0, 1, 0),
-('bx_groups_snippet_meta', 'bx_groups', 'date', '_sys_menu_item_title_system_sm_date', '_sys_menu_item_title_sm_date', '', '', '', '', '', 2147483647, '', 0, 0, 1, 1),
-('bx_groups_snippet_meta', 'bx_groups', 'category', '_sys_menu_item_title_system_sm_category', '_sys_menu_item_title_sm_category', '', '', '', '', '', 2147483647, '', 0, 0, 1, 5),
-('bx_groups_snippet_meta', 'bx_groups', 'tags', '_sys_menu_item_title_system_sm_tags', '_sys_menu_item_title_sm_tags', '', '', '', '', '', 2147483647, '', 0, 0, 1, 10),
-('bx_groups_snippet_meta', 'bx_groups', 'views', '_sys_menu_item_title_system_sm_views', '_sys_menu_item_title_sm_views', '', '', '', '', '', 2147483647, '', 0, 0, 1, 15),
-('bx_groups_snippet_meta', 'bx_groups', 'comments', '_sys_menu_item_title_system_sm_comments', '_sys_menu_item_title_sm_comments', '', '', '', '', '', 2147483647, '', 0, 0, 1, 20),
-('bx_groups_snippet_meta', 'bx_groups', 'members', '_sys_menu_item_title_system_sm_members', '_sys_menu_item_title_sm_members', '', '', '', '', '', 2147483647, '', 1, 0, 1, 25),
-('bx_groups_snippet_meta', 'bx_groups', 'subscribers', '_sys_menu_item_title_system_sm_subscribers', '_sys_menu_item_title_sm_subscribers', '', '', '', '', '', 2147483647, '', 0, 0, 1, 30),
-('bx_groups_snippet_meta', 'bx_groups', 'nl', '_sys_menu_item_title_system_sm_nl', '_sys_menu_item_title_sm_nl', '', '', '', '', '', 2147483647, '', 1, 0, 1, 35),
-('bx_groups_snippet_meta', 'bx_groups', 'join-paid', '_sys_menu_item_title_system_sm_join_paid', '_sys_menu_item_title_sm_join_paid', '', '', '', '', '', 2147483647, 'a:3:{s:6:"module";s:9:"bx_groups";s:6:"method";s:33:"is_paid_join_avaliable_by_content";s:6:"params";a:1:{i:0;s:12:"{content_id}";}}', 1, 0, 1, 40),
-('bx_groups_snippet_meta', 'bx_groups', 'join', '_sys_menu_item_title_system_sm_join', '_sys_menu_item_title_sm_join', '', '', '', '', '', 2147483647, 'a:3:{s:6:"module";s:9:"bx_groups";s:6:"method";s:33:"is_free_join_avaliable_by_content";s:6:"params";a:1:{i:0;s:12:"{content_id}";}}', 1, 0, 1, 45),
-('bx_groups_snippet_meta', 'bx_groups', 'leave', '_sys_menu_item_title_system_sm_leave', '_sys_menu_item_title_sm_leave', '', '', '', '', '', 2147483647, '', 0, 0, 1, 50),
-('bx_groups_snippet_meta', 'bx_groups', 'subscribe', '_sys_menu_item_title_system_sm_subscribe', '_sys_menu_item_title_sm_subscribe', '', '', '', '', '', 2147483647, '', 0, 0, 1, 55),
-('bx_groups_snippet_meta', 'bx_groups', 'unsubscribe', '_sys_menu_item_title_system_sm_unsubscribe', '_sys_menu_item_title_sm_unsubscribe', '', '', '', '', '', 2147483647, '', 0, 0, 1, 60);
+INSERT INTO `sys_menu_items`(`set_name`, `module`, `name`, `title_system`, `title`, `link`, `onclick`, `target`, `icon`, `submenu_object`, `visible_for_levels`, `visibility_custom`, `hidden_on_cxt`, `active`, `copyable`, `editable`, `order`) VALUES
+('bx_groups_snippet_meta', 'bx_groups', 'privacy', '_bx_groups_menu_item_title_system_sm_privacy', '_bx_groups_menu_item_title_sm_privacy', '', '', '', '', '', 2147483647, '', '', 1, 0, 1, 0),
+('bx_groups_snippet_meta', 'bx_groups', 'date', '_sys_menu_item_title_system_sm_date', '_sys_menu_item_title_sm_date', '', '', '', '', '', 2147483647, '', '', 0, 0, 1, 1),
+('bx_groups_snippet_meta', 'bx_groups', 'category', '_sys_menu_item_title_system_sm_category', '_sys_menu_item_title_sm_category', '', '', '', '', '', 2147483647, '', '', 0, 0, 1, 5),
+('bx_groups_snippet_meta', 'bx_groups', 'tags', '_sys_menu_item_title_system_sm_tags', '_sys_menu_item_title_sm_tags', '', '', '', '', '', 2147483647, '', '', 0, 0, 1, 10),
+('bx_groups_snippet_meta', 'bx_groups', 'views', '_sys_menu_item_title_system_sm_views', '_sys_menu_item_title_sm_views', '', '', '', '', '', 2147483647, '', '', 0, 0, 1, 15),
+('bx_groups_snippet_meta', 'bx_groups', 'comments', '_sys_menu_item_title_system_sm_comments', '_sys_menu_item_title_sm_comments', '', '', '', '', '', 2147483647, '', '', 0, 0, 1, 20),
+('bx_groups_snippet_meta', 'bx_groups', 'members', '_sys_menu_item_title_system_sm_members', '_sys_menu_item_title_sm_members', '', '', '', '', '', 2147483647, '', '', 1, 0, 1, 25),
+('bx_groups_snippet_meta', 'bx_groups', 'subscribers', '_sys_menu_item_title_system_sm_subscribers', '_sys_menu_item_title_sm_subscribers', '', '', '', '', '', 2147483647, '', '', 0, 0, 1, 30),
+('bx_groups_snippet_meta', 'bx_groups', 'nl', '_sys_menu_item_title_system_sm_nl', '_sys_menu_item_title_sm_nl', '', '', '', '', '', 2147483647, '', '', 1, 0, 1, 35),
+('bx_groups_snippet_meta', 'bx_groups', 'join-paid', '_sys_menu_item_title_system_sm_join_paid', '_sys_menu_item_title_sm_join_paid', '', '', '', '', '', 2147483647, 'a:3:{s:6:"module";s:9:"bx_groups";s:6:"method";s:33:"is_paid_join_avaliable_by_content";s:6:"params";a:1:{i:0;s:12:"{content_id}";}}', '', 1, 0, 1, 40),
+('bx_groups_snippet_meta', 'bx_groups', 'join', '_sys_menu_item_title_system_sm_join', '_sys_menu_item_title_sm_join', '', '', '', '', '', 2147483647, 'a:3:{s:6:"module";s:9:"bx_groups";s:6:"method";s:33:"is_free_join_avaliable_by_content";s:6:"params";a:1:{i:0;s:12:"{content_id}";}}', '', 1, 0, 1, 45),
+('bx_groups_snippet_meta', 'bx_groups', 'leave', '_sys_menu_item_title_system_sm_leave', '_sys_menu_item_title_sm_leave', '', '', '', '', '', 2147483647, '', 'recom_groups_fans', 0, 0, 1, 50),
+('bx_groups_snippet_meta', 'bx_groups', 'subscribe', '_sys_menu_item_title_system_sm_subscribe', '_sys_menu_item_title_sm_subscribe', '', '', '', '', '', 2147483647, '', 'recom_groups_fans', 0, 0, 1, 55),
+('bx_groups_snippet_meta', 'bx_groups', 'unsubscribe', '_sys_menu_item_title_system_sm_unsubscribe', '_sys_menu_item_title_sm_unsubscribe', '', '', '', '', '', 2147483647, '', 'recom_groups_fans', 0, 0, 1, 60),
+('bx_groups_snippet_meta', 'bx_groups', 'ignore-join', '_sys_menu_item_title_system_sm_ignore', '_sys_menu_item_title_sm_ignore', '', '', '', '', '', 2147483647, '', 'all!recom_groups_fans', 1, 0, 1, 70);
 
 -- MENU: profile stats
 SET @iNotifMenuOrder = (SELECT IFNULL(MAX(`order`), 0) FROM `sys_menu_items` WHERE `set_name` = 'sys_profile_stats' AND `active` = 1 LIMIT 1);
@@ -522,6 +524,15 @@ INSERT INTO `sys_objects_search` (`ObjectName`, `Title`, `Order`, `ClassName`, `
 INSERT INTO `sys_objects_connection` (`object`, `table`, `profile_initiator`, `profile_content`, `type`, `override_class_name`, `override_class_file`) VALUES
 ('bx_groups_fans', 'bx_groups_fans', 1, 1, 'mutual', 'BxGroupsConnectionFans', 'modules/boonex/groups/classes/BxGroupsConnectionFans.php');
 
+-- RECOMMENDATIONS
+INSERT INTO `sys_objects_recommendation` (`name`, `module`, `connection`, `content_info`, `countable`, `active`, `class_name`, `class_file`) VALUES
+('bx_groups_fans', 'system', 'bx_groups_fans', '', 1, 1, 'BxGroupsRecommendationFans', 'modules/boonex/groups/classes/BxGroupsRecommendationFans.php');
+SET @iRecFans = LAST_INSERT_ID();
+
+INSERT INTO `sys_recommendation_criteria` (`object_id`, `name`, `source_type`, `source`, `params`, `weight`, `active`) VALUES
+(@iRecFans, 'by_friends', 'sql', 'SELECT `tgf`.`content` AS `id`, SUM({points}) AS `value` FROM `sys_profiles_conn_friends` AS `tf` INNER JOIN `bx_groups_fans` AS `tgf` ON `tf`.`content`=`tgf`.`initiator` AND `tgf`.`content` NOT IN (SELECT `content` FROM `bx_groups_fans` WHERE `initiator`={profile_id} AND `mutual`=''1'') AND `tgf`.`mutual`=''1'' WHERE `tf`.`initiator`={profile_id} AND `tf`.`mutual`=''1'' GROUP BY `id`', 'a:1:{s:6:"points";i:2;}', 0.5, 1),
+(@iRecFans, 'by_subscriptions', 'sql', 'SELECT `tgf`.`content` AS `id`, SUM({points}) AS `value` FROM `sys_profiles_conn_subscriptions` AS `ts` INNER JOIN `sys_profiles` AS `tp` ON `ts`.`content`=`tp`.`id` AND `tp`.`type` IN ({profile_types}) AND `tp`.`status`=''active'' INNER JOIN `bx_groups_fans` AS `tgf` ON `ts`.`content`=`tgf`.`initiator` AND `tgf`.`content` NOT IN (SELECT `content` FROM `bx_groups_fans` WHERE `initiator`={profile_id} AND `mutual`=''1'') AND `tgf`.`mutual`=''1'' WHERE `ts`.`initiator`={profile_id} GROUP BY `id`', 'a:2:{s:6:"points";i:2;s:13:"profile_types";s:0:"";}', 0.25, 1),
+(@iRecFans, 'by_fans', 'sql', 'SELECT `tg2`.`content` AS `id`, SUM({points}) AS `value` FROM `bx_groups_fans` AS `tg1` INNER JOIN `bx_groups_fans` AS `tm` ON `tg1`.`content`=`tm`.`content` AND `tm`.`initiator`<>{profile_id} AND `tm`.`mutual`=''1'' INNER JOIN `bx_groups_fans` AS `tg2` ON `tm`.`initiator`=`tg2`.`initiator` AND `tg2`.`mutual`=''1'' AND `tg2`.`content` NOT IN (SELECT `content` FROM `bx_groups_fans` WHERE `initiator`={profile_id} AND `mutual`=''1'')  WHERE `tg1`.`initiator`={profile_id} AND `tg1`.`mutual`=''1'' GROUP BY `id`', 'a:1:{s:6:"points";i:1;}', 0.25, 1);
 
 -- STATS
 SET @iMaxOrderStats = (SELECT IFNULL(MAX(`order`), 0) FROM `sys_statistics`);

+ 2 - 0
modules/boonex/russian/data/langs/bx_groups/ru.xml

@@ -201,6 +201,8 @@
     <string name="_bx_groups_page_block_title_favorites_entries_actions"><![CDATA[Действия]]></string>
     <string name="_bx_groups_page_block_title_sys_cover_block"><![CDATA[Обложка]]></string>
     <string name="_bx_groups_page_block_title_cover_block"><![CDATA[Обложка]]></string>
+    <string name="_bx_groups_page_block_title_sys_recom_fans"><![CDATA[Рекомендуемые группы (Вступить)]]></string>
+    <string name="_bx_groups_page_block_title_recom_fans"><![CDATA[Группы для вступления]]></string>
 
   <string name="_bx_groups_menu_title_submenu"><![CDATA[Группы - Подменю]]></string>
     <string name="_bx_groups_menu_set_title_submenu"><![CDATA[Группы - Подменю]]></string>