Alex Trofimov 13 лет назад
Родитель
Сommit
f08a448a3e

+ 4 - 0
modules/boonex/persons/classes/BxPersonsConfig.php

@@ -18,11 +18,15 @@ class BxPersonsConfig extends BxDolModuleConfig {
     public static $FIELD_CHANGED = 'changed';
     public static $FIELD_NAME = 'fullname';
     public static $FIELD_PICTURE = 'picture';
+    public static $FIELD_COVER = 'cover';
 
     public static $OBJECT_STORAGE = 'bx_persons_pictures';
+    public static $OBJECT_STORAGE_COVER = 'bx_persons_pictures_covers';
     public static $OBJECT_IMAGES_TRANSCODER_THUMB = 'bx_persons_thumb';
     public static $OBJECT_IMAGES_TRANSCODER_ICON = 'bx_persons_icon';
     public static $OBJECT_IMAGES_TRANSCODER_PREVIEW = 'bx_persons_preview';
+    public static $OBJECT_IMAGES_TRANSCODER_COVER = 'bx_persons_cover';
+    public static $OBJECT_IMAGES_TRANSCODER_COVER_THUMB = 'bx_persons_cover_thumb';
 
     /**
      * Constructor

+ 2 - 2
modules/boonex/persons/classes/BxPersonsDb.php

@@ -28,8 +28,8 @@ class BxPersonsDb extends BxDolModuleDb {
         return $this->getRow($sQuery);
     }
 
-    function updateContentPictureById($iContentId, $iProfileId, $iPictureId) {
-        $sQuery = $this->prepare ("UPDATE `" . $this->_sPrefix . "data` SET `" . BxPersonsConfig::$FIELD_PICTURE . "` = ? WHERE `id` = ? AND `author` = ?", $iPictureId, $iContentId, $iProfileId);
+    function updateContentPictureById($iContentId, $iProfileId, $iPictureId, $sFieldPicture) {
+        $sQuery = $this->prepare ("UPDATE `" . $this->_sPrefix . "data` SET `" . $sFieldPicture . "` = ? WHERE `id` = ? AND `author` = ?", $iPictureId, $iContentId, $iProfileId);
         return $this->res($sQuery);
     }
 

+ 114 - 60
modules/boonex/persons/classes/BxPersonsFormPerson.php

@@ -18,10 +18,24 @@ class BxPersonsFormPerson extends BxTemplFormView {
 
     protected $_oModule;
     protected $_iAccountProfileId;
+    protected $_aImageFields;
 
     public function __construct($aInfo, $oTemplate = false) {                
         parent::__construct($aInfo, $oTemplate);
 
+        $this->_aImageFields = array (
+            BxPersonsConfig::$FIELD_PICTURE => array (
+                'storage_object' => BxPersonsConfig::$OBJECT_STORAGE,
+                'images_transcoder' => BxPersonsConfig::$OBJECT_IMAGES_TRANSCODER_THUMB,
+                'uploaders' => array('bx_persons_avatar'),
+            ),
+            BxPersonsConfig::$FIELD_COVER => array (
+                'storage_object' => BxPersonsConfig::$OBJECT_STORAGE_COVER,
+                'images_transcoder' => BxPersonsConfig::$OBJECT_IMAGES_TRANSCODER_COVER_THUMB,
+                'uploaders' => array('bx_persons_cover'),
+            ),
+        );
+
         bx_import('BxDolProfile');
         $oAccountProfile = BxDolProfile::getInstanceAccountProfile();
         if ($oAccountProfile)
@@ -29,38 +43,51 @@ class BxPersonsFormPerson extends BxTemplFormView {
 
         $this->_oModule = BxDolModule::getInstance('bx_persons');
 
-        if (isset($this->aInputs[BxPersonsConfig::$FIELD_PICTURE])) {
-            $this->aInputs[BxPersonsConfig::$FIELD_PICTURE]['storage_object'] = BxPersonsConfig::$OBJECT_STORAGE;
-            $this->aInputs[BxPersonsConfig::$FIELD_PICTURE]['uploaders'] = array('bx_persons_avatar');
-            $this->aInputs[BxPersonsConfig::$FIELD_PICTURE]['images_transcoder'] = BxPersonsConfig::$OBJECT_IMAGES_TRANSCODER_THUMB;
-            $this->aInputs[BxPersonsConfig::$FIELD_PICTURE]['multiple'] = false;
-            $this->aInputs[BxPersonsConfig::$FIELD_PICTURE]['content_id'] = 0;
-            $this->aInputs[BxPersonsConfig::$FIELD_PICTURE]['upload_buttons_titles'] = _t('_bx_persons_form_person_input_picture_btn_upload');
-            $this->aInputs[BxPersonsConfig::$FIELD_PICTURE]['ghost_template'] = '';
-        }   
+
+        $aDefaultsFieldImage = array (
+            'storage_object' => BxPersonsConfig::$OBJECT_STORAGE,
+            'uploaders' => array('bx_persons_avatar'),
+            'images_transcoder' => BxPersonsConfig::$OBJECT_IMAGES_TRANSCODER_THUMB,
+            'multiple' => false,
+            'content_id' => 0,
+            'upload_buttons_titles' => _t('_bx_persons_form_person_input_picture_btn_upload'),
+            'ghost_template' => '',
+        );
+
+        foreach ($this->_aImageFields as $sField => $aVals) {
+            if (!isset($this->aInputs[$sField]))
+                continue;
+            foreach ($aDefaultsFieldImage as $k => $v )
+                $this->aInputs[$sField][$k] = isset($aVals[$k]) ? $aVals[$k] : $v;
+        }
+
     }
 
     function initChecker ($aValues = array (), $aSpecificValues = array())  {
 
-        if (isset($this->aInputs[BxPersonsConfig::$FIELD_PICTURE])) {
+        foreach ($this->_aImageFields as $sField => $aVals) {
+            if (!isset($this->aInputs[$sField]))
+                continue;
 
             if ($aValues && !empty($aValues['id'])) 
-                $this->aInputs[BxPersonsConfig::$FIELD_PICTURE]['content_id'] = $aValues['id'];
+                $this->aInputs[$sField]['content_id'] = $aValues['id'];
 
             bx_import('BxDolUploader');
-            $oUploader = BxDolUploader::getObjectInstance($this->aInputs[BxPersonsConfig::$FIELD_PICTURE]['uploaders'][0], $this->aInputs[BxPersonsConfig::$FIELD_PICTURE]['storage_object'], rand(0, PHP_INT_MAX));
+            $oUploader = BxDolUploader::getObjectInstance($this->aInputs[$sField]['uploaders'][0], $this->aInputs[$sField]['storage_object'], rand(0, PHP_INT_MAX));
             
             $aVars = array (
-                'name' => $this->aInputs[BxPersonsConfig::$FIELD_PICTURE]['name'],
-                'content_id' => $this->aInputs[BxPersonsConfig::$FIELD_PICTURE]['content_id'],
-                'current_picture_id' => (isset($aValues[BxPersonsConfig::$FIELD_PICTURE]) ? $aValues[BxPersonsConfig::$FIELD_PICTURE] : 0),
+                'name' => $this->aInputs[$sField]['name'],
+                'content_id' => $this->aInputs[$sField]['content_id'],
+                'current_picture_id' => (isset($aValues[$sField]) ? $aValues[$sField] : 0),
                 'uploader_js_instance_name' => $oUploader->getNameJsInstanceUploader(),
                 'bx_if:not_required' => array (
-                    'condition' => !$this->aInputs[BxPersonsConfig::$FIELD_PICTURE]['required'],
-                    'content' => array(),
+                    'condition' => !$this->aInputs[$sField]['required'],
+                    'content' => array(
+                        'name' => $this->aInputs[$sField]['name'],
+                    ),
                 ),
             );            
-            $this->aInputs[BxPersonsConfig::$FIELD_PICTURE]['ghost_template'] = $this->_oModule->_oTemplate->parseHtmlByName('form_ghost_template.html', $aVars);
+            $this->aInputs[$sField]['ghost_template'] = $this->_oModule->_oTemplate->parseHtmlByName('form_ghost_template.html', $aVars);
         }
         
         return parent::initChecker($aValues, $aSpecificValues);
@@ -72,85 +99,112 @@ class BxPersonsFormPerson extends BxTemplFormView {
             BxPersonsConfig::$FIELD_ADDED => time(),
             BxPersonsConfig::$FIELD_CHANGED => time(),
         ));
-        if ($iContentId = parent::insert ($aValsToAdd, $isIgnore)) 
-            $this->_processFiles ((int)$this->getCleanValue(BxPersonsConfig::$FIELD_PICTURE), $iContentId, true);
+        if ($iContentId = parent::insert ($aValsToAdd, $isIgnore)) {
+            foreach ($this->_aImageFields as $sField => $aVals)
+                $this->_processFiles ((int)$this->getCleanValue($sField), $iContentId, true, $sField);
+        }
         return $iContentId;
     }
 
     function update ($iContentId, $aValsToAdd = array(), &$aTrackTextFieldsChanges = null) {        
         $aValsToAdd[BxPersonsConfig::$FIELD_CHANGED] = time();
-        if ($iRet = parent::update ($iContentId, $aValsToAdd, $aTrackTextFieldsChanges)) 
-            $this->_processFiles ((int)$this->getCleanValue(BxPersonsConfig::$FIELD_PICTURE), $iContentId);
+        if ($iRet = parent::update ($iContentId, $aValsToAdd, $aTrackTextFieldsChanges)) {
+            foreach ($this->_aImageFields as $sField => $aVals)
+                $this->_processFiles ((int)$this->getCleanValue($sField), $iContentId, false, $sField);
+        }
         return $iRet;
     }
 
     function delete ($iContentId, $aContentInfo = array()) {
 
-        if (!$this->_deleteFile($aContentInfo[BxPersonsConfig::$FIELD_PICTURE]))
+        // TODO: clean db field after deletion
+        // TODO: delete proper file! cover or avatar - NOT BOTH!
+        // TODO: also old image is not deleted when new image is uploaded
+        if (!$this->_deleteFile($aContentInfo[BxPersonsConfig::$FIELD_PICTURE], BxPersonsConfig::$OBJECT_STORAGE) && !$this->_deleteFile($aContentInfo[BxPersonsConfig::$FIELD_COVER], BxPersonsConfig::$OBJECT_STORAGE_COVER))
             return false;
 
         return parent::delete($iContentId);
     }
 
-    function deleteGhost ($iFileId, $iContentId, $isRestoreOriginal = true) {
+    function deleteGhost ($iFileId, $iContentId, $isRestoreOriginal = true, $sFieldName = '') {
 
         if (CHECK_ACTION_RESULT_ALLOWED !== ($sMsg = $this->_oModule->isAllowedAdd()))
             return $sMsg;
 
-        bx_import('BxDolStorage');
-        $oStorage = BxDolStorage::getObjectInstance(BxPersonsConfig::$OBJECT_STORAGE);
-        if (!$oStorage)
-            return _t('_sys_txt_error_occured');
+        foreach ($this->_aImageFields as $sField => $aVals) {
 
-        if (!$oStorage->deleteFile($iFileId, $this->_iAccountProfileId))
-            return _t('_sys_txt_error_occured');
+            if ($sField != $sFieldName)
+                continue;
 
-        $this->_oModule->_oDb->updateContentPictureById($iContentId, $this->_iAccountProfileId, 0);
+            bx_import('BxDolStorage');
+            $oStorage = BxDolStorage::getObjectInstance($aVals['storage_object']);
+            if (!$oStorage)
+                return _t('_sys_txt_error_occured');
+
+            if (!$oStorage->deleteFile($iFileId, $this->_iAccountProfileId))
+                return _t('_sys_txt_error_occured');
+
+            $this->_oModule->_oDb->updateContentPictureById($iContentId, $this->_iAccountProfileId, 0, $sField);
+        }
 
         return '';
     }
 
-    function discardGhost ($iFileId, $iContentId, $isRestoreOriginal = true) {
+    function discardGhost ($iFileId, $iContentId, $isRestoreOriginal = true, $sFieldName = '') {
 
         if (CHECK_ACTION_RESULT_ALLOWED !== ($sMsg = $this->_oModule->isAllowedAdd()))
             return $sMsg;
 
-        bx_import('BxDolStorage');
-        $oStorage = BxDolStorage::getObjectInstance(BxPersonsConfig::$OBJECT_STORAGE);
-        if (!$oStorage)
-            return _t('_sys_txt_error_occured');
-    
+
+        foreach ($this->_aImageFields as $sField => $aVals) {
+
+            if ($sField != $sFieldName)
+                continue;
+
+            bx_import('BxDolStorage');
+            $oStorage = BxDolStorage::getObjectInstance($aVals['storage_object']);
+            if (!$oStorage)
+                return _t('_sys_txt_error_occured');
         
-        $aFiles = $oStorage->getGhosts($this->_iAccountProfileId, $iContentId);        
-        if (!$aFiles)
-            return _t('_sys_txt_error_occured');
-
-        $isFileDeleted = false;
-        foreach ($aFiles as $aFile) {
-            if ($aFile['id'] == $iFileId) {
-                $isFileDeleted = $oStorage->deleteFile($aFile['id'], $this->_iAccountProfileId);
-                break;
-            }
-        }
- 
-        if (!$isFileDeleted)
-            return _t('_sys_txt_error_occured');
+            
+            $aFiles = $oStorage->getGhosts($this->_iAccountProfileId, $iContentId);        
+            if (!$aFiles)
+                return _t('_sys_txt_error_occured');
 
-        if ($isRestoreOriginal && $iContentId) {
-            $aContentInfo = $this->_oModule->_oDb->getContentInfoById($iContentId);
-            if (!$aContentInfo)
+            $isFileDeleted = false;
+            foreach ($aFiles as $aFile) {
+                if ($aFile['id'] == $iFileId) {
+                    $isFileDeleted = $oStorage->deleteFile($aFile['id'], $this->_iAccountProfileId);
+                    break;
+                }
+            }
+     
+            if (!$isFileDeleted)
                 return _t('_sys_txt_error_occured');
-            if ($aContentInfo[BxPersonsConfig::$FIELD_PICTURE])
-                if (!$oStorage->insertGhost($aContentInfo[BxPersonsConfig::$FIELD_PICTURE], $this->_iAccountProfileId, $iContentId))
+
+            if ($isRestoreOriginal && $iContentId) {
+                $aContentInfo = $this->_oModule->_oDb->getContentInfoById($iContentId);
+                if (!$aContentInfo)
                     return _t('_sys_txt_error_occured');
+
+                
+                if ($aContentInfo[$sField])
+                    if (!$oStorage->insertGhost($aContentInfo[$sField], $this->_iAccountProfileId, $iContentId))
+                        return _t('_sys_txt_error_occured');
+                
+            }
+
         }
 
         return '';
     }
 
-    function _processFiles ($iFileId, $iContentId = 0, $isCheckForZero = false) {
+    function _processFiles ($iFileId, $iContentId = 0, $isCheckForZero = false, $sField = '') {
+        if (!isset($this->_aImageFields[$sField]))
+            return false;
+
         bx_import('BxDolStorage');
-        $oStorage = BxDolStorage::getObjectInstance(BxPersonsConfig::$OBJECT_STORAGE);
+        $oStorage = BxDolStorage::getObjectInstance($this->_aImageFields[$sField]['storage_object']);
         if (!$oStorage)
             return false;
 
@@ -178,13 +232,13 @@ class BxPersonsFormPerson extends BxTemplFormView {
         return $iErrors ? false : true;
     }
 
-    function _deleteFile ($iFileId) {
+    function _deleteFile ($iFileId, $sStorageObject) {
 
         if (!$iFileId)
             return true;        
 
         bx_import('BxDolStorage');
-        if (!($oStorage = BxDolStorage::getObjectInstance(BxPersonsConfig::$OBJECT_STORAGE)))
+        if (!($oStorage = BxDolStorage::getObjectInstance($sStorageObject)))
             return false;
 
         if (!$oStorage->getFile($iFileId))

+ 4 - 0
modules/boonex/persons/classes/BxPersonsMenuViewPerson.php

@@ -37,6 +37,10 @@ class BxPersonsMenuViewPerson extends BxTemplMenu {
      */ 
     protected function _isVisible ($a) {
 
+        // don't show current item, also this will solve problem when only one view note item is visible
+        if ('bx_persons_view' == $this->_sObject && $this->_isSelected($a))
+            return false;
+
         $sFuncCheckAccess = false;
         switch ($a['name']) {
             case 'view-persons-profile':

+ 21 - 21
modules/boonex/persons/classes/BxPersonsModule.php

@@ -145,7 +145,20 @@ class BxPersonsModule extends BxDolModule implements iBxDolProfileService {
         return $oProfileForms->viewDataForm((int)$iContentId);
     }
 
-    public function serviceProfilePicture ($iContentId = 0) {
+    public function serviceProfileCover ($iContentId = 0) {
+       if (!$iContentId)
+            $iContentId = bx_process_input(bx_get('id'), BX_DATA_INT);
+        if (!$iContentId)
+            return false;
+
+        $aContentInfo = $this->_oDb->getContentInfoById($iContentId);
+        if (!$aContentInfo)
+            return false;
+
+        return $this->_oTemplate->cover($aContentInfo);
+    }
+
+    public function serviceProfileFriends ($iContentId = 0) {
         if (!$iContentId)
             $iContentId = bx_process_input(bx_get('id'), BX_DATA_INT);
         if (!$iContentId)
@@ -155,20 +168,7 @@ class BxPersonsModule extends BxDolModule implements iBxDolProfileService {
         if (!$aContentInfo)
             return false;
         
-        $sImageUrl = '';
-        if (isset($aContentInfo[BxPersonsConfig::$FIELD_PICTURE]) && $aContentInfo[BxPersonsConfig::$FIELD_PICTURE]) {
-            bx_import('BxDolImageTranscoder');        
-            $oImagesTranscoder = BxDolImageTranscoder::getObjectInstance(BxPersonsConfig::$OBJECT_IMAGES_TRANSCODER_PREVIEW);
-            if (!$oImagesTranscoder)
-                return false;
-            $sImageUrl = $oImagesTranscoder->getImageUrl($aContentInfo[BxPersonsConfig::$FIELD_PICTURE]);
-        } 
-
-        if (!$sImageUrl)
-            $sImageUrl = $this->_oTemplate->getImageUrl('no-picture-preview.png');
-
-        $aVars = array ('url' => $sImageUrl);
-        return $this->_oTemplate->parseHtmlByName('block_picture.html', $aVars);
+        return 'TODO: friends here';
     }
 
     // ====== ACTION METHODS
@@ -225,15 +225,15 @@ class BxPersonsModule extends BxDolModule implements iBxDolProfileService {
         $oTemplate->getPageCode();
     }
 
-    function actionDiscardGhost ($iFileId, $iContentId = 0) {
-        $this->_actionWithGhost('discardGhost', $iFileId, $iContentId);
+    function actionDiscardGhost ($iFileId, $iContentId = 0, $sFieldName = '') {
+        $this->_actionWithGhost('discardGhost', $iFileId, $iContentId, $sFieldName);
     }
 
-    function actionDeleteGhost ($iFileId, $iContentId = 0) {
-        $this->_actionWithGhost('deleteGhost', $iFileId, $iContentId);
+    function actionDeleteGhost ($iFileId, $iContentId = 0, $sFieldName = '') {
+        $this->_actionWithGhost('deleteGhost', $iFileId, $iContentId, $sFieldName);
     }
 
-    function _actionWithGhost ($sAction, $iFileId, $iContentId = 0) {
+    function _actionWithGhost ($sAction, $iFileId, $iContentId = 0, $sFieldName = '') {
         $iFileId = (int)$iFileId;
         $iContentId = (int)$iContentId;
 
@@ -247,7 +247,7 @@ class BxPersonsModule extends BxDolModule implements iBxDolProfileService {
         $oForm = BxDolForm::getObjectInstance('bx_person', 'bx_person_add'); 
 
         header('Content-type: text/html; charset=utf-8');
-        echo $oForm->$sAction($iFileId, $iContentId);
+        echo $oForm->$sAction($iFileId, $iContentId, true, $sFieldName);
         exit;
     }
 

+ 25 - 6
modules/boonex/persons/classes/BxPersonsPageProfile.php

@@ -11,13 +11,17 @@
 
 bx_import('BxTemplPage');
 bx_import('BxDolModule');
+bx_import('BxDolMenu');
+bx_import('BxDolProfile');
 
 /**
  * Profile create/edit/delete pages.
  */
 class BxPersonsPageProfile extends BxTemplPage {    
     
-    protected $_aContentInfo = false;
+    protected $_aContentInfo;
+    protected $_oProfile;
+    protected $_oProfileAuthor;
 
     protected $_aMapStatus2LangKey = array (
         BX_PROFILE_STATUS_PENDING => '_bx_persons_txt_account_pending',
@@ -27,20 +31,35 @@ class BxPersonsPageProfile extends BxTemplPage {
     public function __construct($aObject, $oTemplate = false) {
         parent::__construct($aObject, $oTemplate);
 
+        // get profile info
         $iContentId = bx_process_input(bx_get('id'), BX_DATA_INT);
         if ($iContentId) {
             $oModuleMain = BxDolModule::getInstance('bx_persons');
             $this->_aContentInfo = $oModuleMain->_oDb->getContentInfoById($iContentId);
+            $this->_oProfileAuthor = $this->_aContentInfo ? BxDolProfile::getInstance($this->_aContentInfo[BxPersonsConfig::$FIELD_AUTHOR]) : false;
+            $this->_oProfile = $this->_oProfileAuthor ? BxDolProfile::getInstanceByContentTypeAccount($iContentId, 'bx_persons', $this->_oProfileAuthor->getAccountId()) : false;
         }
 
-        if ($this->_aContentInfo)
-            $this->addMarkers($this->_aContentInfo); // every profile field can be used as marker
+        if (!$this->_aContentInfo || !$this->_oProfile)
+            return;
 
-        bx_import('BxDolProfile');        
-        $oProfileAuthor = $this->_aContentInfo ? BxDolProfile::getInstance($this->_aContentInfo['author']) : false;
+        // select view note submenu        
+        $oMenuSumbemu = BxDolMenu::getObjectInstance('sys_site_submenu');
+        $oMenuSumbemu->setObjectSubmenu('bx_persons_view_submenu', array (
+            'title' => $this->_oProfile->getDisplayName(),
+            'link' => $this->_oProfile->getUrl(),
+            'icon' => $this->_oProfile->getIcon(),
+        ));
+
+        // set actions menu
+        $oMenuAction = BxDolMenu::getObjectInstance('sys_site_action');
+        $oMenuAction->setActionsMenu('bx_persons_view');        
+
+        // add replacible markers
+        $this->addMarkers($this->_aContentInfo); // every profile field can be used as marker
 
         // display message if profile isn't active
-        if ($oProfileAuthor && bx_get_logged_profile_id() == $oProfileAuthor->id()) { 
+        if (bx_get_logged_profile_id() == $this->_oProfileAuthor->id()) { 
             $sStatus = $this->_aContentInfo['profile_status'];
             if (isset($this->_aMapStatus2LangKey[$sStatus])) {
                 bx_import('BxDolInformer');

+ 43 - 9
modules/boonex/persons/classes/BxPersonsTemplate.php

@@ -29,8 +29,26 @@ class BxPersonsTemplate extends BxDolModuleTemplate {
      */
     function unit ($aData, $sTemplateName = 'unit.html') {
 
-        // get picture thumb url
-        $sPictureThumb = $this->thumb ($aData);
+        // get person's url
+        bx_import('BxDolPermalinks');
+        $sUrl = BX_DOL_URL_ROOT . BxDolPermalinks::getInstance()->permalink('page.php?i=view-persons-profile&id=' . $aData['id']);
+
+        // generate html
+        $aVars = array (
+            'id' => $aData['id'],
+            'thumb_url' => $this->thumb ($aData),
+            'content_url' => $sUrl,
+            'title' => $aData[BxPersonsConfig::$FIELD_NAME],
+        );
+
+        return $this->parseHtmlByName($sTemplateName, $aVars);
+
+    }
+
+    /**
+     * Get profile cover
+     */
+    function cover ($aData, $sTemplateName = 'cover.html') {
 
         // get person's url
         bx_import('BxDolPermalinks');
@@ -39,7 +57,8 @@ class BxPersonsTemplate extends BxDolModuleTemplate {
         // generate html
         $aVars = array (
             'id' => $aData['id'],
-            'thumb_url' => $sPictureThumb,
+            'cover_url' => $this->urlCover ($aData),
+            'preview_url' => $this->urlPreview ($aData),
             'content_url' => $sUrl,
             'title' => $aData[BxPersonsConfig::$FIELD_NAME],
         );
@@ -52,27 +71,42 @@ class BxPersonsTemplate extends BxDolModuleTemplate {
      * Get profile picture thumb url
      */
     function thumb ($aData, $bSubstituteNoImage = true) {
-        return $this->_image (BxPersonsConfig::$OBJECT_IMAGES_TRANSCODER_THUMB, 'no-picture-thumb.png', $aData, $bSubstituteNoImage);
+        return $this->_image (BxPersonsConfig::$FIELD_PICTURE, BxPersonsConfig::$OBJECT_IMAGES_TRANSCODER_THUMB, 'no-picture-thumb.png', $aData, $bSubstituteNoImage);
     }
 
     /**
      * Get profile picture icon url
      */
     function icon ($aData, $bSubstituteNoImage = true) {
-        return $this->_image (BxPersonsConfig::$OBJECT_IMAGES_TRANSCODER_ICON, 'no-picture-icon.png', $aData, $bSubstituteNoImage);
+        return $this->_image (BxPersonsConfig::$FIELD_PICTURE, BxPersonsConfig::$OBJECT_IMAGES_TRANSCODER_ICON, 'no-picture-icon.png', $aData, $bSubstituteNoImage);
+    }
+
+    /**
+     * Get profile picture icon url
+     */
+    function urlPreview ($aData, $bSubstituteNoImage = true) {
+        return $this->_image (BxPersonsConfig::$FIELD_PICTURE, BxPersonsConfig::$OBJECT_IMAGES_TRANSCODER_PREVIEW, 'no-picture-preview.png', $aData, $bSubstituteNoImage);
+    }
+
+    /**
+     * Get profile cover image url
+     */
+    function urlCover ($aData, $bSubstituteNoImage = true) {
+        return $this->_image (BxPersonsConfig::$FIELD_COVER, BxPersonsConfig::$OBJECT_IMAGES_TRANSCODER_COVER, 'no-picture-cover.jpg', $aData, $bSubstituteNoImage);
     }
 
     /**
      * Get profile picture icon url
      */
-    function _image ($sTranscodeObject, $sNoImage, $aData, $bSubstituteNoImage = true) {
-        if ($aData[BxPersonsConfig::$FIELD_PICTURE]) {
+    function _image ($sField, $sTranscodeObject, $sNoImage, $aData, $bSubstituteNoImage = true) {
+        $sImageUrl = false;
+        if ($aData[$sField]) {
             bx_import('BxDolImageTranscoder');                    
             $oImagesTranscoder = BxDolImageTranscoder::getObjectInstance($sTranscodeObject);
             if ($oImagesTranscoder)
-                return $oImagesTranscoder->getImageUrl($aData[BxPersonsConfig::$FIELD_PICTURE]);
+                $sImageUrl = $oImagesTranscoder->getImageUrl($aData[$sField]);
         }
-        return $bSubstituteNoImage ? $this->getImageUrl('no-picture-icon.png') : '';
+        return $bSubstituteNoImage && !$sImageUrl? $this->getImageUrl($sNoImage) : $sImageUrl;
     }
 }
 

+ 2 - 2
modules/boonex/persons/classes/BxPersonsAvatarUploader.php → modules/boonex/persons/classes/BxPersonsUploader.php

@@ -12,9 +12,9 @@
 bx_import('BxTemplUploaderSimple');
 
 /**
- * Person avatar uploader
+ * Person uploader for avatar and cover images
  */
-class BxPersonsAvatarUploader extends BxTemplUploaderSimple {
+class BxPersonsUploader extends BxTemplUploaderSimple {
 
     protected $_iAccountProfileId;
 

+ 14 - 4
modules/boonex/persons/install/langs/en.xml

@@ -19,14 +19,16 @@
 	<string name="_bx_persons_form_person_input_sys_picture"><![CDATA[Profile Picture]]></string>
 	<string name="_bx_persons_form_person_input_picture"><![CDATA[Profile Picture]]></string>
 	<string name="_bx_persons_form_person_input_picture_err"><![CDATA[Profile picture is mandatory.]]></string>
+	<string name="_bx_persons_form_person_input_sys_cover"><![CDATA[Cover Image]]></string>
+	<string name="_bx_persons_form_person_input_cover"><![CDATA[Cover Image]]></string>
 	<string name="_bx_persons_form_person_input_sys_delete_confirm"><![CDATA[Delete confirmation]]></string>
 	<string name="_bx_persons_form_person_input_delete_confirm"><![CDATA[I am sure I want to delete this profile]]></string>
 	<string name="_bx_persons_form_person_input_delete_confirm_info"><![CDATA[This action can not be undone.]]></string>
 	<string name="_bx_persons_form_person_input_delete_confirm_error"><![CDATA[Please check this checkbox if you really want to delete your profile.]]></string>
 	<string name="_bx_persons_form_person_input_picture_btn_upload"><![CDATA[Choose Picture]]></string>
-    <string name="_bx_persons_form_person_input_picture_txt_new"><![CDATA[New Profile Picture]]></string>
+    <string name="_bx_persons_form_person_input_picture_txt_new"><![CDATA[New Picture]]></string>
     <string name="_bx_persons_form_person_input_picture_txt_discard"><![CDATA[Discard]]></string>
-    <string name="_bx_persons_form_person_input_picture_txt_current"><![CDATA[Current Profile Picture]]></string>
+    <string name="_bx_persons_form_person_input_picture_txt_current"><![CDATA[Current Picture]]></string>
     <string name="_bx_persons_form_person_input_picture_txt_delete"><![CDATA[Delete]]></string>
 
 	<string name="_bx_persons_acl_action_create_profile"><![CDATA[Create Person's Profile]]></string>
@@ -44,15 +46,21 @@
 	<string name="_bx_persons_page_title_delete_profile"><![CDATA[Delete Profile]]></string>
 	<string name="_bx_persons_page_block_title_delete_profile"><![CDATA[Delete Profile]]></string>
 	<string name="_bx_persons_page_title_sys_view_profile"><![CDATA[View Person's Profile]]></string>
-	<string name="_bx_persons_page_title_view_profile"><![CDATA[Person - {fullname}]]></string>
+	<string name="_bx_persons_page_title_view_profile"><![CDATA[{fullname}]]></string>
 	<string name="_bx_persons_page_block_title_profile_info"><![CDATA[Info]]></string>
-	<string name="_bx_persons_page_block_title_profile_picture"><![CDATA[Picture]]></string>
+	<string name="_bx_persons_page_block_title_profile_friends"><![CDATA[Friends]]></string>
+	<string name="_bx_persons_page_block_title_profile_cover"><![CDATA[Profile Cover]]></string>
 	<string name="_bx_persons_page_block_title_profile_menu"><![CDATA[Menu]]></string>
 	<string name="_bx_persons_page_title_browse_recent"><![CDATA[Persons]]></string>
 	<string name="_bx_persons_page_block_title_latest_persons"><![CDATA[Recent Persons]]></string>
+	<string name="_bx_persons_page_title_sys_profile_info"><![CDATA[Profile Info]]></string>
+	<string name="_bx_persons_page_title_profile_info"><![CDATA[Info about {fullname}]]></string>
+
 
     <string name="_bx_persons_menu_set_title_view_person"><![CDATA[View Person]]></string>
+    <string name="_bx_persons_menu_set_title_view_person_submenu"><![CDATA[View Person Submenu]]></string>
     <string name="_bx_persons_menu_title_view_person"><![CDATA[View Person]]></string>
+    <string name="_bx_persons_menu_title_view_person_submenu"><![CDATA[View Person Submenu]]></string>
     <string name="_bx_persons_menu_item_title_system_edit_person"><![CDATA[Edit Person]]></string>
     <string name="_bx_persons_menu_item_title_edit_person"><![CDATA[Edit Profile]]></string>
     <string name="_bx_persons_menu_item_title_system_delete_person"><![CDATA[Delete Person]]></string>
@@ -63,6 +71,8 @@
     <string name="_bx_persons_menu_item_title_persons_profile"><![CDATA[Person]]></string>
     <string name="_bx_persons_menu_item_title_system_create_person"><![CDATA[Create Person]]></string>
     <string name="_bx_persons_menu_item_title_create_person"><![CDATA[Create Person]]></string>
+    <string name="_bx_persons_menu_item_title_system_view_person_info"><![CDATA[Info]]></string>
+    <string name="_bx_persons_menu_item_title_view_person_info"><![CDATA[Info]]></string>
 
 	<string name="_bx_persons_txt_error_profile_creation"><![CDATA[Profile creation failed]]></string>
 	<string name="_bx_persons_txt_error_profile_update"><![CDATA[Profile update failed]]></string>

+ 8 - 7
modules/boonex/persons/install/sql/disable.sql

@@ -9,28 +9,29 @@ DELETE FROM `sys_options_types` WHERE `id` = @iTypeId;
 
 -- STORAGES & TRANSCODERS
 
-DELETE FROM `sys_objects_storage` WHERE `object` = 'bx_persons_pictures' OR `object` = 'bx_persons_pictures_resized';
-DELETE FROM `sys_storage_tokens` WHERE `object` = 'bx_persons_pictures' OR `object` = 'bx_persons_pictures_resized';
+DELETE FROM `sys_objects_storage` WHERE `object` IN('bx_persons_pictures', 'bx_persons_pictures_resized', 'bx_persons_pictures_covers');
+DELETE FROM `sys_storage_tokens` WHERE `object` IN('bx_persons_pictures', 'bx_persons_pictures_resized', 'bx_persons_pictures_covers');
 
-DELETE FROM `sys_objects_transcoder_images` WHERE `object` = 'bx_persons_icon' OR `object` = 'bx_persons_thumb' OR `object` = 'bx_persons_preview';
-DELETE FROM `sys_transcoder_images_files` WHERE `transcoder_object` = 'bx_persons_icon' OR `transcoder_object` = 'bx_persons_thumb' OR `transcoder_object` = 'bx_persons_preview';
+DELETE FROM `sys_objects_transcoder_images` WHERE `object` IN('bx_persons_icon', 'bx_persons_thumb', 'bx_persons_preview', 'bx_persons_cover', 'bx_persons_cover_thumb');
+DELETE FROM `sys_transcoder_images_filters` WHERE `transcoder_object` IN('bx_persons_icon', 'bx_persons_thumb', 'bx_persons_preview', 'bx_persons_cover', 'bx_persons_cover_thumb');
+DELETE FROM `sys_transcoder_images_files` WHERE `transcoder_object` IN('bx_persons_icon', 'bx_persons_thumb', 'bx_persons_preview', 'bx_persons_cover', 'bx_persons_cover_thumb');
 -- TODO: delete resized picture files as well
 TRUNCATE TABLE `bx_persons_pictures_resized`; 
 
 -- UPLOADERS
 
-DELETE FROM `sys_objects_uploader` WHERE `object` = 'bx_persons_avatar';
+DELETE FROM `sys_objects_uploader` WHERE `object` IN('bx_persons_avatar', 'bx_persons_cover');
 
 -- PAGES
 
 DELETE FROM `sys_objects_page` WHERE `module` = 'bx_persons';
-DELETE FROM `sys_pages_blocks` WHERE `module` = 'bx_persons' OR `object` = 'bx_persons_create_profile' OR `object` = 'bx_persons_delete_profile' OR `object` = 'bx_persons_edit_profile' OR `object` = 'bx_persons_view_profile';
+DELETE FROM `sys_pages_blocks` WHERE `module` = 'bx_persons' OR `object` IN('bx_persons_create_profile', 'bx_persons_delete_profile', 'bx_persons_edit_profile', 'bx_persons_view_profile', 'bx_persons_profile_info');
 
 -- MENU
 
 DELETE FROM `sys_objects_menu` WHERE `module` = 'bx_persons';
 DELETE FROM `sys_menu_sets` WHERE `module` = 'bx_persons';
-DELETE FROM `sys_menu_items` WHERE `module` = 'bx_persons' OR `set_name` = 'bx_persons_view';
+DELETE FROM `sys_menu_items` WHERE `module` = 'bx_persons' OR `set_name` IN('bx_persons_view', 'bx_persons_view_submenu');
 
 -- ACL
 

+ 55 - 22
modules/boonex/persons/install/sql/enable.sql

@@ -16,27 +16,39 @@ INSERT INTO `sys_options` (`name`, `value`, `category_id`, `caption`, `type`, `c
 
 -- STORAGES & TRANSCODERS
 
-SET @iTotalFilesSize = (SELECT SUM(`size`) FROM `bx_persons_pictures`);
-SET @iTotalFilesNum = (SELECT COUNT(*) FROM `bx_persons_pictures`);
+SET @iTotalPicturesSize = IFNULL((SELECT SUM(`size`) FROM `bx_persons_pictures`), 0);
+SET @iTotalPicturesNum = IFNULL((SELECT COUNT(*) FROM `bx_persons_pictures`), 0);
+
+SET @iTotalPicturesCoversSize = IFNULL((SELECT SUM(`size`) FROM `bx_persons_pictures_covers`), 0);
+SET @iTotalPicturesCoversNum = IFNULL((SELECT COUNT(*) FROM `bx_persons_pictures_covers`), 0);
+
+SET @iTotalPicturesResizedSize = IFNULL((SELECT SUM(`size`) FROM `bx_persons_pictures_resized`), 0);
+SET @iTotalPicturesResizedNum = IFNULL((SELECT COUNT(*) FROM `bx_persons_pictures_resized`), 0);
 
 INSERT INTO `sys_objects_storage` (`object`, `engine`, `params`, `token_life`, `cache_control`, `levels`, `table_files`, `ext_mode`, `ext_allow`, `ext_deny`, `quota_size`, `current_size`, `quota_number`, `current_number`, `max_file_size`, `ts`) VALUES
-('bx_persons_pictures', 'Local', '', 360, 2592000, 3, 'bx_persons_pictures', 'allow-deny', 'jpg,jpeg,jpe,gif,png', '', 0, @iTotalFilesSize, 0, @iTotalFilesNum, 0, 0),
-('bx_persons_pictures_resized', 'Local', '', 360, 2592000, 3, 'bx_persons_pictures_resized', 'allow-deny', 'jpg,jpeg,jpe,gif,png', '', 0, @iTotalFilesSize, 0, @iTotalFilesNum, 0, 0);
+('bx_persons_pictures', 'Local', '', 360, 2592000, 3, 'bx_persons_pictures', 'allow-deny', 'jpg,jpeg,jpe,gif,png', '', 0, @iTotalPicturesSize, 0, @iTotalPicturesNum, 0, 0),
+('bx_persons_pictures_covers', 'Local', '', 360, 2592000, 3, 'bx_persons_pictures_covers', 'allow-deny', 'jpg,jpeg,jpe,gif,png', '', 0, @iTotalPicturesCoversSize, 0, @iTotalPicturesCoversNum, 0, 0),
+('bx_persons_pictures_resized', 'Local', '', 360, 2592000, 3, 'bx_persons_pictures_resized', 'allow-deny', 'jpg,jpeg,jpe,gif,png', '', 0, @iTotalPicturesResizedSize, 0, @iTotalPicturesResizedNum, 0, 0);
 
 INSERT INTO `sys_objects_transcoder_images` (`object`, `storage_object`, `source_type`, `source_params`, `private`, `atime_tracking`, `atime_pruning`, `ts`) VALUES 
 ('bx_persons_icon', 'bx_persons_pictures_resized', 'Storage', 'a:1:{s:6:"object";s:19:"bx_persons_pictures";}', 'no', '1', '2592000', '0'),
 ('bx_persons_thumb', 'bx_persons_pictures_resized', 'Storage', 'a:1:{s:6:"object";s:19:"bx_persons_pictures";}', 'no', '1', '2592000', '0'),
-('bx_persons_preview', 'bx_persons_pictures_resized', 'Storage', 'a:1:{s:6:"object";s:19:"bx_persons_pictures";}', 'no', '1', '2592000', '0');
+('bx_persons_preview', 'bx_persons_pictures_resized', 'Storage', 'a:1:{s:6:"object";s:19:"bx_persons_pictures";}', 'no', '1', '2592000', '0'),
+('bx_persons_cover', 'bx_persons_pictures_resized', 'Storage', 'a:1:{s:6:"object";s:26:"bx_persons_pictures_covers";}', 'no', '1', '2592000', '0'),
+('bx_persons_cover_thumb', 'bx_persons_pictures_resized', 'Storage', 'a:1:{s:6:"object";s:26:"bx_persons_pictures_covers";}', 'no', '1', '2592000', '0');
 
 INSERT INTO `sys_transcoder_images_filters` (`transcoder_object`, `filter`, `filter_params`, `order`) VALUES 
 ('bx_persons_icon', 'Resize', 'a:4:{s:1:"w";s:2:"32";s:1:"h";s:2:"32";s:13:"square_resize";s:1:"1";s:10:"force_type";s:3:"jpg";}', '0'),
 ('bx_persons_thumb', 'Resize', 'a:4:{s:1:"w";s:2:"64";s:1:"h";s:2:"64";s:13:"square_resize";s:1:"1";s:10:"force_type";s:3:"jpg";}', '0'),
-('bx_persons_preview', 'Resize', 'a:4:{s:1:"w";s:3:"278";s:1:"h";s:3:"278";s:13:"square_resize";s:1:"1";s:10:"force_type";s:3:"jpg";}', '0');
+('bx_persons_preview', 'Resize', 'a:4:{s:1:"w";s:3:"150";s:1:"h";s:3:"150";s:13:"square_resize";s:1:"1";s:10:"force_type";s:3:"jpg";}', '0'),
+('bx_persons_cover', 'Resize', 'a:4:{s:1:"w";s:4:"1024";s:1:"h";s:4:"1024";s:13:"square_resize";s:1:"1";s:10:"force_type";s:3:"jpg";}', '0'),
+('bx_persons_cover_thumb', 'Resize', 'a:4:{s:1:"w";s:2:"64";s:1:"h";s:2:"64";s:13:"square_resize";s:1:"1";s:10:"force_type";s:3:"jpg";}', '0');
 
 -- UPLOADERS
 
 INSERT INTO `sys_objects_uploader` (`object`, `active`, `override_class_name`, `override_class_file`) VALUES
-('bx_persons_avatar', 1, 'BxPersonsAvatarUploader', 'modules/boonex/persons/classes/BxPersonsAvatarUploader.php');
+('bx_persons_avatar', 1, 'BxPersonsUploader', 'modules/boonex/persons/classes/BxPersonsUploader.php'),
+('bx_persons_cover', 1, 'BxPersonsUploader', 'modules/boonex/persons/classes/BxPersonsUploader.php');
 
 -- PAGES
 
@@ -50,37 +62,44 @@ INSERT INTO `sys_pages_blocks`(`object`, `cell_id`, `module`, `title`, `designbo
 ('bx_persons_create_profile', 1, 'bx_persons', '_bx_persons_page_block_title_create_profile', 11, 2147483647, 'service', 'a:2:{s:6:\"module\";s:10:\"bx_persons\";s:6:\"method\";s:14:\"create_profile\";}', 0, 1, 1);
 
 --
--- Dumping data for 'bx_persons_delete_profile' page
+-- Dumping data for 'bx_persons_view_profile' page
 --
 INSERT INTO `sys_objects_page`(`object`, `uri`, `title_system`, `title`, `module`, `layout_id`, `visible_for_levels`, `visible_for_levels_editable`, `url`, `meta_description`, `meta_keywords`, `meta_robots`, `cache_lifetime`, `cache_editable`, `deletable`, `override_class_name`, `override_class_file`) VALUES 
-('bx_persons_delete_profile', 'delete-persons-profile', '_bx_persons_page_title_sys_delete_profile', '_bx_persons_page_title_delete_profile', 'bx_persons', 1, 2147483647, 1, 'page.php?i=delete-persons-profile', '', '', '', 0, 1, 0, 'BxPersonsPageProfile', 'modules/boonex/persons/classes/BxPersonsPageProfile.php');
+('bx_persons_view_profile', 'view-persons-profile', '_bx_persons_page_title_sys_view_profile', '_bx_persons_page_title_view_profile', 'bx_persons', 9, 2147483647, 1, 'page.php?i=view-persons-profile', '', '', '', 0, 1, 0, 'BxPersonsPageProfile', 'modules/boonex/persons/classes/BxPersonsPageProfile.php');
 
 INSERT INTO `sys_pages_blocks`(`object`, `cell_id`, `module`, `title`, `designbox_id`, `visible_for_levels`, `type`, `content`, `deletable`, `copyable`, `order`) VALUES 
-('bx_persons_delete_profile', 2, 'bx_persons', '_bx_persons_page_block_title_delete_profile', 11, 2147483647, 'service', 'a:2:{s:6:\"module\";s:10:\"bx_persons\";s:6:\"method\";s:14:\"delete_profile\";}', 0, 1, 0),
-('bx_persons_delete_profile', 1, 'bx_persons', '_bx_persons_page_block_title_profile_picture', 3, 2147483647, 'service', 'a:2:{s:6:\"module\";s:10:\"bx_persons\";s:6:\"method\";s:15:\"profile_picture\";}', 0, 0, 1),
-('bx_persons_delete_profile', 1, 'bx_persons', '_bx_persons_page_block_title_profile_menu', 13, 2147483647, 'menu', 'bx_persons_view', 0, 0, 2);
+('bx_persons_view_profile', 3, 'bx_persons', '_bx_persons_page_block_title_profile_friends', 11, 2147483647, 'service', 'a:2:{s:6:\"module\";s:10:\"bx_persons\";s:6:\"method\";s:15:\"profile_friends\";}', 0, 0, 0),
+('bx_persons_view_profile', 1, 'bx_persons', '_bx_persons_page_block_title_profile_cover', 3, 2147483647, 'service', 'a:2:{s:6:\"module\";s:10:\"bx_persons\";s:6:\"method\";s:13:\"profile_cover\";}', 0, 0, 0),
+('bx_persons_view_profile', 2, 'bx_persons', '_bx_persons_page_block_title_profile_info', 11, 2147483647, 'service', 'a:2:{s:6:\"module\";s:10:\"bx_persons\";s:6:\"method\";s:12:\"profile_info\";}', 0, 0, 0);
 
 --
 -- Dumping data for 'bx_persons_edit_profile' page
 --
 INSERT INTO `sys_objects_page`(`object`, `uri`, `title_system`, `title`, `module`, `layout_id`, `visible_for_levels`, `visible_for_levels_editable`, `url`, `meta_description`, `meta_keywords`, `meta_robots`, `cache_lifetime`, `cache_editable`, `deletable`, `override_class_name`, `override_class_file`) VALUES 
-('bx_persons_edit_profile', 'edit-persons-profile', '_bx_persons_page_title_sys_edit_profile', '_bx_persons_page_title_edit_profile', 'bx_persons', 1, 2147483647, 1, 'page.php?i=edit-persons-profile', '', '', '', 0, 1, 0, 'BxPersonsPageProfile', 'modules/boonex/persons/classes/BxPersonsPageProfile.php');
+('bx_persons_edit_profile', 'edit-persons-profile', '_bx_persons_page_title_sys_edit_profile', '_bx_persons_page_title_edit_profile', 'bx_persons', 5, 2147483647, 1, 'page.php?i=edit-persons-profile', '', '', '', 0, 1, 0, 'BxPersonsPageProfile', 'modules/boonex/persons/classes/BxPersonsPageProfile.php');
 
 INSERT INTO `sys_pages_blocks`(`object`, `cell_id`, `module`, `title`, `designbox_id`, `visible_for_levels`, `type`, `content`, `deletable`, `copyable`, `order`) VALUES 
-('bx_persons_edit_profile', 2, 'bx_persons', '_bx_persons_page_block_title_edit_profile', 11, 2147483647, 'service', 'a:2:{s:6:\"module\";s:10:\"bx_persons\";s:6:\"method\";s:12:\"edit_profile\";}', 0, 1, 0),
-('bx_persons_edit_profile', 1, 'bx_persons', '_bx_persons_page_block_title_profile_picture', 3, 2147483647, 'service', 'a:2:{s:6:\"module\";s:10:\"bx_persons\";s:6:\"method\";s:15:\"profile_picture\";}', 0, 1, 1),
-('bx_persons_edit_profile', 1, 'bx_persons', '_bx_persons_page_block_title_profile_menu', 13, 2147483647, 'menu', 'bx_persons_view', 0, 1, 2);
+('bx_persons_edit_profile', 1, 'bx_persons', '_bx_persons_page_block_title_edit_profile', 11, 2147483647, 'service', 'a:2:{s:6:\"module\";s:10:\"bx_persons\";s:6:\"method\";s:12:\"edit_profile\";}', 0, 1, 0);
 
 --
--- Dumping data for 'bx_persons_view_profile' page
+-- Dumping data for 'bx_persons_delete_profile' page
+--
+INSERT INTO `sys_objects_page`(`object`, `uri`, `title_system`, `title`, `module`, `layout_id`, `visible_for_levels`, `visible_for_levels_editable`, `url`, `meta_description`, `meta_keywords`, `meta_robots`, `cache_lifetime`, `cache_editable`, `deletable`, `override_class_name`, `override_class_file`) VALUES 
+('bx_persons_delete_profile', 'delete-persons-profile', '_bx_persons_page_title_sys_delete_profile', '_bx_persons_page_title_delete_profile', 'bx_persons', 5, 2147483647, 1, 'page.php?i=delete-persons-profile', '', '', '', 0, 1, 0, 'BxPersonsPageProfile', 'modules/boonex/persons/classes/BxPersonsPageProfile.php');
+
+INSERT INTO `sys_pages_blocks`(`object`, `cell_id`, `module`, `title`, `designbox_id`, `visible_for_levels`, `type`, `content`, `deletable`, `copyable`, `order`) VALUES 
+('bx_persons_delete_profile', 1, 'bx_persons', '_bx_persons_page_block_title_delete_profile', 11, 2147483647, 'service', 'a:2:{s:6:\"module\";s:10:\"bx_persons\";s:6:\"method\";s:14:\"delete_profile\";}', 0, 1, 0);
+
+--
+-- Dumping data for 'bx_persons_profile_info' page
 --
 INSERT INTO `sys_objects_page`(`object`, `uri`, `title_system`, `title`, `module`, `layout_id`, `visible_for_levels`, `visible_for_levels_editable`, `url`, `meta_description`, `meta_keywords`, `meta_robots`, `cache_lifetime`, `cache_editable`, `deletable`, `override_class_name`, `override_class_file`) VALUES 
-('bx_persons_view_profile', 'view-persons-profile', '_bx_persons_page_title_sys_view_profile', '_bx_persons_page_title_view_profile', 'bx_persons', 1, 2147483647, 1, 'page.php?i=view-persons-profile', '', '', '', 0, 1, 0, 'BxPersonsPageProfile', 'modules/boonex/persons/classes/BxPersonsPageProfile.php');
+('bx_persons_profile_info', 'persons-profile-info', '_bx_persons_page_title_sys_profile_info', '_bx_persons_page_title_profile_info', 'bx_persons', 5, 2147483647, 1, 'page.php?i=persons-profile-info', '', '', '', 0, 1, 0, 'BxPersonsPageProfile', 'modules/boonex/persons/classes/BxPersonsPageProfile.php');
 
 INSERT INTO `sys_pages_blocks`(`object`, `cell_id`, `module`, `title`, `designbox_id`, `visible_for_levels`, `type`, `content`, `deletable`, `copyable`, `order`) VALUES 
-('bx_persons_view_profile', 2, 'bx_persons', '_bx_persons_page_block_title_profile_info', 11, 2147483647, 'service', 'a:2:{s:6:\"module\";s:10:\"bx_persons\";s:6:\"method\";s:12:\"profile_info\";}', 0, 0, 0),
-('bx_persons_view_profile', 1, 'bx_persons', '_bx_persons_page_block_title_profile_picture', 3, 2147483647, 'service', 'a:2:{s:6:\"module\";s:10:\"bx_persons\";s:6:\"method\";s:15:\"profile_picture\";}', 0, 0, 1),
-('bx_persons_view_profile', 1, 'bx_persons', '_bx_persons_page_block_title_profile_menu', 13, 2147483647, 'menu', 'bx_persons_view', 0, 0, 2);
+('bx_persons_profile_info', 1, 'bx_persons', '_bx_persons_page_block_title_profile_info', 11, 2147483647, 'service', 'a:2:{s:6:\"module\";s:10:\"bx_persons\";s:6:\"method\";s:12:\"profile_info\";}', 0, 0, 1);
+
+
 
 -- Homepage
 INSERT INTO `sys_pages_blocks` (`object`, `cell_id`, `module`, `title`, `designbox_id`, `visible_for_levels`, `type`, `content`, `deletable`, `copyable`, `order`) VALUES
@@ -101,7 +120,7 @@ INSERT INTO `sys_menu_items` (`set_name`, `module`, `name`, `title_system`, `tit
 -- Dumping data for 'bx_persons_view' menu
 --
 INSERT INTO `sys_objects_menu`(`object`, `title`, `set_name`, `module`, `template_id`, `deletable`, `active`, `override_class_name`, `override_class_file`) VALUES 
-('bx_persons_view', '_bx_persons_menu_title_view_person', 'bx_persons_view', 'bx_persons', 6, 0, 1, 'BxPersonsMenuViewPerson', 'modules/boonex/persons/classes/BxPersonsMenuViewPerson.php');
+('bx_persons_view', '_bx_persons_menu_title_view_person', 'bx_persons_view', 'bx_persons', 10, 0, 1, 'BxPersonsMenuViewPerson', 'modules/boonex/persons/classes/BxPersonsMenuViewPerson.php');
 
 INSERT INTO `sys_menu_sets`(`set_name`, `module`, `title`, `deletable`) VALUES 
 ('bx_persons_view', 'bx_persons', '_bx_persons_menu_set_title_view_person', 0);
@@ -111,6 +130,20 @@ INSERT INTO `sys_menu_items`(`set_name`, `module`, `name`, `title_system`, `titl
 ('bx_persons_view', 'bx_persons', 'edit-persons-profile', '_bx_persons_menu_item_title_system_edit_person', '_bx_persons_menu_item_title_edit_person', 'page.php?i=edit-persons-profile&id={content_id}', '', '', 'pencil', '', 0, 1, 0, 1),
 ('bx_persons_view', 'bx_persons', 'delete-persons-profile', '_bx_persons_menu_item_title_system_delete_person', '_bx_persons_menu_item_title_delete_person', 'page.php?i=delete-persons-profile&id={content_id}', '', '', 'remove', '', 0, 1, 0, 2);
 
+--
+-- Dumping data for 'bx_persons_view_submenu' menu
+--
+INSERT INTO `sys_objects_menu`(`object`, `title`, `set_name`, `module`, `template_id`, `deletable`, `active`, `override_class_name`, `override_class_file`) VALUES 
+('bx_persons_view_submenu', '_bx_persons_menu_title_view_person_submenu', 'bx_persons_view_submenu', 'bx_persons', 8, 0, 1, 'BxPersonsMenuViewPerson', 'modules/boonex/persons/classes/BxPersonsMenuViewPerson.php');
+
+INSERT INTO `sys_menu_sets`(`set_name`, `module`, `title`, `deletable`) VALUES 
+('bx_persons_view_submenu', 'bx_persons', '_bx_persons_menu_set_title_view_person_submenu', 0);
+
+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_persons_view_submenu', 'bx_persons', 'persons-profile-info', '_bx_persons_menu_item_title_system_view_person_info', '_bx_persons_menu_item_title_view_person_info', 'page.php?i=persons-profile-info&id={content_id}', '', '', '', '', 2147483647, 1, 0, 0);
+
+
+
 
 -- ACL
 

+ 31 - 9
modules/boonex/persons/install/sql/install.sql

@@ -7,6 +7,7 @@ CREATE TABLE IF NOT EXISTS `bx_persons_data` (
   `added` int(11) NOT NULL,
   `changed` int(11) NOT NULL,
   `picture` int(11) NOT NULL,
+  `cover` int(11) NOT NULL,
   `fullname` varchar(255) NOT NULL,
   `sex` int(11) NOT NULL,
   PRIMARY KEY (`id`)
@@ -31,6 +32,22 @@ CREATE TABLE `bx_persons_pictures` (
   UNIQUE KEY `remote_id` (`remote_id`)
 );
 
+CREATE TABLE `bx_persons_pictures_covers` (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `profile_id` int(10) unsigned NOT NULL,
+  `remote_id` varchar(255) NOT NULL,
+  `path` varchar(255) NOT NULL,
+  `file_name` varchar(255) NOT NULL,
+  `mime_type` varchar(128) NOT NULL,
+  `ext` varchar(32) NOT NULL,
+  `size` int(11) NOT NULL,
+  `added` int(11) NOT NULL,
+  `modified` int(11) NOT NULL,
+  `private` int(11) NOT NULL,
+  PRIMARY KEY (`id`),
+  UNIQUE KEY `remote_id` (`remote_id`)
+);
+
 CREATE TABLE `bx_persons_pictures_resized` (
   `id` int(11) NOT NULL AUTO_INCREMENT,
   `profile_id` int(10) unsigned NOT NULL,
@@ -63,29 +80,34 @@ INSERT INTO `sys_form_inputs`(`object`, `module`, `name`, `value`, `values`, `ch
 ('bx_person', 'bx_persons', 'do_submit', '_sys_form_account_input_submit', '', 0, 'submit', '_bx_persons_form_person_input_sys_do_submit', '', '', 0, 0, 0, '', '', '', '', '', '', '', '', 1, 0),
 ('bx_person', 'bx_persons', 'fullname', '', '', 0, 'text', '_bx_persons_form_person_input_sys_fullname', '_bx_persons_form_person_input_fullname', '', 1, 0, 0, '', '', '', 'Avail', '', '_bx_persons_form_person_input_fullname_err', 'Xss', '', 1, 0),
 ('bx_person', 'bx_persons', 'picture', '', '', 0, 'files', '_bx_persons_form_person_input_sys_picture', '_bx_persons_form_person_input_picture', '', 1, 0, 0, '', '', '', 'Avail', '', '_bx_persons_form_person_input_picture_err', 'Int', '', 1, 0),
+('bx_person', 'bx_persons', 'cover', '', '', 0, 'files', '_bx_persons_form_person_input_sys_cover', '_bx_persons_form_person_input_cover', '', 0, 0, 0, '', '', '', '', '', '', 'Int', '', 1, 0),
 ('bx_person', 'bx_persons', 'sex', 1, '#!Sex', 0, 'radio_set', '_bx_persons_form_person_input_sys_sex', '_bx_persons_form_person_input_sex', '', 1, 0, 0, '', '', '', 'Avail', '', '_bx_persons_form_person_input_sex_err', 'Xss', '', 1, 1);
 
 INSERT INTO `sys_form_display_inputs`(`display_name`, `input_name`, `visible_for_levels`, `active`, `order`) VALUES 
 ('bx_person_add', 'delete_confirm', 2147483647, 0, 1),
 ('bx_person_add', 'picture', 2147483647, 1, 2),
-('bx_person_add', 'fullname', 2147483647, 1, 3),
-('bx_person_add', 'sex', 2147483647, 1, 4),
-('bx_person_add', 'do_submit', 2147483647, 1, 5),
+('bx_person_add', 'cover', 2147483647, 1, 3),
+('bx_person_add', 'fullname', 2147483647, 1, 4),
+('bx_person_add', 'sex', 2147483647, 1, 5),
+('bx_person_add', 'do_submit', 2147483647, 1, 6),
 ('bx_person_delete', 'picture', 2147483647, 0, 0),
+('bx_person_delete', 'cover', 2147483647, 0, 0),
 ('bx_person_delete', 'delete_confirm', 2147483647, 1, 0),
 ('bx_person_delete', 'do_submit', 2147483647, 1, 1),
 ('bx_person_delete', 'fullname', 2147483647, 0, 2),
 ('bx_person_delete', 'sex', 2147483647, 0, 3),
 ('bx_person_edit', 'delete_confirm', 2147483647, 0, 1),
 ('bx_person_edit', 'picture', 2147483647, 1, 2),
-('bx_person_edit', 'fullname', 2147483647, 1, 3),
-('bx_person_edit', 'sex', 2147483647, 1, 4),
-('bx_person_edit', 'do_submit', 2147483647, 1, 5),
+('bx_person_edit', 'cover', 2147483647, 1, 3),
+('bx_person_edit', 'fullname', 2147483647, 1, 4),
+('bx_person_edit', 'sex', 2147483647, 1, 5),
+('bx_person_edit', 'do_submit', 2147483647, 1, 6),
 ('bx_person_view', 'delete_confirm', 2147483647, 0, 1),
 ('bx_person_view', 'picture', 2147483647, 0, 2),
-('bx_person_view', 'fullname', 2147483647, 1, 3),
-('bx_person_view', 'sex', 2147483647, 1, 4),
-('bx_person_view', 'do_submit', 2147483647, 0, 5);
+('bx_person_view', 'cover', 2147483647, 0, 3),
+('bx_person_view', 'fullname', 2147483647, 1, 4),
+('bx_person_view', 'sex', 2147483647, 1, 5),
+('bx_person_view', 'do_submit', 2147483647, 0, 6);
 
 -- STUDIO PAGE & WIDGET
 

+ 1 - 0
modules/boonex/persons/install/sql/uninstall.sql

@@ -8,6 +8,7 @@ DELETE FROM sys_profiles WHERE `type` = 'bx_persons';
 
 -- TODO: delete picture files as well
 DROP TABLE IF EXISTS `bx_persons_pictures`; 
+DROP TABLE IF EXISTS `bx_persons_pictures_covers`; 
 DROP TABLE IF EXISTS `bx_persons_pictures_resized`;
 
 -- FORMS

+ 11 - 11
modules/boonex/persons/js/forms.js

@@ -1,7 +1,7 @@
 
-function bx_persons_action_with_ghost (sAction, iFileId, iContentId, oUploader) {
+function bx_persons_action_with_ghost (sAction, iFileId, iContentId, oUploader, sFieldName) {
     bx_loading("bx-uploader-file-" + iFileId, true);
-    $.post(sUrlRoot + "modules/?r=persons/" + sAction + "/" + iFileId + "/" + iContentId, function(s) {
+    $.post(sUrlRoot + "modules/?r=persons/" + sAction + "/" + iFileId + "/" + iContentId + "/" + sFieldName, function(s) {
         bx_loading("bx-uploader-file-" + iFileId, false);
         if (s.length)
             alert(s);
@@ -10,21 +10,21 @@ function bx_persons_action_with_ghost (sAction, iFileId, iContentId, oUploader)
     });
 }
 
-function bx_persons_discard_ghost (iFileId, iContentId, oUploader) {
-    bx_persons_action_with_ghost ('discard_ghost', iFileId, iContentId, oUploader);
+function bx_persons_discard_ghost (iFileId, iContentId, oUploader, sFieldName) {
+    bx_persons_action_with_ghost ('discard_ghost', iFileId, iContentId, oUploader, sFieldName);
 }
 
-function bx_persons_delete_ghost (iFileId, iContentId, oUploader) {
-    bx_persons_action_with_ghost ('delete_ghost', iFileId, iContentId, oUploader);
+function bx_persons_delete_ghost (iFileId, iContentId, oUploader, sFieldName) {
+    bx_persons_action_with_ghost ('delete_ghost', iFileId, iContentId, oUploader, sFieldName);
 }
 
-function bx_persons_toggle_draft (iFileId, iCurrentFileId) {
+function bx_persons_toggle_draft (iFileId, iCurrentFileId, sFieldName) {
     if (iFileId == iCurrentFileId) {
-        $(".bx-uploader-ghost-current").show();
-        $(".bx-uploader-ghost-draft").hide();
+        $("#bx-form-element-" + sFieldName + " .bx-uploader-ghost-current").show();
+        $("#bx-form-element-" + sFieldName + " .bx-uploader-ghost-draft").hide();
     } else {
-        $(".bx-uploader-ghost-current").hide();
-        $(".bx-uploader-ghost-draft").show();
+        $("#bx-form-element-" + sFieldName + " .bx-uploader-ghost-current").hide();
+        $("#bx-form-element-" + sFieldName + " .bx-uploader-ghost-draft").show();
     }
 }
 

+ 8 - 0
modules/boonex/persons/template/cover.html

@@ -0,0 +1,8 @@
+
+<div class="bx-persons-cover bx-def-round-corners" style="background-image:url(__cover_url__)">
+    <div class="bx-persons-cover-info bx-def-padding">
+        <img class="bx-def-margin-right bx-def-round-corners" src="__preview_url__" />
+        <h1 class="bx-def-margin-sec-bottom bx-def-margin-sec-top">__title__</h1>
+    </div>
+</div>
+

+ 43 - 0
modules/boonex/persons/template/css/main.css

@@ -36,3 +36,46 @@
 .bx-persons-preview img {
     width:100%;
 }
+
+/* profile cover */
+
+.bx-persons-cover {
+    position:relative;
+    height:300px;
+
+    -moz-box-sizing: border-box;
+    -ms-box-sizing: border-box;
+    -webkit-box-sizing: border-box;
+    box-sizing: border-box;
+
+    background: url(../images/no-picture-cover.png) no-repeat center center; 
+    -webkit-background-size: cover;
+    -moz-background-size: cover;
+    -o-background-size: cover;
+    background-size: cover;
+}
+
+.bx-persons-cover-info {
+    position:absolute;
+    bottom:0;
+    left:0;
+}
+
+.bx-persons-cover-info img,
+.bx-persons-cover-info h1 {
+    display:inline-block;
+    vertical-align:bottom;
+}
+
+.bx-persons-cover-info img {
+    border:3px solid #fff;
+	-moz-box-shadow:0px 0px 0px 1px #000;
+	-webkit-box-shadow:0px 0px 0px 1px #000;
+    box-shadow:0px 0px 0px 1px #000;
+}
+
+.bx-persons-cover-info h1 {
+    padding:0;
+    color:#fff;
+    text-shadow: 0px 0px 2px #000;
+}

+ 4 - 4
modules/boonex/persons/template/form_ghost_template.html

@@ -1,17 +1,17 @@
-<div id="bx-uploader-file-{file_id}" class="bx-uploader-ghost">
+<div id="bx-uploader-file-{file_id}" class="bx-uploader-ghost bx-def-margin-sec-top">
     <input type="hidden" name="__name__" value="{file_id}" />
     <img src="{file_icon}" class="bx-def-margin-sec-right" style="vertical-align:middle;" />
     <span class="bx-uploader-ghost-draft">
         <bx_text:_bx_persons_form_person_input_picture_txt_new />
-        <a class="bx-btn bx-btn-small" style="float:none; display:inline-block;" href="javascript:void(0);" onclick="bx_persons_discard_ghost({file_id}, __content_id__, {js_instance_name});"><bx_text:_bx_persons_form_person_input_picture_txt_discard /></a>
+        <a class="bx-btn bx-btn-small" style="float:none; display:inline-block;" href="javascript:void(0);" onclick="bx_persons_discard_ghost({file_id}, __content_id__, {js_instance_name}, '__name__');"><bx_text:_bx_persons_form_person_input_picture_txt_discard /></a>
     </span>
     <span class="bx-uploader-ghost-current" style="display:none;">
         <bx_text:_bx_persons_form_person_input_picture_txt_current />
         <bx_if:not_required>
-            <a class="bx-btn bx-btn-small" style="float:none; display:inline-block;" href="javascript:void(0);" onclick="bx_persons_delete_ghost({file_id}, __content_id__, {js_instance_name});"><bx_text:_bx_persons_form_person_input_picture_txt_delete /></a>
+            <a class="bx-btn bx-btn-small" style="float:none; display:inline-block;" href="javascript:void(0);" onclick="bx_persons_delete_ghost({file_id}, __content_id__, {js_instance_name}, '__name__');"><bx_text:_bx_persons_form_person_input_picture_txt_delete /></a>
         </bx_if:not_required>
     </span>
     <script>
-        bx_persons_toggle_draft({file_id}, __current_picture_id__);
+        bx_persons_toggle_draft({file_id}, __current_picture_id__, '__name__');
     </script>
 </div>

BIN
modules/boonex/persons/template/images/no-picture-cover.jpg


+ 8 - 5
template/scripts/BxBaseMenuSubmenu.php

@@ -17,7 +17,7 @@ class BxBaseMenuSubmenu extends BxTemplMenu
 {
 
     protected $_sObjectSubmenu = false;
-    protected $_sMainMenuItemSelected = false;
+    protected $_mixedMainMenuItemSelected = false;
 
     public function __construct ($aObject, $oTemplate) 
     {
@@ -27,12 +27,12 @@ class BxBaseMenuSubmenu extends BxTemplMenu
     /**
      * Set current submenu object
      * @param $sMenuObject menu object name
-     * @param $sForceMainMenuSelection force main menu item selection by meni item name
+     * @param $sForceMainMenuSelection force main menu item selection by menu item name
      */
     public function setObjectSubmenu ($sMenuObject, $sForceMainMenuSelection = false)
     { 
         $this->_sObjectSubmenu = $sMenuObject; 
-        $this->_sMainMenuItemSelected = $sForceMainMenuSelection;
+        $this->_mixedMainMenuItemSelected = $sForceMainMenuSelection;
     }
 
     /** 
@@ -70,6 +70,9 @@ class BxBaseMenuSubmenu extends BxTemplMenu
     }
 
     protected function _getSelectedMenuItem () {
+        if (is_array($this->_mixedMainMenuItemSelected))
+            return $this->_mixedMainMenuItemSelected;
+
         $aRet = array();
         if (!isset($this->_aObject['menu_items']))
             $this->_aObject['menu_items'] = $this->_oQuery->getMenuItems();
@@ -84,8 +87,8 @@ class BxBaseMenuSubmenu extends BxTemplMenu
 
             $isSelected = false;
 
-            if ($this->_sMainMenuItemSelected)
-                $isSelected = $this->_sMainMenuItemSelected == $a['name'];
+            if ($this->_mixedMainMenuItemSelected)
+                $isSelected = $this->_mixedMainMenuItemSelected == $a['name'];
             else 
                 $isSelected = $this->_isSelected($a) || ($this->_sObjectSubmenu && $this->_sObjectSubmenu == $a['submenu_object']);