Răsfoiți Sursa

Merge branch 'master' of https://github.com/unaio/una

roman.lesnikov@gmail.com 3 ani în urmă
părinte
comite
d3ede82ec7
27 a modificat fișierele cu 355 adăugiri și 102 ștergeri
  1. 17 4
      inc/classes/BxDolConnection.php
  2. 2 2
      manifest.json.php
  3. 50 26
      modules/base/general/classes/BxBaseModGeneralModule.php
  4. 40 0
      modules/base/groups/classes/BxBaseModGroupsConnectionFans.php
  5. 0 16
      modules/base/groups/classes/BxBaseModGroupsMenuViewMeta.php
  6. 2 2
      modules/base/groups/template/unit.html
  7. 8 20
      modules/base/profile/classes/BxBaseModProfileFormEntry.php
  8. 32 0
      modules/base/profile/classes/BxBaseModProfileMenuViewMeta.php
  9. 22 0
      modules/base/profile/classes/BxBaseModProfileModule.php
  10. 4 2
      modules/base/text/template/unit_gallery.html
  11. 22 24
      modules/boonex/accounts/classes/BxAccntTemplate.php
  12. 8 0
      modules/boonex/accounts/template/css/manage_tools.css
  13. 7 0
      modules/boonex/accounts/template/profiles_more.html
  14. 22 0
      modules/boonex/courses/classes/BxCoursesConnectionFans.php
  15. 1 1
      modules/boonex/courses/install/sql/enable.sql
  16. 22 0
      modules/boonex/events/classes/BxEventsConnectionFans.php
  17. 1 1
      modules/boonex/events/install/sql/enable.sql
  18. 12 0
      modules/boonex/files/template/css/forms.css
  19. 1 1
      modules/boonex/files/template/entry-text.html
  20. 22 0
      modules/boonex/groups/classes/BxGroupsConnectionFans.php
  21. 1 1
      modules/boonex/groups/install/sql/enable.sql
  22. 22 0
      modules/boonex/organizations/classes/BxOrgsConnectionFans.php
  23. 1 1
      modules/boonex/organizations/install/sql/enable.sql
  24. 2 0
      modules/boonex/persons/install/sql/enable.sql
  25. 22 0
      modules/boonex/spaces/classes/BxSpacesConnectionFans.php
  26. 1 1
      modules/boonex/spaces/install/sql/enable.sql
  27. 11 0
      modules/boonex/timeline/classes/BxTimelineModule.php

+ 17 - 4
inc/classes/BxDolConnection.php

@@ -188,12 +188,11 @@ class BxDolConnection extends BxDolFactory implements iBxDolFactoryObject
             return _t('_sys_txt_access_denied');
 
         // check ACL
-        $aCheck = checkActionModule($iInitiator, 'connect', 'system', $isPerformAction);
-        if($aCheck[CHECK_ACTION_RESULT] !== CHECK_ACTION_RESULT_ALLOWED)
-            return $aCheck[CHECK_ACTION_MESSAGE];
+        if(($mixedResult = $this->_checkAllowedConnectInitiator($oInitiator, $isPerformAction)) !== CHECK_ACTION_RESULT_ALLOWED)
+            return $mixedResult;
 
         // check content's visibility
-        if(($mixedResult = $oContent->checkAllowedProfileView()) !== CHECK_ACTION_RESULT_ALLOWED)
+        if(($mixedResult = $this->_checkAllowedConnectContent($oContent)) !== CHECK_ACTION_RESULT_ALLOWED)
             return $mixedResult;
 
         if($isSwap)
@@ -207,6 +206,20 @@ class BxDolConnection extends BxDolFactory implements iBxDolFactoryObject
         return $isConnected ? _t('_sys_txt_access_denied') : CHECK_ACTION_RESULT_ALLOWED;
     }
 
+    protected function _checkAllowedConnectInitiator ($oInitiator, $isPerformAction = false)
+    {
+        $aCheck = checkActionModule($oInitiator->id(), 'connect', 'system', $isPerformAction);
+        if($aCheck[CHECK_ACTION_RESULT] !== CHECK_ACTION_RESULT_ALLOWED)
+            return $aCheck[CHECK_ACTION_MESSAGE];
+
+        return CHECK_ACTION_RESULT_ALLOWED;
+    }
+
+    protected function _checkAllowedConnectContent ($oContent)
+    {
+        return $oContent->checkAllowedProfileView();
+    }
+
     /**
      * Add new connection.
      * @param $iContent content to make connection to, in most cases some content id, or other profile id in case of friends

+ 2 - 2
manifest.json.php

@@ -16,7 +16,7 @@ require_once('./inc/header.inc.php');
 $aContent = [
     'name' => '',
     'short_name' => '',
-    'start_url' => '/',
+    'start_url' => parse_url(BX_DOL_URL_ROOT, PHP_URL_PATH),
     'display' => 'standalone',
 ];
 
@@ -72,4 +72,4 @@ if(!empty($aAdi) && is_array($aAdi))
 header("Content-Type: application/json");
 header("X-Robots-Tag: none");
 echo json_encode($aContent);
-?>
+?>

+ 50 - 26
modules/base/general/classes/BxBaseModGeneralModule.php

@@ -72,38 +72,18 @@ class BxBaseModGeneralModule extends BxDolModule
         return true;        
     }
 
-    
     public function actionUpdateImage($sFiledName, $iContentId, $sValue)
     {
-        $CNF = &$this->_oConfig->CNF;
-        $aData = $this->_oDb->getContentInfoById($iContentId);
-        if ($this->checkAllowedEdit($aData) === CHECK_ACTION_RESULT_ALLOWED){
-        
-            $this->_oDb->updateEntriesBy([$sFiledName => $sValue], [$CNF['FIELD_ID'] => $iContentId]);
-            //TODO add transcoder settings
-            $oImgStorage = BxDolStorage::getObjectInstance($CNF['OBJECT_STORAGE']);
-            $sImageUrl = $oImgStorage->getFileUrlById($sValue);
-            
-            $this->actionUpdateImagePosition($iContentId, $sFiledName, '', '');
-            
-            echo $sImageUrl;
-        }
-        
+        $mixedResult = $this->serviceUpdateImage($sFiledName, $iContentId, $sValue);
+        if($mixedResult !== false)
+            echo $mixedResult;
     }
-    
+
     public function actionUpdateImagePosition($iContentId, $sFiledName, $sH, $sV)
     {
-        $CNF = &$this->_oConfig->CNF;
-        $sFieldNamePos = 'FIELD_' . strtoupper($sFiledName) . '_POSITION';
-        if (isset($CNF[$sFieldNamePos])){
-            $sValue = '';
-            $CNF = &$this->_oConfig->CNF;
-            if ($sH != '' || $sV != '')
-                $sValue = json_encode(['x' => $sH, 'y' => $sV]);
-            $this->_oDb->updateEntriesBy([$CNF[$sFieldNamePos] => $sValue], [$CNF['FIELD_ID'] => $iContentId]);
-        }
+        $this->serviceUpdateImagePosition($iContentId, $sFiledName, $sH, $sV);
     }
-    
+
     public function actionApprove()
     {
         $CNF = &$this->_oConfig->CNF;
@@ -657,6 +637,48 @@ class BxBaseModGeneralModule extends BxDolModule
         return $aTextFields;
     }
 
+    public function serviceUpdateImage($sFiledName, $iContentId, $sValue)
+    {
+        $CNF = &$this->_oConfig->CNF;
+
+        $aData = $this->_oDb->getContentInfoById($iContentId);
+        if(empty($aData) || !is_array($aData))
+            return false;
+
+        if($this->checkAllowedEdit($aData) !== CHECK_ACTION_RESULT_ALLOWED)
+            return false;
+
+        //TODO add transcoder settings
+        $oImgStorage = BxDolStorage::getObjectInstance($CNF['OBJECT_STORAGE']);
+        if(!$oImgStorage)
+            return false;
+
+        $this->_oDb->updateEntriesBy([$sFiledName => $sValue], [$CNF['FIELD_ID'] => $iContentId]);
+
+        $this->serviceUpdateImagePosition($iContentId, $sFiledName, '', '');
+
+        $this->onUpdateImage($iContentId, $sFiledName, $sValue);
+
+        return $oImgStorage->getFileUrlById($sValue);
+    }
+
+    public function serviceUpdateImagePosition($iContentId, $sFiledName, $sH, $sV)
+    {
+        $CNF = &$this->_oConfig->CNF;
+
+        $sFieldNamePos = 'FIELD_' . strtoupper($sFiledName) . '_POSITION';
+        if(!isset($CNF[$sFieldNamePos]))
+            return false;
+
+        $sValue = '';
+        if($sH != '' || $sV != '')
+            $sValue = json_encode(['x' => $sH, 'y' => $sV]);
+
+        $this->_oDb->updateEntriesBy([$CNF[$sFieldNamePos] => $sValue], [$CNF['FIELD_ID'] => $iContentId]);
+
+        return true;
+    }
+
     public function serviceManageTools($sType = 'common')
     {
         if(!isLogged())
@@ -2847,6 +2869,8 @@ class BxBaseModGeneralModule extends BxDolModule
         $this->onPublished($mixedContent[$CNF['FIELD_ID']]);
     }
 
+    public function onUpdateImage($iContentId, $sFiledName, $sFiledValue, $iProfileId = 0) {}
+
     public function alertAfterAdd($aContentInfo) {}
     
     public function alertAfterEdit($aContentInfo) {}

+ 40 - 0
modules/base/groups/classes/BxBaseModGroupsConnectionFans.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    Groups Groups
+ * @ingroup     UnaModules
+ * 
+ * @{
+ */
+
+class BxBaseModGroupsConnectionFans extends BxTemplConnection
+{
+    protected $_sModule;
+    protected $_oModule;
+
+    public function __construct($aObject)
+    {
+        parent::__construct($aObject);
+
+        $this->_oModule = BxDolModule::getInstance($this->_sModule);
+    }
+
+    public function _checkAllowedConnectContent ($oContent)
+    {
+        $CNF = &$this->_oModule->_oConfig->CNF;
+
+        if(!empty($CNF['OBJECT_PRIVACY_VIEW']) && ($oPrivacy = BxDolPrivacy::getObjectInstance($CNF['OBJECT_PRIVACY_VIEW'])) !== false) {
+            $iContentId = $oContent->getContentId();
+            $aContentInfo = $this->_oModule->_oDb->getContentInfoById($iContentId);
+
+            if(in_array($aContentInfo[$CNF['FIELD_ALLOW_VIEW_TO']], array_merge($oPrivacy->getPartiallyVisiblePrivacyGroups(), ['s'])))
+                return CHECK_ACTION_RESULT_ALLOWED;
+        }
+
+        return parent::_checkAllowedConnectContent($oContent);
+    }
+}
+
+/** @} */

+ 0 - 16
modules/base/groups/classes/BxBaseModGroupsMenuViewMeta.php

@@ -34,22 +34,6 @@ class BxBaseModGroupsMenuViewMeta extends BxBaseModProfileMenuViewMeta
 
         return $oConnection->getCounter($this->_oContentProfile->id(), true, ['caption' => '_sys_menu_item_title_sm_members', 'custom_icon' => $sIcon], BX_CONNECTIONS_CONTENT_TYPE_INITIATORS);
     }
-
-    protected function _getMenuItemSubscribers($aItem)
-    {
-        $CNF = &$this->_oModule->_oConfig->CNF;
-
-        if(!$this->_bContentPublic || !$this->_oContentProfile)
-            return false;
-
-        $oConnection = BxDolConnection::getObjectInstance('sys_profiles_subscriptions');
-        if(!$oConnection)
-            return false;
-
-        $sIcon = BxTemplFunctions::getInstanceWithTemplate($this->_oTemplate)->getIconAsHtml(!empty($aItem['icon']) ? $aItem['icon'] : '');
-        
-        return $oConnection->getCounter($this->_oContentProfile->id(), false, ['caption' => '_sys_menu_item_title_sm_subscribers', 'custom_icon' => $sIcon], BX_CONNECTIONS_CONTENT_TYPE_INITIATORS);
-    }
 }
 
 /** @} */

+ 2 - 2
modules/base/groups/template/unit.html

@@ -18,8 +18,8 @@
         </a>
         <div class="bx-base-pofile-unit-info p-4 text-left">
             <div class="bx-base-pofile-unit-title">
-                <div class="bx-base-put-title">
-                    <a href="__content_url__" onclick="__content_click__" class="hover:underline text-gray-700 dark:text-gray-200 hover:text-gray-900 dark:hover:text-white text-xl font-semibold">__title__</a>__badges__
+                <div class="bx-base-put-title truncate">
+                    <a href="__content_url__" onclick="__content_click__" title="__title_attr__" class="hover:underline text-gray-700 dark:text-gray-200 hover:text-gray-900 dark:hover:text-white text-xl font-semibold">__title__</a>__badges__
                 </div>
                 <div class="bx-base-put-addon text-sm text-gray-500 dark:text-gray-400">__addon__</div>
             </div>

+ 8 - 20
modules/base/profile/classes/BxBaseModProfileFormEntry.php

@@ -218,33 +218,21 @@ class BxBaseModProfileFormEntry extends BxBaseModGeneralFormEntry
         if(!$bResult) 
             return;
 
-        $CNF = &$this->_oModule->_oConfig->CNF;
-
-        $aField2Method = [
-            $CNF['FIELD_PICTURE'] => 'picture',
-            $CNF['FIELD_COVER'] => 'cover',
-        ];
-
-        if(!empty($aField2Method[$sPictureField]))
-            bx_alert($this->_oModule->getName(), 'profile_' . $aField2Method[$sPictureField] . '_changed', $iFileId, $iProfileId, [
-                'object_author_id' => $iProfileId, 
-                'content' => $iContentId, 
-                'field' => $sPictureField
-            ]);
+        $this->_oModule->onUpdateImage($iContentId, $sPictureField, $iFileId, $iProfileId);
     }
 
     protected function _getProfilePhotoGhostTmplVars($sField, $aContentInfo = array())
     {
     	$CNF = &$this->_oModule->_oConfig->CNF;
 
-    	return array (
-			'name' => $this->aInputs[$sField]['name'],
+    	return [
+            'name' => $this->aInputs[$sField]['name'],
             'content_id' => $this->aInputs[$sField]['content_id'],
-			'bx_if:set_thumb' => array (
-				'condition' => false,
-				'content' => array (),
-			),
-		);
+            'bx_if:set_thumb' => [
+                'condition' => false,
+                'content' => [],
+            ]
+        ];
     }
 
     protected function _isAdmin ($iContentId = 0)

+ 32 - 0
modules/base/profile/classes/BxBaseModProfileMenuViewMeta.php

@@ -94,6 +94,38 @@ class BxBaseModProfileMenuViewMeta extends BxTemplMenuUnitMeta
         return $sResult;
     }
 
+    protected function _getMenuItemFriends($aItem)
+    {
+        $CNF = &$this->_oModule->_oConfig->CNF;
+
+        if(!$this->_bContentPublic || !$this->_oContentProfile)
+            return false;
+
+        $oConnection = BxDolConnection::getObjectInstance('sys_profiles_friends');
+        if(!$oConnection)
+            return false;
+
+        $sIcon = BxTemplFunctions::getInstanceWithTemplate($this->_oTemplate)->getIconAsHtml(!empty($aItem['icon']) ? $aItem['icon'] : '');
+
+        return $oConnection->getCounter($this->_oContentProfile->id(), true, ['caption' => '_sys_menu_item_title_sm_friends', 'custom_icon' => $sIcon], BX_CONNECTIONS_CONTENT_TYPE_INITIATORS);
+    }
+
+    protected function _getMenuItemSubscribers($aItem)
+    {
+        $CNF = &$this->_oModule->_oConfig->CNF;
+
+        if(!$this->_bContentPublic || !$this->_oContentProfile)
+            return false;
+
+        $oConnection = BxDolConnection::getObjectInstance('sys_profiles_subscriptions');
+        if(!$oConnection)
+            return false;
+
+        $sIcon = BxTemplFunctions::getInstanceWithTemplate($this->_oTemplate)->getIconAsHtml(!empty($aItem['icon']) ? $aItem['icon'] : '');
+        
+        return $oConnection->getCounter($this->_oContentProfile->id(), false, ['caption' => '_sys_menu_item_title_sm_subscribers', 'custom_icon' => $sIcon], BX_CONNECTIONS_CONTENT_TYPE_INITIATORS);
+    }
+
     protected function _getMenuItemViews($aItem)
     {
         $CNF = &$this->_oModule->_oConfig->CNF;

+ 22 - 0
modules/base/profile/classes/BxBaseModProfileModule.php

@@ -1864,6 +1864,28 @@ class BxBaseModProfileModule extends BxBaseModGeneralModule implements iBxDolCon
     }
 
     // ====== COMMON METHODS
+    public function onUpdateImage($iContentId, $sFiledName, $sFiledValue, $iProfileId = 0)
+    {
+        $CNF = &$this->_oConfig->CNF;
+
+        $sModule = $this->getName();
+
+        if(!$iProfileId && ($oProfile = BxDolProfile::getInstanceByContentAndType($iContentId, $sModule)) !== false)
+            $iProfileId = $oProfile->id();
+
+        $aField2Method = [
+            $CNF['FIELD_PICTURE'] => 'picture',
+            $CNF['FIELD_COVER'] => 'cover',
+        ];
+
+        if(!empty($aField2Method[$sFiledName]))
+            bx_alert($sModule, 'profile_' . $aField2Method[$sFiledName] . '_changed', $sFiledValue, $iProfileId, [
+                'object_author_id' => $iProfileId, 
+                'content' => $iContentId, 
+                'field' => $sFiledName
+            ]);
+    }
+
     protected function _alertParams($aContentInfo)
     {
         $aParams = parent::_alertParams($aContentInfo);

+ 4 - 2
modules/base/text/template/unit_gallery.html

@@ -14,8 +14,10 @@
         </bx_if:no_thumb>
         <div class="bx-base-text-unit-text flex flex-col flex-1 p-3 md:p-4 lg:p-6 pt-1 md:pt-2 lg:pt-3 box-border">
             <div class="bx-base-text-unit-badges pb-1 lg:pb-2">__badges__</div>
-            <div class="bx-base-text-unit-title flex-inline flex-auto max-h-14 truncate text-left">
-                <a href="__content_url__" class="text-left">__title__</a>
+            <div class="bx-base-text-unit-title flex-auto max-h-14">
+                <div class="bx-base-tut-title truncate text-left">
+                    <a href="__content_url__" class="text-left">__title__</a>
+                </div>
             </div>
             <div class="bx-base-text-unit-info flex flex-auto flex-col justify-end text-sm text-gray-500 dark:text-gray-400">
                 <bx_if:meta><div class="bx-base-general-unit-meta pt-2">__meta__</div></bx_if:meta>

+ 22 - 24
modules/boonex/accounts/classes/BxAccntTemplate.php

@@ -17,35 +17,34 @@ class BxAccntTemplate extends BxBaseModGeneralTemplate
         parent::__construct($oConfig, $oDb);
     }
 
-    public function getProfilesByAccount($aContentInfo, $iMaxVisible = 2)
+    public function getProfilesByAccount($aContentInfo, $iMaxVisible = 2, $iMaxInPopup = 20)
     {
         $CNF = &$this->_oConfig->CNF;
+        $iMax = $iMaxVisible + $iMaxInPopup;
 
         $aProfiles = BxDolAccount::getInstance($aContentInfo['id'])->getProfiles();
         $iProfiles = count($aProfiles);
 
-        $aTmplVars = array (
+        $aTmplVars = [
             'class_cnt' => '',
-            'bx_repeat:profiles' => array(),
-            'bx_if:profiles_more' => array(
+            'bx_repeat:profiles' => [],
+            'bx_if:profiles_more' => [
                 'condition' => $iProfiles > $iMaxVisible,
-                'content' => array(
+                'content' => [
                     'html_id' => $this->_oConfig->getHtmlIds('profile_more_popup') . $aContentInfo['id'],
                     'more' => _t('_bx_accnt_txt_more', $iProfiles - $iMaxVisible),
                     'more_attr' => bx_html_attribute(_t('_bx_accnt_txt_see_more')),
                     'popup' => '',
-                ),
-            ),
-        );
-
-        $aTmplVarsPopup = array (
-            'class_cnt' => ' bx-def-padding',
-            'bx_repeat:profiles' => array(),
-            'bx_if:profiles_more' => array(
-                'condition' => false,
-                'content' => array(),
-            ),
-        );
+                ],
+            ],
+        ];
+
+        $aTmplVarsPopup = [
+            'bx_repeat:profiles' => [],
+        ];
+
+        if($iProfiles > $iMax)
+            $aProfiles = array_slice($aProfiles, 0, $iMax);
 
         $i = 0;
         foreach ($aProfiles as $iProfileId => $aProfile) {
@@ -54,25 +53,24 @@ class BxAccntTemplate extends BxBaseModGeneralTemplate
                 continue;
 
             $sName = $oProfile->getDisplayName();
-            $aTmplVarsProfile = array (
+            $aTmplVarsProfile = [
             	'html_id' => $this->_oConfig->getHtmlIds('profile') . $aProfile['id'],
                 'id' => $oProfile->id(),
                 'url' => $oProfile->getUrl(),
                 'name' => strmaxtextlen($sName, $CNF['PARAM_PROFILE_NAME_LENGTH_MAX'], '...'),
-                'name_attr' =>  bx_html_attribute($sName)
-            );
+                'name_attr' => bx_html_attribute($sName)
+            ];
 
             if($i < $iMaxVisible)
-				$aTmplVars['bx_repeat:profiles'][] = $aTmplVarsProfile;
+                $aTmplVars['bx_repeat:profiles'][] = $aTmplVarsProfile;
             if($i >= $iMaxVisible)
                 $aTmplVarsPopup['bx_repeat:profiles'][] = $aTmplVarsProfile;
 
             ++$i;
         }
 
-        if($aTmplVarsPopup['bx_repeat:profiles']) {
-            $aTmplVars['bx_if:profiles_more']['content']['popup'] = BxTemplFunctions::getInstance()->transBox('', $this->parseHtmlByName('profiles.html', $aTmplVarsPopup));
-        }
+        if($aTmplVarsPopup['bx_repeat:profiles'])
+            $aTmplVars['bx_if:profiles_more']['content']['popup'] = BxTemplFunctions::getInstance()->transBox('', $this->parseHtmlByName('profiles_more.html', $aTmplVarsPopup));
 
         return $this->parseHtmlByName('profiles.html', $aTmplVars);
     }

+ 8 - 0
modules/boonex/accounts/template/css/manage_tools.css

@@ -16,4 +16,12 @@
 .bx-accnt-sr-done .bx-btn {
     display: inline-block;
     float: none;
+}
+
+/*--- Profiles popup ---*/
+.bx-accnt-profiles-popup {
+    max-width: 18rem;
+}
+.bx-accnt-profiles-popup-cnt > span:last-child {
+    display: none;
 }

+ 7 - 0
modules/boonex/accounts/template/profiles_more.html

@@ -0,0 +1,7 @@
+<div class="bx-accnt-profiles-popup">
+    <div class="bx-accnt-profiles-popup-cnt bx-def-padding">
+        <bx_repeat:profiles>
+            <a href="__url__" target="_blank" title="__name_attr__">__name__</a><span>,</span>
+        </bx_repeat:profiles>
+    </div>
+</div>

+ 22 - 0
modules/boonex/courses/classes/BxCoursesConnectionFans.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    Courses Courses
+ * @ingroup     UnaModules
+ *
+ * @{
+ */
+
+class BxCoursesConnectionFans extends BxBaseModGroupsConnectionFans
+{
+    public function __construct($aObject)
+    {
+        $this->_sModule = 'bx_courses';
+
+        parent::__construct($aObject);
+    }
+}
+
+/** @} */

+ 1 - 1
modules/boonex/courses/install/sql/enable.sql

@@ -505,7 +505,7 @@ INSERT INTO `sys_objects_search` (`ObjectName`, `Title`, `Order`, `ClassName`, `
 
 -- CONNECTIONS
 INSERT INTO `sys_objects_connection` (`object`, `table`, `profile_initiator`, `profile_content`, `type`, `override_class_name`, `override_class_file`) VALUES
-('bx_courses_fans', 'bx_courses_fans', 1, 1, 'mutual', '', '');
+('bx_courses_fans', 'bx_courses_fans', 1, 1, 'mutual', 'BxCoursesConnectionFans', 'modules/boonex/courses/classes/BxCoursesConnectionFans.php');
 
 -- STATS
 SET @iMaxOrderStats = (SELECT IFNULL(MAX(`order`), 0) FROM `sys_statistics`);

+ 22 - 0
modules/boonex/events/classes/BxEventsConnectionFans.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    Events Events
+ * @ingroup     UnaModules
+ *
+ * @{
+ */
+
+class BxEventsConnectionFans extends BxBaseModGroupsConnectionFans
+{
+    public function __construct($aObject)
+    {
+        $this->_sModule = 'bx_events';
+
+        parent::__construct($aObject);
+    }
+}
+
+/** @} */

+ 1 - 1
modules/boonex/events/install/sql/enable.sql

@@ -563,7 +563,7 @@ INSERT INTO `sys_objects_search` (`ObjectName`, `Title`, `Order`, `ClassName`, `
 
 -- CONNECTIONS
 INSERT INTO `sys_objects_connection` (`object`, `table`, `profile_initiator`, `profile_content`, `type`, `override_class_name`, `override_class_file`) VALUES
-('bx_events_fans', 'bx_events_fans', 1, 1, 'mutual', '', '');
+('bx_events_fans', 'bx_events_fans', 1, 1, 'mutual', 'BxEventsConnectionFans', 'modules/boonex/events/classes/BxEventsConnectionFans.php');
 
 -- STATS
 SET @iMaxOrderStats = (SELECT IFNULL(MAX(`order`), 0) FROM `sys_statistics`);

+ 12 - 0
modules/boonex/files/template/css/forms.css

@@ -0,0 +1,12 @@
+/*--- Uploader Ghost: Files ---*/
+#bx_files_upload #bx-form-element-attachments .bx-uploader-ghost {
+    justify-content: flex-end;
+}
+
+#bx_files #bx-form-element-attachments .bx-base-general-uploader-ghost {
+    position: relative;
+    display: block;
+
+    text-overflow: ellipsis;
+    overflow: hidden;
+}

+ 1 - 1
modules/boonex/files/template/entry-text.html

@@ -3,7 +3,7 @@
     <div class="bx-files-entity-preview bx-def-border-radius-block">__entry_preview__</div>
     <bx_if:show_content>
         <div class="bx-base-text-entity-content bx-def-constraint-list bx-def-constraint-pre bx-def-constraint-object bx-def-constraint-iframe bx-def-constraint-img bx-def-margin-top bx-def-vanilla-html">
-            <h1>__entry_title__</h1>
+            <h1 class="truncate">__entry_title__</h1>
             __entry_text__
         </div>
     </bx_if:show_content>

+ 22 - 0
modules/boonex/groups/classes/BxGroupsConnectionFans.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 BxGroupsConnectionFans extends BxBaseModGroupsConnectionFans
+{
+    public function __construct($aObject)
+    {
+        $this->_sModule = 'bx_groups';
+
+        parent::__construct($aObject);
+    }
+}
+
+/** @} */

+ 1 - 1
modules/boonex/groups/install/sql/enable.sql

@@ -520,7 +520,7 @@ INSERT INTO `sys_objects_search` (`ObjectName`, `Title`, `Order`, `ClassName`, `
 
 -- CONNECTIONS
 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', '', '');
+('bx_groups_fans', 'bx_groups_fans', 1, 1, 'mutual', 'BxGroupsConnectionFans', 'modules/boonex/groups/classes/BxGroupsConnectionFans.php');
 
 
 -- STATS

+ 22 - 0
modules/boonex/organizations/classes/BxOrgsConnectionFans.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    Organizations Organizations
+ * @ingroup     UnaModules
+ *
+ * @{
+ */
+
+class BxOrgsConnectionFans extends BxBaseModGroupsConnectionFans
+{
+    public function __construct($aObject)
+    {
+        $this->_sModule = 'bx_organizations';
+
+        parent::__construct($aObject);
+    }
+}
+
+/** @} */

+ 1 - 1
modules/boonex/organizations/install/sql/enable.sql

@@ -589,7 +589,7 @@ INSERT INTO `sys_objects_search` (`ObjectName`, `Title`, `Order`, `ClassName`, `
 
 -- CONNECTIONS
 INSERT INTO `sys_objects_connection` (`object`, `table`, `profile_initiator`, `profile_content`, `type`, `override_class_name`, `override_class_file`) VALUES
-('bx_organizations_fans', 'bx_organizations_fans', 1, 1, 'mutual', '', '');
+('bx_organizations_fans', 'bx_organizations_fans', 1, 1, 'mutual', 'BxOrgsConnectionFans', 'modules/boonex/organizations/classes/BxOrgsConnectionFans.php');
 
 
 -- STATS

+ 2 - 0
modules/boonex/persons/install/sql/enable.sql

@@ -294,6 +294,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`, `submenu_popup`, `visible_for_levels`, `visibility_custom`, `active`, `copyable`, `order`) VALUES 
 ('bx_persons_view_meta', 'bx_persons', 'membership', '_sys_menu_item_title_system_vm_membership', '_sys_menu_item_title_vm_membership', '', '', '', '', '', 0, 2147483647, '', 1, 0, 10),
 ('bx_persons_view_meta', 'bx_persons', 'badges', '_sys_menu_item_title_system_vm_badges', '_sys_menu_item_title_vm_badges', '', '', '', '', '', 0, 2147483647, '', 1, 0, 20),
+('bx_persons_view_meta', 'bx_persons', 'friends', '_sys_menu_item_title_system_sm_friends', '_sys_menu_item_title_sm_friends', '', '', '', '', '', 0, 2147483647, '', 1, 0, 23),
+('bx_persons_view_meta', 'bx_persons', 'subscribers', '_sys_menu_item_title_system_sm_subscribers', '_sys_menu_item_title_sm_subscribers', '', '', '', '', '', 0, 2147483647, '', 1, 0, 25),
 ('bx_persons_view_meta', 'bx_persons', 'views', '_sys_menu_item_title_system_sm_views', '_sys_menu_item_title_sm_views', '', '', '', '', '', 0, 2147483647, '', 1, 0, 30),
 ('bx_persons_view_meta', 'bx_persons', 'votes', '_sys_menu_item_title_system_sm_votes', '_sys_menu_item_title_sm_votes', '', '', '', '', '', 0, 2147483647, '', 1, 0, 40),
 ('bx_persons_view_meta', 'bx_persons', 'comments', '_sys_menu_item_title_system_sm_comments', '_sys_menu_item_title_sm_comments', '', '', '', '', '', 0, 2147483647, '', 1, 0, 50);

+ 22 - 0
modules/boonex/spaces/classes/BxSpacesConnectionFans.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
+ *
+ * @defdroup    Spaces Spaces
+ * @indroup     UnaModules
+ *
+ * @{
+ */
+
+class BxSpacesConnectionFans extends BxBaseModGroupsConnectionFans
+{
+    public function __construct($aObject)
+    {
+        $this->_sModule = 'bx_spaces';
+
+        parent::__construct($aObject);
+    }
+}
+
+/** @} */

+ 1 - 1
modules/boonex/spaces/install/sql/enable.sql

@@ -507,7 +507,7 @@ INSERT INTO `sys_objects_search` (`ObjectName`, `Title`, `Order`, `ClassName`, `
 
 -- CONNECTIONS
 INSERT INTO `sys_objects_connection` (`object`, `table`, `profile_initiator`, `profile_content`, `type`, `override_class_name`, `override_class_file`) VALUES
-('bx_spaces_fans', 'bx_spaces_fans', 1, 1, 'mutual', '', '');
+('bx_spaces_fans', 'bx_spaces_fans', 1, 1, 'mutual', 'BxSpacesConnectionFans', 'modules/boonex/spaces/classes/BxSpacesConnectionFans.php');
 
 -- STATS
 SET @iMaxOrderStats = (SELECT IFNULL(MAX(`order`), 0) FROM `sys_statistics`);

+ 11 - 0
modules/boonex/timeline/classes/BxTimelineModule.php

@@ -1037,6 +1037,8 @@ class BxTimelineModule extends BxBaseModNotificationsModule implements iBxDolCon
      */
     public function serviceGetCreatePostForm($aParams = array())
     {
+        $CNF = &$this->_oConfig->CNF;
+
     	$aParams = array_merge($this->_aFormParams, $aParams);
 
         $bContext = $aParams['context_id'] !== false;
@@ -1066,6 +1068,15 @@ class BxTimelineModule extends BxBaseModNotificationsModule implements iBxDolCon
     	if(!empty($aResult['form'])) {
             $bDynamicMode = isset($aParams['dynamic_mode']) && $aParams['dynamic_mode'];
 
+            if($this->_oConfig->isEditorAutoattach() && !empty($aResult['form_object'])) {
+                $aUploadersInfo = $aResult['form_object']->getUploadersInfo($CNF['FIELD_PHOTO']);
+                if(!empty($aUploadersInfo) && is_array($aUploadersInfo))
+                    $aParams = [
+                        'gparams' => ['sAutoUploader' => $aUploadersInfo['name'], 'sAutoUploaderId' => $aUploadersInfo['id']],
+                        'rparams' => $aParams
+                    ];
+            }
+
             $sCode = '';
             $sCode .= $this->_oTemplate->getJsCodePost($this->_iOwnerId, $aParams, true, $bDynamicMode);
             $sCode .= $aResult['form'];