AntonLV 5 vuotta sitten
vanhempi
sitoutus
07b5109063

+ 17 - 0
modules/boonex/russian/data/langs/bx_timeline/ru.xml

@@ -90,6 +90,21 @@
     <string name="_bx_timeline_form_attach_link_input_do_submit"><![CDATA[Добавить]]></string>
     <string name="_bx_timeline_form_attach_link_input_do_cancel"><![CDATA[Закрыть]]></string>
 
+    <string name="_bx_timeline_form_repost_to"><![CDATA[Сделать репост в]]></string>
+    <string name="_bx_timeline_form_repost_to_display_browse"><![CDATA[Просмотреть, чтобы сделать репост в]]></string>
+    <string name="_bx_timeline_form_repost_to_input_sys_reposter_id"><![CDATA[ID исполнителя]]></string>
+    <string name="_bx_timeline_form_repost_to_input_sys_type"><![CDATA[Тип]]></string>
+    <string name="_bx_timeline_form_repost_to_input_sys_action"><![CDATA[Действие]]></string>
+    <string name="_bx_timeline_form_repost_to_input_sys_object_id"><![CDATA[ID объекта]]></string>
+    <string name="_bx_timeline_form_repost_to_input_sys_search"><![CDATA[Поиск]]></string>
+    <string name="_bx_timeline_form_repost_to_input_search"><![CDATA[Найти]]></string>
+    <string name="_bx_timeline_form_repost_to_input_sys_list"><![CDATA[Список]]></string>
+    <string name="_bx_timeline_form_repost_to_input_list"><![CDATA[или выбрать]]></string>
+    <string name="_bx_timeline_form_repost_to_input_sys_do_submit"><![CDATA[Репост]]></string>
+    <string name="_bx_timeline_form_repost_to_input_do_submit"><![CDATA[Репост]]></string>
+    <string name="_bx_timeline_form_repost_to_input_sys_do_cancel"><![CDATA[Отмена]]></string>
+    <string name="_bx_timeline_form_repost_to_input_do_cancel"><![CDATA[Отмена]]></string>
+
     <string name="_bx_timeline_privacy_view"><![CDATA[Просматривать события]]></string>
 
     <string name="_bx_timeline_acl_action_post"><![CDATA[Писать сообщения]]></string>
@@ -181,6 +196,8 @@
     <string name="_bx_timeline_menu_set_title_item_share"><![CDATA[Поделиться]]></string>
     <string name="_bx_timeline_menu_item_title_system_item_repost"><![CDATA[Сделать репост]]></string>
     <string name="_bx_timeline_menu_item_title_item_repost"><![CDATA[Сделать репост]]></string>
+    <string name="_bx_timeline_menu_item_title_system_item_repost_to"><![CDATA[Сделать репост в контекст]]></string>
+    <string name="_bx_timeline_menu_item_title_item_repost_to"><![CDATA[Сделать репост в контекст]]></string>
     <string name="_bx_timeline_menu_item_title_system_item_send"><![CDATA[Послать]]></string>
     <string name="_bx_timeline_menu_item_title_item_send"><![CDATA[Послать другу]]></string>
     <string name="_bx_timeline_menu_item_title_system_admt_timeline"><![CDATA[Лента]]></string>

+ 3 - 0
modules/boonex/timeline/classes/BxTimelineConfig.php

@@ -218,12 +218,14 @@ class BxTimelineConfig extends BxBaseModNotificationsConfig
 
             'form_post' => $this->_sName . '_post',
             'form_attach_link' => $this->_sName . '_attach_link',
+            'form_repost_to' => $this->_sName . '_repost_to',
             'form_display_post_add' => $this->_sName . '_post_add',
             'form_display_post_add_public' => $this->_sName . '_post_add_public',
             'form_display_post_add_profile' => $this->_sName . '_post_add_profile',
             'form_display_post_edit' => $this->_sName . '_post_edit',
             'form_display_post_view' => $this->_sName . '_post_view',
             'form_display_attach_link_add' => $this->_sName . '_attach_link_add',
+            'form_display_repost_to_browse' => $this->_sName . '_repost_to_browse',
 
             'grid_mute' => $this->CNF['OBJECT_GRID_MUTE'],
 
@@ -293,6 +295,7 @@ class BxTimelineConfig extends BxBaseModNotificationsConfig
                 'main' => $sHp . '-repost-',
                 'counter' => $sHp . '-repost-counter-',
                 'by_popup' => $sHp . '-repost-by-',
+                'to_popup' => $sHp . '-repost-to',
             )
         );
 

+ 40 - 0
modules/boonex/timeline/classes/BxTimelineFormRepostTo.php

@@ -0,0 +1,40 @@
+<?php defined('BX_DOL') or die('hack attempt');
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ *
+ * @defgroup    Timeline Timeline
+ * @ingroup     UnaModules
+ *
+ * @{
+ */
+
+class BxTimelineFormRepostTo extends BxTemplFormView
+{
+    protected $_sModule;
+    protected $_oModule;
+
+    public function __construct($aInfo, $oTemplate = false)
+    {
+        $this->_sModule = 'bx_timeline';
+        $this->_oModule = BxDolModule::getInstance($this->_sModule);
+
+        parent::__construct($aInfo, $oTemplate);
+
+        $this->aFormAttrs['action'] = BX_DOL_URL_ROOT . $this->_oModule->_oConfig->getBaseUri() . 'repost_to/';
+    }
+
+    protected function genCustomInputSearch($aInput)
+    {
+        $aInput['ajax_get_suggestions'] = BX_DOL_URL_ROOT . $this->_oModule->_oConfig->getBaseUri() . 'get_contexts';
+
+        return $this->genCustomInputUsernamesSuggestions($aInput);
+    }
+
+    protected function genCustomInputList($aInput)
+    {
+        return $this->_oModule->_oTemplate->getRepostToFieldList($this, $aInput);
+    }
+}
+
+/** @} */

+ 3 - 1
modules/boonex/timeline/classes/BxTimelineMenuItemShare.php

@@ -56,10 +56,11 @@ class BxTimelineMenuItemShare extends BxTemplMenu
                     $this->_aEvent['url'] = $aResult['url'];
             }
 
-            //--- Repost item
+            //--- Repost and 'Repost To' items
             $iOwnerId = $this->_oModule->getUserId(); //--- in whose timeline the content will be reposted
             $iObjectId = $this->_oModule->_oConfig->isSystem($sType, $sAction) ? $this->_aEvent['object_id'] : $this->_aEvent['id'];
             $sRepostOnclick = $this->_oModule->serviceGetRepostJsClick($iOwnerId, $sType, $sAction, $iObjectId);
+            $sRepostToOnclick = $this->_oModule->serviceGetRepostToJsClick($iOwnerId, $sType, $sAction, $iObjectId);
 
             //--- Send item
     	    $sAetSend = urlencode(base64_encode(serialize(array(
@@ -75,6 +76,7 @@ class BxTimelineMenuItemShare extends BxTemplMenu
             'content_url' => $this->_aEvent['url'],
 
             'repost_onclick' => $sRepostOnclick,
+            'repost_to_onclick' => $sRepostToOnclick,
             'et_send' => $sAetSend
     	));
     }

+ 119 - 1
modules/boonex/timeline/classes/BxTimelineModule.php

@@ -90,6 +90,41 @@ class BxTimelineModule extends BxBaseModNotificationsModule implements iBxDolCon
     /**
      * ACTION METHODS
      */
+    public function actionGetContexts($iLimit = 20)
+    {
+        $oConnection = BxDolConnection::getObjectInstance('sys_profiles_subscriptions');
+        if(!$oConnection)
+            return echoJson(array());
+
+        $iProfileId = bx_get_logged_profile_id();
+        $aConnected = $oConnection->getConnectedContent($iProfileId);
+
+        $sTerm = bx_get('term');
+        if(!$sTerm)
+            return array_slice($aConnected, 0, $iLimit);
+
+        $aResults = array();
+        $aModules = bx_srv('system', 'get_profiles_modules', array(false), 'TemplServiceProfiles');
+        foreach($aModules as $aModule) {
+            if(!BxDolRequest::serviceExists($aModule['name'], 'act_as_profile'))
+                continue;
+
+            $aContexts = bx_srv($aModule['name'], 'profiles_search', array($sTerm, PHP_INT_MAX));
+            foreach($aContexts as $aContext) {
+                if(!in_array($aContext['value'], $aConnected))
+                    continue;
+
+                $aResults[] = $aContext;
+            }
+        }
+
+        usort($aResults, function($r1, $r2) {
+            return strcmp($r1['label'], $r2['label']);
+        });
+
+        echoJson(array_slice($aResults, 0, $iLimit));
+    }
+
     public function actionVideo($iEventId, $iVideoId)
     {
         $aEvent = $this->_oDb->getEvents(array('browse' => 'id', 'value' => $iEventId));
@@ -319,6 +354,60 @@ class BxTimelineModule extends BxBaseModNotificationsModule implements iBxDolCon
         ));
     }
 
+    public function actionRepostTo()
+    {
+        $iReposterId = bx_process_input(bx_get('reposter_id'), BX_DATA_INT);
+        if($iReposterId != $this->getUserId())
+            return;
+
+        $sType = bx_process_input(bx_get('type'), BX_DATA_TEXT);
+        $sAction = bx_process_input(bx_get('action'), BX_DATA_TEXT);
+        $iObjectId = bx_process_input(bx_get('object_id'), BX_DATA_INT);
+
+        $oForm = BxDolForm::getObjectInstance($this->_oConfig->getObject('form_repost_to'), $this->_oConfig->getObject('form_display_repost_to_browse'));
+        $oForm->initChecker(array(
+            'reposter_id' => $iReposterId,
+            'type' => $sType,
+            'action' => $sAction, 
+            'object_id' => $iObjectId
+        ));
+
+        if($oForm->isSubmitted()) {
+            if(!$oForm->isValid())
+                return echoJson(array('popup' => array(
+                    'html' => BxTemplFunctions::getInstance()->transBox($this->_oConfig->getHtmlIds('repost', 'to_popup'), $this->_oTemplate->getRepostTo($oForm)), 
+                    'options' => array('closeOnOuterClick' => false, 'removeOnClose' => true)
+                )));
+
+            $aContexts = array();
+            if(($aContextsSearch = $oForm->getCleanValue('search')) !== false)
+                $aContexts = array_merge($aContexts, $aContextsSearch);
+
+            if(($aContextsList = $oForm->getCleanValue('list')) !== false)
+                $aContexts = array_merge($aContexts, $aContextsList);
+
+            $aContexts = array_unique($aContexts);
+            if(empty($aContexts) || !is_array($aContexts))
+                return echoJson(array());
+
+            foreach($aContexts as $iContextId)
+                $this->serviceRepost($iReposterId, $iContextId, $sType, $sAction, $iObjectId);
+
+            $aReposted = $this->_oDb->getReposted($sType, $sAction, $iObjectId);
+            $sCounter = $this->_oTemplate->getRepostCounter($aReposted);
+
+            return echoJson(array(
+                'code' => 0, 
+                'message' => _t('_bx_timeline_txt_msg_success_repost'), 
+                'count' => $aReposted['reposts'], 
+                'countf' => (int)$aReposted['reposts'] > 0 ? $this->_oTemplate->getRepostCounterLabel($aReposted['reposts']) : '',
+                'counter' => $sCounter,
+            ));
+        }
+
+        echo $this->_oTemplate->getRepostTo($oForm);
+    }
+
     function actionGetView()
     {
         $aParams = $this->_prepareParamsGet();
@@ -2168,10 +2257,39 @@ class BxTimelineModule extends BxBaseModNotificationsModule implements iBxDolCon
     public function serviceGetRepostJsClick($iOwnerId, $sType, $sAction, $iObjectId)
     {
     	if(!$this->isEnabled())
-    		return '';
+            return '';
 
         return $this->_oTemplate->getRepostJsClick($iOwnerId, $sType, $sAction, $iObjectId);
     }
+    
+    /**
+     * @page service Service Calls
+     * @section bx_timeline Timeline
+     * @subsection bx_timeline-repost Repost
+     * @subsubsection bx_timeline-get_repost_to_js_click get_repost_to_js_click
+     * 
+     * @code bx_srv('bx_timeline', 'get_repost_to_js_click', [...]); @endcode
+     * 
+     * Get 'repost to' JavaScript code for OnClick event.
+     * 
+     * @param $iReposterId integer value with reposter profile ID.
+     * @param $sType string value with type (module name). 
+     * @param $sAction string value with action (module action). 
+     * @param $iObjectId integer value with object ID to be reposted. 
+     * @return HTML string with JavaScript code to display in OnClick events of HTML elements.
+     * 
+     * @see BxTimelineModule::serviceGetRepostToJsClick
+     */
+    /** 
+     * @ref bx_timeline-get_repost_to_js_click "get_repost_to_js_click"
+     */
+    public function serviceGetRepostToJsClick($iReposterId, $sType, $sAction, $iObjectId)
+    {
+    	if(!$this->isEnabled())
+            return '';
+
+        return $this->_oTemplate->getRepostToJsClick($iReposterId, $sType, $sAction, $iObjectId);
+    }
 
     /**
      * @page service Service Calls

+ 92 - 0
modules/boonex/timeline/classes/BxTimelineTemplate.php

@@ -984,6 +984,70 @@ class BxTimelineTemplate extends BxBaseModNotificationsTemplate
         ));
     }
 
+    public function getRepostTo($oForm)
+    {
+        $sStylePrefix = $this->_oConfig->getPrefix('style');
+        $sJsObject = $this->_oConfig->getJsObject('repost');
+
+        return $this->parseHtmlByName('repost_to_popup.html', array(
+            'style_prefix' => $sStylePrefix,
+            'js_object' => $sJsObject,
+            'form' => $oForm->getCode(),
+            'form_id' => $oForm->getId()
+        ));
+    }
+
+    public function getRepostToFieldList($oForm, $aInput)
+    {
+        $sStylePrefix = $this->_oConfig->getPrefix('style');
+
+        $oConnection = BxDolConnection::getObjectInstance('sys_profiles_subscriptions');
+        if(!$oConnection)
+            return '';
+
+        $iProfileId = bx_get_logged_profile_id();
+        $aConnectedIds = $oConnection->getConnectedContent($iProfileId);
+
+        $aSelected = array();
+        $aTmplVarsModules = array();
+        if(!empty($aConnectedIds) && is_array($aConnectedIds)) {
+            $aCheckbox = $aInput;
+            $aCheckbox['type'] = 'checkbox';
+            $aCheckbox['name'] .= '[]';
+
+            foreach($aConnectedIds as $iConnectedId) {
+                $oProfile = BxDolProfile::getInstanceMagic($iConnectedId);
+                if(!$oProfile)
+                    continue;
+
+                $sProfileModule = $oProfile->getModule();
+                if(!isset($aTmplVarsModules[$sProfileModule]))
+                    $aTmplVarsModules[$sProfileModule] = array(
+                        'style_prefix' => $sStylePrefix,
+                        'title' => _t('_' . $sProfileModule),
+                        'bx_repeat:contexts' => array()
+                    );
+                        
+                $aCheckbox['value'] = $iConnectedId;
+                $aCheckbox['checked'] = in_array($iConnectedId, $aSelected) ? 1 : 0;
+
+                $aTmplVarsModules[$sProfileModule]['bx_repeat:contexts'][] = array(
+                    'style_prefix' => $sStylePrefix,
+                    'checkbox' => $oForm->genInput($aCheckbox),
+                    'unit' => $oProfile->getUnit(0, array('template' => 'unit_wo_cover'))
+                );
+            }
+        }      
+
+        if(empty($aTmplVarsModules))
+            $aTmplVarsModules = MsgBox(_t('_Empty'));
+
+        return $this->parseHtmlByName('repost_to_list.html', array(
+            'style_prefix' => $sStylePrefix,
+            'bx_repeat:modules' => array_values($aTmplVarsModules)
+        ));
+    }
+
     public function getRepostJsScript($bDynamicMode = false)
     {
         $sCode = $this->getJsCode('repost', array(), array('mask' => '{object} = new {class}({params});', 'wrap' => false));
@@ -1028,6 +1092,25 @@ class BxTimelineTemplate extends BxBaseModNotificationsTemplate
         return $sResult;
     }
 
+    public function getRepostToJsClick($iReposterId, $sType, $sAction, $iObjectId)
+    {
+        $aReposted = $this->_oDb->getReposted($sType, $sAction, $iObjectId);
+        if(empty($aReposted) || !is_array($aReposted))
+            return '';
+
+        $sResult = '';
+        $sCommonPrefix = $this->_oConfig->getPrefix('common_post');
+        if(str_replace($sCommonPrefix, '', $sType) == BX_TIMELINE_PARSE_TYPE_REPOST) {
+            $aRepostedData = unserialize($aReposted['content']);
+
+            $sResult = $this->_getRepostToJsClick($iReposterId, $aRepostedData['type'], $aRepostedData['action'], $aRepostedData['object_id']);
+        }
+        else
+            $sResult = $this->_getRepostToJsClick($iReposterId, $sType, $sAction, $iObjectId);
+
+        return $sResult;
+    }
+
     public function getAttachLinkForm($iEventId = 0)
     {
         $sStylePrefix = $this->_oConfig->getPrefix('style');
@@ -1679,6 +1762,15 @@ class BxTimelineTemplate extends BxBaseModNotificationsTemplate
         return sprintf($sFormat, $sJsObject, $iOwnerId, $sType, $sAction, (int)$iObjectId);
     }
 
+    protected function _getRepostToJsClick($iReposterId, $sType, $sAction, $iObjectId)
+    {
+        $sJsObject = $this->_oConfig->getJsObject('repost');
+        $sFormat = "%s.repostItemTo(this, %d, '%s', '%s', %d);";
+
+        $iReposterId = !empty($iReposterId) ? (int)$iReposterId : $this->getModule()->getUserId();
+        return sprintf($sFormat, $sJsObject, $iReposterId, $sType, $sAction, (int)$iObjectId);
+    }
+
     protected function _getJumpToList($aParams)
     {
         $iYearSel = (int)$aParams['timeline'];

+ 17 - 0
modules/boonex/timeline/install/langs/en.xml

@@ -90,6 +90,21 @@
     <string name="_bx_timeline_form_attach_link_input_do_submit"><![CDATA[Add]]></string>
     <string name="_bx_timeline_form_attach_link_input_do_cancel"><![CDATA[Close]]></string>
 
+    <string name="_bx_timeline_form_repost_to"><![CDATA[Repost To]]></string>
+    <string name="_bx_timeline_form_repost_to_display_browse"><![CDATA[Browse to Repost To]]></string>
+    <string name="_bx_timeline_form_repost_to_input_sys_reposter_id"><![CDATA[Reposter ID]]></string>
+    <string name="_bx_timeline_form_repost_to_input_sys_type"><![CDATA[Type]]></string>
+    <string name="_bx_timeline_form_repost_to_input_sys_action"><![CDATA[Action]]></string>
+    <string name="_bx_timeline_form_repost_to_input_sys_object_id"><![CDATA[Object ID]]></string>
+    <string name="_bx_timeline_form_repost_to_input_sys_search"><![CDATA[Search]]></string>
+    <string name="_bx_timeline_form_repost_to_input_search"><![CDATA[Search]]></string>
+    <string name="_bx_timeline_form_repost_to_input_sys_list"><![CDATA[List]]></string>
+    <string name="_bx_timeline_form_repost_to_input_list"><![CDATA[or select]]></string>
+    <string name="_bx_timeline_form_repost_to_input_sys_do_submit"><![CDATA[Repost]]></string>
+    <string name="_bx_timeline_form_repost_to_input_do_submit"><![CDATA[Repost]]></string>
+    <string name="_bx_timeline_form_repost_to_input_sys_do_cancel"><![CDATA[Cancel]]></string>
+    <string name="_bx_timeline_form_repost_to_input_do_cancel"><![CDATA[Cancel]]></string>
+
     <string name="_bx_timeline_privacy_view"><![CDATA[View event]]></string>
 
     <string name="_bx_timeline_acl_action_post"><![CDATA[Post]]></string>
@@ -183,6 +198,8 @@
     <string name="_bx_timeline_menu_set_title_item_share"><![CDATA[Share Item]]></string>
     <string name="_bx_timeline_menu_item_title_system_item_repost"><![CDATA[Repost]]></string>
     <string name="_bx_timeline_menu_item_title_item_repost"><![CDATA[Repost]]></string>
+    <string name="_bx_timeline_menu_item_title_system_item_repost_to"><![CDATA[Repost to Context]]></string>
+    <string name="_bx_timeline_menu_item_title_item_repost_to"><![CDATA[Repost to Context]]></string>
     <string name="_bx_timeline_menu_item_title_system_item_send"><![CDATA[Send]]></string>
     <string name="_bx_timeline_menu_item_title_item_send"><![CDATA[Send to Friend]]></string>
     <string name="_bx_timeline_menu_item_title_system_admt_timeline"><![CDATA[Timeline]]></string>

+ 2 - 1
modules/boonex/timeline/install/sql/enable.sql

@@ -113,7 +113,8 @@ INSERT INTO `sys_menu_sets`(`set_name`, `module`, `title`, `deletable`) VALUES
 
 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
 ('bx_timeline_menu_item_share', 'bx_timeline', 'item-repost', '_bx_timeline_menu_item_title_system_item_repost', '_bx_timeline_menu_item_title_item_repost', 'javascript:void(0)', 'javascript:{repost_onclick}', '_self', 'redo', '', 2147483647, 1, 0, 1),
-('bx_timeline_menu_item_share', 'bx_timeline', 'item-send', '_bx_timeline_menu_item_title_system_item_send', '_bx_timeline_menu_item_title_item_send', 'page.php?i=start-convo&et={et_send}', '', '_self', 'envelope', '', 2147483647, 1, 0, 2);
+('bx_timeline_menu_item_share', 'bx_timeline', 'item-repost-to', '_bx_timeline_menu_item_title_system_item_repost_to', '_bx_timeline_menu_item_title_item_repost_to', 'javascript:void(0)', 'javascript:{repost_to_onclick}', '_self', 'redo', '', 2147483647, 1, 0, 2),
+('bx_timeline_menu_item_share', 'bx_timeline', 'item-send', '_bx_timeline_menu_item_title_system_item_send', '_bx_timeline_menu_item_title_item_send', 'page.php?i=start-convo&et={et_send}', '', '_self', 'envelope', '', 2147483647, 1, 0, 3);
 
 -- MENU: Item Manage (Pin, Delete, etc)
 INSERT INTO `sys_objects_menu`(`object`, `title`, `set_name`, `module`, `template_id`, `deletable`, `active`, `override_class_name`, `override_class_file`) VALUES 

+ 29 - 0
modules/boonex/timeline/install/sql/install.sql

@@ -518,6 +518,35 @@ INSERT INTO `sys_form_display_inputs` (`display_name`, `input_name`, `visible_fo
 ('bx_timeline_attach_link_add', 'do_submit', 2147483647, 1, 4),
 ('bx_timeline_attach_link_add', 'do_cancel', 2147483647, 1, 5);
 
+-- Forms -> Repost To
+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_timeline_repost_to', @sName, '_bx_timeline_form_repost_to', '', '', 'do_submit', '', '', '', '', '', 0, 1, 'BxTimelineFormRepostTo', 'modules/boonex/timeline/classes/BxTimelineFormRepostTo.php');
+
+INSERT INTO `sys_form_displays` (`display_name`, `module`, `object`, `title`, `view_mode`) VALUES
+('bx_timeline_repost_to_browse', @sName, 'bx_timeline_repost_to', '_bx_timeline_form_repost_to_display_browse', 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_timeline_repost_to', @sName, 'reposter_id', '', '', 0, 'hidden', '_bx_timeline_form_repost_to_input_sys_reposter_id', '', '', 0, 0, 0, '', '', '', '', '', '', 'Int', '', 0, 0),
+('bx_timeline_repost_to', @sName, 'type', '', '', 0, 'hidden', '_bx_timeline_form_repost_to_input_sys_type', '', '', 0, 0, 0, '', '', '', '', '', '', 'Xss', '', 0, 0),
+('bx_timeline_repost_to', @sName, 'action', '', '', 0, 'hidden', '_bx_timeline_form_repost_to_input_sys_action', '', '', 0, 0, 0, '', '', '', '', '', '', 'Xss', '', 0, 0),
+('bx_timeline_repost_to', @sName, 'object_id', '', '', 0, 'hidden', '_bx_timeline_form_repost_to_input_sys_object_id', '', '', 0, 0, 0, '', '', '', '', '', '', 'Int', '', 0, 0),
+('bx_timeline_repost_to', @sName, 'search', '', '', 0, 'custom', '_bx_timeline_form_repost_to_input_sys_search', '_bx_timeline_form_repost_to_input_search', '', 0, 0, 0, '', '', '', '', '', '', '', '', 0, 0),
+('bx_timeline_repost_to', @sName, 'list', '', '', 0, 'custom', '_bx_timeline_form_repost_to_input_sys_list', '_bx_timeline_form_repost_to_input_list', '', 0, 0, 0, '', '', '', '', '', '', '', '', 0, 0),
+('bx_timeline_repost_to', @sName, 'controls', '', 'do_submit,do_cancel', 0, 'input_set', '', '', '', 0, 0, 0, '', '', '', '', '', '', '', '', 0, 0),
+('bx_timeline_repost_to', @sName, 'do_submit', '_bx_timeline_form_repost_to_input_do_submit', '', 0, 'submit', '_bx_timeline_form_repost_to_input_sys_do_submit', '', '', 0, 0, 0, '', '', '', '', '', '', '', '', 0, 0),
+('bx_timeline_repost_to', @sName, 'do_cancel', '_bx_timeline_form_repost_to_input_do_cancel', '', 0, 'button', '_bx_timeline_form_repost_to_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";}', '', '', '', '', '', '', '', 0, 0);
+
+INSERT INTO `sys_form_display_inputs` (`display_name`, `input_name`, `visible_for_levels`, `active`, `order`) VALUES
+('bx_timeline_repost_to_browse', 'reposter_id', 2147483647, 1, 1),
+('bx_timeline_repost_to_browse', 'type', 2147483647, 1, 2),
+('bx_timeline_repost_to_browse', 'action', 2147483647, 1, 3),
+('bx_timeline_repost_to_browse', 'object_id', 2147483647, 1, 4),
+('bx_timeline_repost_to_browse', 'search', 2147483647, 1, 5),
+('bx_timeline_repost_to_browse', 'list', 2147483647, 1, 6),
+('bx_timeline_repost_to_browse', 'controls', 2147483647, 1, 7),
+('bx_timeline_repost_to_browse', 'do_submit', 2147483647, 1, 8),
+('bx_timeline_repost_to_browse', 'do_cancel', 2147483647, 1, 9);
+
 
 -- COMMENTS
 INSERT INTO `sys_objects_cmts` (`Name`, `Module`, `Table`, `CharsPostMin`, `CharsPostMax`, `CharsDisplayMax`, `Html`, `PerView`, `PerViewReplies`, `BrowseType`, `IsBrowseSwitch`, `PostFormPosition`, `NumberOfLevels`, `IsDisplaySwitch`, `IsRatable`, `ViewingThreshold`, `IsOn`, `RootStylePrefix`, `BaseUrl`, `ObjectVote`, `TriggerTable`, `TriggerFieldId`, `TriggerFieldAuthor`, `TriggerFieldTitle`, `TriggerFieldComments`, `ClassName`, `ClassFile`) VALUES

+ 25 - 0
modules/boonex/timeline/js/repost.js

@@ -66,6 +66,31 @@ BxTimelineRepost.prototype.repostItem = function(oLink, iOwnerId, sType, sAction
     );
 };
 
+BxTimelineRepost.prototype.repostItemTo = function(oLink, iReposterId, sType, sAction, iId) {
+    var $this = this;
+    var oData = this._getDefaultData();
+    oData = jQuery.extend({}, oData, {
+        reposter_id: iReposterId,
+        type: sType,
+        action: sAction,
+        object_id: iId
+    });   
+
+    $(window).dolPopupAjax({
+        id: {value: this._aHtmlIds['to_popup'], force: true}, 
+        url: bx_append_url_params(this._sActionsUri + 'repost_to/', oData),
+        closeOnOuterClick: false,
+        removeOnClose: true,
+        onBeforeShow: function() {
+            $this.loadingIn(oLink, false);
+
+            $(oLink).parents(".bx-popup-applied:visible:first").dolPopupHide();
+        }
+    });
+
+    return false;
+};
+
 BxTimelineRepost.prototype.toggleByPopup = function(oLink, iId) {
     var oData = this._getDefaultData();
     oData['id'] = iId;

+ 34 - 0
modules/boonex/timeline/template/css/repost.css

@@ -13,6 +13,40 @@ div.bx-tl-by-list div.bx-base-pofile-unit {
     margin-bottom: 0px;
 }
 
+/*--- Repost To ---*/
+.ui-autocomplete.ui-front {
+    z-index: 10001;
+}
+.bx-tl-rt-list {
+    max-height: 200px;
+    overflow-x: hidden;
+    overflow-y: auto;
+}
+.bx-tl-rtlm-items {
+    display: -webkit-flex;
+    display: flex;
+    -webkit-align-items: flex-start;
+    align-items: flex-start;
+    -webkit-justify-content: flex-start;
+    justify-content: flex-start;
+    -webkit-flex-wrap: wrap;
+    flex-wrap: wrap;
+}
+.bx-tl-rtlm-item {
+    display: -webkit-flex;
+    display: flex;
+    -webkit-align-items: center;
+    align-items: center;
+    -webkit-justify-content: flex-start;
+    justify-content: flex-start;
+
+    -webkit-flex: 1 1 50%;
+    flex: 1 1 50%;
+}
+.bx-tl-rtlm-item .bx-tl-rtlm-unit .bx-base-pofile-unit {
+    margin: 0;
+}
+
 /*--- Repost Element Styles ---*/
 .bx-tl-repost .bx-tl-repost-element-holder .bx-tl-repost-do-repost.bx-tl-repost-disabled,
 .bx-tl-repost .bx-tl-repost-element-holder .bx-tl-repost-do-repost.bx-tl-repost-disabled .sys-icon {

+ 17 - 0
modules/boonex/timeline/template/repost_to_list.html

@@ -0,0 +1,17 @@
+<div class="__style_prefix__-rt-list">
+    <div class="__style_prefix__-rtl-modules">
+        <bx_repeat:modules>
+            <div class="__style_prefix__-rtl-module bx-def-margin-top-auto">
+                <div class="__style_prefix__-rtlm-title bx-def-font-large">__title__</div>
+                <div class="__style_prefix__-rtlm-items">
+                    <bx_repeat:contexts>
+                        <div class="__style_prefix__-rtlm-item bx-def-padding-thd-topbottom bx-clearfix">
+                            <div class="__style_prefix__-rtlm-checbox">__checkbox__</div>
+                            <div class="__style_prefix__-rtlm-unit bx-def-margin-left">__unit__</div>            
+                        </div>
+                    </bx_repeat:contexts>
+                </div>
+            </div>
+        </bx_repeat:modules>
+    </div>
+</div>

+ 20 - 0
modules/boonex/timeline/template/repost_to_popup.html

@@ -0,0 +1,20 @@
+<div class="__style_prefix__-repost-to bx-popup-width">
+    <div class="__style_prefix__-repost-to-cnt bx-def-padding">
+        __form__
+        <script language="javascript">
+            $(document).ready(function () {
+                $("#__form_id__").ajaxForm({ 
+                    dataType: "json",
+                    beforeSubmit: function (formData, jqForm, options) {
+                        bx_loading($("#__form_id__"), true);
+                    },
+                    success: function (oData) {
+                        $("#__form_id__").parents(".bx-popup-applied:visible:first").dolPopupHide();
+
+                        processJsonData(oData);
+                    }
+                });
+            });
+        </script>
+    </div>
+</div>

+ 15 - 8
template/scripts/BxBaseServiceProfiles.php

@@ -266,7 +266,7 @@ class BxBaseServiceProfiles extends BxDol
         return $oProfilesQuery->getOnlineCount();
     }
     
-    public function serviceGetProfilesModules ()
+    public function serviceGetProfilesModules ($bForceActAsProfile = true)
     {
         if (getParam('sys_db_cache_enable')) { // get list of profiles  modules from db cache, cache is invalidated when new module is installed
 
@@ -274,7 +274,7 @@ class BxBaseServiceProfiles extends BxDol
 
             $oCache = $oDb->getDbCacheObject ();
 
-            $sKey = $oDb->genDbCacheKey('profiles_modules_array');
+            $sKey = $oDb->genDbCacheKey('profiles_' . (!$bForceActAsProfile ? 'all_' : '') . 'modules_array');
             $sKeyTs = $oDb->genDbCacheKey('profiles_modules_ts');
 
             $mixedRetTs = $oCache->getData($sKeyTs);
@@ -288,7 +288,7 @@ class BxBaseServiceProfiles extends BxDol
 
             } else {
 
-                $aModulesArray = $this->_getProfilesModules ();
+                $aModulesArray = $this->_getProfilesModules ($bForceActAsProfile);
 
                 $oCache->setData($sKey, $aModulesArray);
                 $oCache->setData($sKeyTs, $iNewestModuleTs);
@@ -296,7 +296,7 @@ class BxBaseServiceProfiles extends BxDol
 
         } else {
 
-            $aModulesArray = $this->_getProfilesModules ();
+            $aModulesArray = $this->_getProfilesModules ($bForceActAsProfile);
 
         }
 
@@ -442,15 +442,22 @@ class BxBaseServiceProfiles extends BxDol
         return $aModuleNewest['date'];
     }
 
-    protected function _getProfilesModules ()
+    protected function _getProfilesModules($bForceActAsProfile = true)
     {
         $aRet = array();
+
         $aModules = BxDolModuleQuery::getInstance()->getModulesBy(array('type' => 'modules', 'active' => 1));
-        foreach ($aModules as $aModule) {
+        foreach($aModules as $aModule) {
             $oModule = BxDolModule::getInstance($aModule['name']);
-            if ($oModule instanceof iBxDolProfileService && $oModule->serviceActAsProfile())
-                $aRet[] = $aModule;
+            if(!($oModule instanceof iBxDolProfileService)) 
+                continue;
+
+            if($bForceActAsProfile && !$oModule->serviceActAsProfile())
+                continue;
+
+            $aRet[] = $aModule;
         }
+
         return $aRet;
     }