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

Merge branch 'master' of https://github.com/boonex/dolphin

AntonLV 13 лет назад
Родитель
Сommit
dd5d6026cb
47 измененных файлов с 632 добавлено и 313 удалено
  1. 28 0
      inc/classes/BxDolImageTranscoder.php
  2. 2 2
      inc/classes/BxDolRssFactory.php
  3. 4 0
      inc/classes/BxDolTemplate.php
  4. 35 0
      inc/design.inc.php
  5. 38 0
      inc/js/functions.js
  6. 0 70
      inc/utils.inc.php
  7. 1 2
      install/index.php
  8. 12 7
      install/sql/v70.sql
  9. 1 0
      modules/boonex/english/data/langs/system.xml
  10. 2 2
      modules/boonex/notes/classes/BxNotesTemplate.php
  11. 17 4
      modules/boonex/notes/install/installer.php
  12. 1 1
      modules/boonex/notes/install/sql/disable.sql
  13. 1 1
      modules/boonex/notes/install/sql/enable.sql
  14. 1 1
      modules/boonex/notes/template/unit.html
  15. 4 0
      modules/boonex/persons/classes/BxPersonsConfig.php
  16. 2 2
      modules/boonex/persons/classes/BxPersonsDb.php
  17. 114 60
      modules/boonex/persons/classes/BxPersonsFormPerson.php
  18. 4 0
      modules/boonex/persons/classes/BxPersonsMenuViewPerson.php
  19. 21 21
      modules/boonex/persons/classes/BxPersonsModule.php
  20. 25 6
      modules/boonex/persons/classes/BxPersonsPageProfile.php
  21. 43 9
      modules/boonex/persons/classes/BxPersonsTemplate.php
  22. 2 2
      modules/boonex/persons/classes/BxPersonsUploader.php
  23. 17 5
      modules/boonex/persons/install/installer.php
  24. 14 4
      modules/boonex/persons/install/langs/en.xml
  25. 8 7
      modules/boonex/persons/install/sql/disable.sql
  26. 55 22
      modules/boonex/persons/install/sql/enable.sql
  27. 31 9
      modules/boonex/persons/install/sql/install.sql
  28. 1 0
      modules/boonex/persons/install/sql/uninstall.sql
  29. 11 11
      modules/boonex/persons/js/forms.js
  30. 8 0
      modules/boonex/persons/template/cover.html
  31. 44 0
      modules/boonex/persons/template/css/main.css
  32. 4 4
      modules/boonex/persons/template/form_ghost_template.html
  33. BIN
      modules/boonex/persons/template/images/no-picture-cover.jpg
  34. 3 3
      modules/boonex/sites/classes/BxSitesAccount.php
  35. 2 2
      modules/boonex/sites/classes/BxSitesGridBrowse.php
  36. 3 3
      modules/boonex/sites/classes/BxSitesGridOverview.php
  37. 6 7
      modules/boonex/sites/install/installer.php
  38. 5 0
      plugins/moment/moment+langs.min.js
  39. 2 1
      template/_header.html
  40. 4 14
      template/comments_uploader_bs.html
  41. 2 2
      template/scripts/BxBaseFormView.php
  42. 20 0
      template/scripts/BxBaseFunctions.php
  43. 8 5
      template/scripts/BxBaseMenuSubmenu.php
  44. 2 12
      template/uploader_button_html5.html
  45. 11 0
      template/uploader_button_html5_js.html
  46. 2 12
      template/uploader_button_simple.html
  47. 11 0
      template/uploader_button_simple_js.html

+ 28 - 0
inc/classes/BxDolImageTranscoder.php

@@ -147,6 +147,24 @@ class BxDolImageTranscoder extends BxDol implements iBxDolFactoryObject {
         return $iCount;
     }
 
+    /**
+     * Register handlers array
+     * It can be called upon module enable event.
+     * @param $mixed array of transcoders objects, or just one object 
+     */
+    static public function registerHandlersArray ($mixed) {
+        self::_registerHandlersArray ($mixed, 'registerHandlers');
+    }
+
+    /**
+     * Unregister handlers array
+     * It can be called upon module disbale event.
+     * @param $mixed array of transcoders objects, or just one object 
+     */
+    static public function unregisterHandlersArray ($mixed) {
+        self::_registerHandlersArray ($mixed, 'unregisterHandlers');
+    }
+
     /**
      * Called automatically, upon local(transcoded) file deletetion.
      */
@@ -554,6 +572,16 @@ class BxDolImageTranscoder extends BxDol implements iBxDolFactoryObject {
         $oCacheDb = $this->_oDb->getDbCacheObject();
         return $oCacheDb->removeAllByPrefix('db_');
     }
+
+    static protected function _registerHandlersArray ($mixed, $sFunc) {
+        if (!is_array($mixed))
+            $mixed = array($mixed);
+        foreach ($mixed as $sObject) {
+            $oTranscoder = self::getObjectInstance($sObject);
+            if ($oTranscoder)
+                $oTranscoder->$sFunc();
+        }
+    }
 }
 
 /** @} */

+ 2 - 2
inc/classes/BxDolRssFactory.php

@@ -54,7 +54,7 @@ class BxDolRssFactory extends BxDol {
         $sUnits = '';
         $sRSSLast = '';
         if (isset($aRssData[0]))
-            $sRSSLast = getLocaleDate($aRssData[0][$aFields['DateTimeUTS']], 6);
+            $sRSSLast = bx_time_utc($aRssData[0][$aFields['DateTimeUTS']]);
 
         if ($iPID > 0)
             $aPIDOwnerInfo = getProfileInfo($iPID);
@@ -67,7 +67,7 @@ class BxDolRssFactory extends BxDol {
                 $sUnitGuid = $aUnitInfo[$aFields['Guid']];
 
                 $sUnitTitle = strmaxwordlen(strip_tags($aUnitInfo[$aFields['Title']]), 100);
-                $sUnitDate = getLocaleDate($aUnitInfo[$aFields['DateTimeUTS']], 6);
+                $sUnitDate = bx_time_utc($aUnitInfo[$aFields['DateTimeUTS']]);
 
                 $sLinkMore = '';
                 if ( strlen( $aUnitInfo[$aFields['Desc']]) > $iUnitLimitChars ) {

+ 4 - 0
inc/classes/BxDolTemplate.php

@@ -315,6 +315,7 @@ class BxDolTemplate extends BxDol implements iBxDolSingleton {
             'jquery.dolPopup.js',
             'jquery.ui.position.min.js',
             BX_DOL_URL_PLUGINS . 'spin.min.js',
+            BX_DOL_URL_PLUGINS . 'moment/moment+langs.min.js',
         ));
 
         //--- Load injection's cache ---//
@@ -906,6 +907,9 @@ class BxDolTemplate extends BxDol implements iBxDolSingleton {
                 if(!empty($this->aPage['width']))
                     $sRet = bx_html_attribute($this->aPage['width']);
                 break;
+            case 'lang':
+                $sRet = bx_lang_name();
+                break;
             case 'main_logo':
                 bx_import('BxTemplFunctions');
                 $sRet = BxTemplFunctions::getInstance()->getMainLogo();

+ 35 - 0
inc/design.inc.php

@@ -49,6 +49,12 @@ define('BX_DB_PADDING_DEF', 11);
  */
 define('BX_DB_PADDING_NO_CAPTION', 13);
 
+
+define('BX_FORMAT_DATE', 'sys_format_date'); ///< date format identifier for use in @see bx_time_js function
+define('BX_FORMAT_TIME', 'sys_format_time'); ///< time format identifier for use in @see bx_time_js function
+define('BX_FORMAT_DATE_TIME', 'sys_format_datetime'); ///< datetime format identifier for use in @see bx_time_js function
+
+
 /**
  * Display "design box" HTML code
  *
@@ -307,6 +313,35 @@ function getMemberLoginFormCode($sID = 'member_login_form', $sParams = '')
     trigger_error ("Replace getMemberLoginFormCode with BxDolService::call('system', 'login_form', array(), 'TemplServiceLogin')", E_USER_ERROR);
 }
 
+/**
+ * Output time wrapped in <time> tag in HTML.
+ * Then time is autoformatted using JS upon page load, this is aumatically converted to user's timezone and
+ * updated in realtime in case of short periods of 'from now' time format.
+ *
+ * This is just short version for:
+ * @see BxTemplFunctions::timeForJs
+ * 
+ * @param $iUnixTimestamp time as unixtimestamp
+ * @param $sFormatIdentifier output format identifier
+ *     @see BX_FORMAT_DATE
+ *     @see BX_FORMAT_TIME
+ *     @see BX_FORMAT_DATE_TIME
+ * @param $bForceFormat force provided format and don't use "from now" time autoformat.
+ */
+function bx_time_js ($iUnixTimestamp, $sFormatIdentifier = BX_FORMAT_DATE, $bForceFormat = false) {
+    bx_import('BxTemplFunctions');
+    return BxTemplFunctions::getInstance()->timeForJs ($iUnixTimestamp, $sFormatIdentifier, $bForceFormat);
+}
+
+/**
+ * Get UTC/GMT time string in ISO8601 date format from provided unix timestamp
+ * @param $iUnixTimestamp - unix timestamp
+ * @return ISO8601 formatted date/time string
+ */
+function bx_time_utc ($iUnixTimestamp) {
+    return gmdate(DATE_ISO8601, $iUnixTimestamp);
+}
+
 bx_import('BxDolAlerts');
 $oZ = new BxDolAlerts('system', 'design_included', 0);
 $oZ->alert();

+ 38 - 0
inc/js/functions.js

@@ -287,3 +287,41 @@ function validateLoginForm(eForm) {
     return false;
 }
 
+/**
+ * convert <time> tags to human readable format
+ * @param sLang - use sLang localization
+ * @param isAutoupdate - for internal usage only
+ */
+function bx_time(sLang, isAutoupdate) {
+    var iAutoupdate = 22*60*60; // autoupdate time in realtime if less than 22 hours
+    var sSel = 'time';
+
+    if ('undefined' != typeof(isAutoupdate) && isAutoupdate)
+        sSel += '.bx-time-autoupdate';
+
+    $(sSel).each(function () {
+        var s;
+        var sTime = $(this).attr('datetime');
+        var iSecondsDiff = moment(sTime).unix() - moment().unix();
+        if (iSecondsDiff < 0)
+            iSecondsDiff = -iSecondsDiff;
+
+        if (iSecondsDiff < $(this).attr('data-bx-autoformat'))
+            s = moment(sTime).lang(sLang).fromNow(); // 'time ago' format
+        else
+            s = moment(sTime).lang(sLang).format($(this).attr('data-bx-format')); // custom format
+
+        if (iSecondsDiff < iAutoupdate)
+            $(this).addClass('bx-time-autoupdate');
+        else
+            $(this).removeClass('bx-time-autoupdate');
+
+        $(this).html(s);
+    });
+
+    if ($('time.bx-time-autoupdate').size()) {
+        setTimeout(function () {
+            bx_time(sLang, true);
+        }, 30000);
+    }
+}

+ 0 - 70
inc/utils.inc.php

@@ -7,13 +7,6 @@
  * @{
  */
 
-define('BX_DOL_LOCALE_TIME', 2);
-define('BX_DOL_LOCALE_DATE_SHORT', 4);
-define('BX_DOL_LOCALE_DATE', 5);
-
-define('BX_DOL_LOCALE_PHP', 1);
-define('BX_DOL_LOCALE_DB', 2);
-
 define('BX_DATA_TEXT', 1); ///< regular text data type
 define('BX_DATA_TEXT_MULTILINE', 2); ///< regular multiline text data type
 define('BX_DATA_INT', 3); ///< integer data type
@@ -56,54 +49,6 @@ function uri2title($sValue) {
     );
 }
 
-/**
- * Convert date(timestamp) in accordance with requested format code.
- *
- * @param string $sTimestamp - timestamp
- * @param integer $iCode - format code
- *                  1(4) - short date format. @see sys_options -> short_date_format_php
- *                  2 - time format. @see sys_options -> time_format_php
- *                  3(5) - long date format. @see sys_options -> date_format_php
- *                  6 - RFC 2822 date format.
- */
-function getLocaleDate($sTimestamp = '', $iCode = BX_DOL_LOCALE_DATE_SHORT) {
-    $sFormat = (int)$iCode == 6 ? 'r' : getLocaleFormat($iCode);
-
-    return date($sFormat, $sTimestamp);
-}
-/**
- * Get data format in accordance with requested format code and format type.
- *
- * @param integer $iCode - format code
- *                  1(4) - short date format. @see sys_options -> short_date_format_php
- *                  2 - time format. @see sys_options -> time_format_php
- *                  3(5) - long date format. @see sys_options -> date_format_php
- *                  6 - RFC 2822 date format.
- * @param integer $iType - format type
- *                  1 - for PHP code.
- *                  2 - for database.
- */
-function getLocaleFormat($iCode = BX_DOL_LOCALE_DATE_SHORT, $iType = BX_DOL_LOCALE_PHP) {
-    $sPostfix = (int)$iType == BX_DOL_LOCALE_PHP ? '_php' : '';
-
-    $sResult = '';
-    switch ($iCode) {
-        case 2:
-            $sResult = getParam('time_format' . $sPostfix);
-            break;
-        case 1:
-        case 4:
-            $sResult = getParam('short_date_format' . $sPostfix);
-            break;
-        case 3:
-        case 5:
-            $sResult = getParam('date_format' . $sPostfix);
-            break;
-    }
-
-    return $sResult;
-}
-
 /*
  * functions for limiting maximal word length
  */
@@ -661,21 +606,6 @@ function _format_when ($iSec) {
     return $s;
 }
 
-function _format_time($iSec, $aParams = array()) {
-    $sDivider = isset($aParams['divider']) ? $aParams['divider'] : ':';
-
-    $iSec = (int)$iSec;
-    $sFormat = $iSec > 3600 ? 'H' . $sDivider . 'i' . $sDivider . 's' : 'i' . $sDivider . 's';
-
-    return gmdate($sFormat, $iSec);
-}
-
-function defineTimeInterval($iTime) {
-    $iTime = time() - (int)$iTime;
-    $sCode = _format_when($iTime);
-    return $sCode;
-}
-
 function execSqlFile($sFileName) {
     if (! $f = fopen($sFileName, "r"))
         return false;

+ 1 - 2
install/index.php

@@ -1209,8 +1209,7 @@ function genMainDolphinPage() {
     );
 
     bx_import('BxDolImageTranscoder');
-    foreach($aTranscoders as $sTranscoder)
-        BxDolImageTranscoder::getObjectInstance($sTranscoder)->registerHandlers();
+    BxDolImageTranscoder::registerHandlersArray($aTranscoders);
 
     /**
      * Perform admin login. 

+ 12 - 7
install/sql/v70.sql

@@ -362,15 +362,8 @@ SET @iCategoryId = LAST_INSERT_ID();
 INSERT INTO `sys_options`(`category_id`, `name`, `caption`, `value`, `type`, `extra`, `check`, `check_error`, `order`) VALUES
 (@iCategoryId, 'currency_code', 'Currency code (for checkout system)', 'USD', 'select', 'USD,EURO', 'return strlen($arg0) > 0;', 'Cannot be empty.', 1),
 (@iCategoryId, 'currency_sign', 'Currency sign (for display purposes only)', '&#36;', 'digit', '', 'return strlen($arg0) > 0;', 'Cannot be empty.', 2),
-(@iCategoryId, 'time_format_php', 'Time Format(for code)', 'H:i', 'digit', '', '', '', 3),
-(@iCategoryId, 'short_date_format_php', 'Short Date Format(for code)', 'd.m.Y', 'digit', '', '', '', 4),
-(@iCategoryId, 'date_format_php', 'Long Date Format(for code)', 'd.m.Y H:i', 'digit', '', '', '', 5),
-(@iCategoryId, 'time_format', 'Time Format(for database)', '%H:%i', 'digit', '', '', '', 6),
-(@iCategoryId, 'short_date_format', 'Short Date Format(for database)', '%d.%m.%Y', 'digit', '', '', '', 7),
-(@iCategoryId, 'date_format', 'Long Date Format(for database)', '%d.%m.%Y %H:%i', 'digit', '', '', '', 8),
 (@iCategoryId, 'enable_gd', 'Use GD library for image processing', 'on', 'checkbox', '', '', '', 10),
 (@iCategoryId, 'sys_calendar_starts_sunday', 'Does Calender start on Sunday?', '', 'checkbox', '', '', '', 11),
-(@iCategoryId, 'php_date_format', 'PHP date format', 'F j, Y', 'digit', '', '', '', 12),
 (@iCategoryId, 'license_code', 'Dolphin License Code', '', 'digit', '', '', '', 13),
 (@iCategoryId, 'boonexAffID', 'My BoonEx Affiliate ID', '', 'digit', '', '', '', 14),
 (@iCategoryId, 'useLikeOperator', 'Use operator LIKE for search (recommended for small content)', 'on', 'checkbox', '', '', '', 15);
@@ -466,6 +459,18 @@ INSERT INTO `sys_options`(`category_id`, `name`, `caption`, `value`, `type`, `ex
 (@iCategoryId, 'sys_template_page_width_min', 'Min page width(in pixels)', '774', 'digit', '', '', '', 9),
 (@iCategoryId, 'sys_template_page_width_max', 'Max page width(in pixels)', '1600', 'digit', '', '', '', 10);
 
+--
+-- CATEGORY: date/time format
+--
+INSERT INTO `sys_options_categories`(`type_id`, `name`, `caption`, `hidden`, `order`) VALUES (@iTypeId, 'date_time_format', '_adm_stg_cpt_category_datetime_format', 0, 25);
+SET @iCategoryId = LAST_INSERT_ID();
+
+INSERT INTO `sys_options`(`category_id`, `name`, `caption`, `value`, `type`, `extra`, `check`, `check_error`, `order`) VALUES
+(@iCategoryId, 'sys_format_date', 'Date Format', 'D MMM YYYY', 'digit', '', '', '', 10),
+(@iCategoryId, 'sys_format_time', 'Time Format', 'HH:mm', 'digit', '', '', '', 12),
+(@iCategoryId, 'sys_format_datetime', 'Datetime Format', 'D MMM YYYY h:mm:ss a', 'digit', '', '', '', 14),
+(@iCategoryId, 'sys_format_timeago', 'Use \'time ago\' format for dates less than this number of seconds', 432000, 'digit', '', '', '', 20);
+
 -- --------------------------------------------------------
 
 --

+ 1 - 0
modules/boonex/english/data/langs/system.xml

@@ -1611,6 +1611,7 @@ Please click "Continue" below to navigate to the home page of the site.]]></stri
 	<string name="_adm_stg_cpt_category_categories"><![CDATA[Categories]]></string>
 	<string name="_adm_stg_cpt_category_storage"><![CDATA[Storage]]></string>
 	<string name="_adm_stg_cpt_category_languages"><![CDATA[Languages]]></string>
+	<string name="_adm_stg_cpt_category_datetime_format"><![CDATA[Date/time format]]></string>
 	<string name="_adm_stg_err_save"><![CDATA[Cannot save settings]]></string>
 	<string name="_adm_stg_scs_save"><![CDATA[Settings were successfully saved]]></string>
 

+ 2 - 2
modules/boonex/notes/classes/BxNotesTemplate.php

@@ -66,7 +66,7 @@ class BxNotesTemplate extends BxDolModuleTemplate {
             'summary' => $sSummary,
             'author' => $oProfile->getDisplayName(),
             'author_url' => $oProfile->getUrl(),
-            'when' => defineTimeInterval($aData['added']),
+            'entry_posting_date' => bx_time_js($aData['added'], BX_FORMAT_DATE),
             'bx_if:thumb' => array (
                 'condition' => $sPhotoThumb,
                 'content' => array (
@@ -93,7 +93,7 @@ class BxNotesTemplate extends BxDolModuleTemplate {
             'author_url' => $oProfile->getUrl(),
             'author_thumb_url' => $oProfile->getThumb(),
             'author_title' => $oProfile->getDisplayName(),
-            'entry_posting_date' => defineTimeInterval($aData['added']),
+            'entry_posting_date' =>  bx_time_js($aData['added'], BX_FORMAT_DATE),
         );
         return $this->parseHtmlByName($sTemplateName, $aVars);
     }

+ 17 - 4
modules/boonex/notes/install/installer.php

@@ -10,9 +10,12 @@
  */
 
 bx_import('BxDolStudioInstaller');
+bx_import('BxDolImageTranscoder');
 
 class BxNotesInstaller extends BxDolStudioInstaller {
 
+    protected $_aTranscoders = array ('bx_notes_preview');
+
     function __construct($aConfig) {
         parent::__construct($aConfig);
     }
@@ -20,10 +23,20 @@ class BxNotesInstaller extends BxDolStudioInstaller {
     function enable($aParams) {
         $aResult = parent::enable($aParams);
 
-        bx_import('BxDolImageTranscoder');
-        $oTranscoder = BxDolImageTranscoder::getObjectInstance('bx_notes_preview');
-        if ($oTranscoder)
-            $oTranscoder->registerHandlers();
+        if ($aResult['result']) // register it only in case of successful enable
+            BxDolImageTranscoder::registerHandlersArray($this->_aTranscoders);
+
+        return $aResult;
+    }
+
+    function disable($aParams) {
+        
+        BxDolImageTranscoder::unregisterHandlersArray($this->_aTranscoders);
+
+        $aResult = parent::disable($aParams);
+
+        if (!$aResult['result']) // we need to register it back if disable failed
+            BxDolImageTranscoder::registerHandlersArray($this->_aTranscoders);
 
         return $aResult;
     }

+ 1 - 1
modules/boonex/notes/install/sql/disable.sql

@@ -34,4 +34,4 @@ DELETE `sys_acl_actions`, `sys_acl_matrix` FROM `sys_acl_actions`, `sys_acl_matr
 DELETE FROM `sys_acl_actions` WHERE `Module` = 'bx_notes';
 
 -- COMMENTS
-DELETE FROM `sys_objects_cmts` WHERE `ObjectName`='bx_notes';
+DELETE FROM `sys_objects_cmts` WHERE `Name`='bx_notes';

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

@@ -220,5 +220,5 @@ INSERT INTO `sys_acl_matrix` (`IDLevel`, `IDAction`) VALUES
 
 -- COMMENTS
 
-INSERT INTO `sys_objects_cmts` (`ObjectName`, `TableCmts`, `TableTrack`, `CharsPostMin`, `CharsPostMax`, `CharsDisplayMax`, `Nl2br`, `PerView`, `PerViewReplies`, `BrowseType`, `IsBrowseSwitch`, `PostFormPosition`, `NumberOfLevels`, `IsDisplaySwitch`, `IsRatable`, `ViewingThreshold`, `IsOn`, `RootStylePrefix`, `BaseUrl`, `TriggerTable`, `TriggerFieldId`, `TriggerFieldTitle`, `TriggerFieldComments`, `ClassName`, `ClassFile`) VALUES
+INSERT INTO `sys_objects_cmts` (`Name`, `TableCmts`, `TableTrack`, `CharsPostMin`, `CharsPostMax`, `CharsDisplayMax`, `Nl2br`, `PerView`, `PerViewReplies`, `BrowseType`, `IsBrowseSwitch`, `PostFormPosition`, `NumberOfLevels`, `IsDisplaySwitch`, `IsRatable`, `ViewingThreshold`, `IsOn`, `RootStylePrefix`, `BaseUrl`, `TriggerTable`, `TriggerFieldId`, `TriggerFieldTitle`, `TriggerFieldComments`, `ClassName`, `ClassFile`) VALUES
 ('bx_notes', 'bx_notes_cmts', 'bx_notes_cmts_track', 1, 5000, 1000, 1, 5, 3, 'tail', 1, 'bottom', 1, 1, 1, -3, 1, 'cmt', 'page/view-note&id={object_id}', 'bx_notes_posts', 'id', 'title', 'comments', '', '');

+ 1 - 1
modules/boonex/notes/template/unit.html

@@ -10,6 +10,6 @@
         __summary__
     </div>
     <div class="bx-clear"></div>
-    <div class="bx-notes-unit-info bx-def-margin-sec-top"><a href="__author_url__">__author__</a> <span class="bx-notes-unit-info-div bx-def-font-grayed">&#183;</span> __when__</div>
+    <div class="bx-notes-unit-info bx-def-margin-sec-top"><a href="__author_url__">__author__</a> <span class="bx-notes-unit-info-div bx-def-font-grayed">&#183;</span> __entry_posting_date__</div>
 </div>
 

+ 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;
 

+ 17 - 5
modules/boonex/persons/install/installer.php

@@ -10,9 +10,12 @@
  */
 
 bx_import('BxDolStudioInstaller');
+bx_import('BxDolImageTranscoder');
 
 class BxPersonsInstaller extends BxDolStudioInstaller {
 
+    protected $_aTranscoders = array ('bx_persons_thumb', 'bx_persons_preview');
+
     function __construct($aConfig) {
         parent::__construct($aConfig);
     }
@@ -20,11 +23,20 @@ class BxPersonsInstaller extends BxDolStudioInstaller {
     function enable($aParams) {
         $aResult = parent::enable($aParams);
 
-        bx_import('BxDolImageTranscoder');
-        $oTranscoder = BxDolImageTranscoder::getObjectInstance('bx_persons_thumb');
-        $oTranscoder->registerHandlers();
-        $oTranscoder = BxDolImageTranscoder::getObjectInstance('bx_persons_preview');
-        $oTranscoder->registerHandlers();
+        if ($aResult['result']) // register it only in case of successful enable
+            BxDolImageTranscoder::registerHandlersArray($this->_aTranscoders);
+
+        return $aResult;
+    }
+
+    function disable($aParams) {
+
+        BxDolImageTranscoder::unregisterHandlersArray($this->_aTranscoders);
+
+        $aResult = parent::disable($aParams);
+
+        if (!$aResult['result']) // we need to register it back if disable failed
+            BxDolImageTranscoder::registerHandlersArray($this->_aTranscoders);
 
         return $aResult;
     }

+ 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>
+

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

@@ -36,3 +36,47 @@
 .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;
+    background-color: #333;
+}
+
+.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


+ 3 - 3
modules/boonex/sites/classes/BxSitesAccount.php

@@ -91,7 +91,7 @@ class BxSitesAccount
 					'Domain' => $this->_oModule->getDomain($aAccount['domain']),
 					'Email' => $aUpdateParams['email'],
 					'Status' => _t('_bx_sites_txt_status_' . BX_SITES_ACCOUNT_STATUS_TRIAL),
-					'NextPaymentDate' => getLocaleDate($aUpdateParams['paid']),
+					'NextPaymentDate' => bx_time_js($aUpdateParams['paid']),
 					'DetailsFormUrl' => BX_DOL_URL_ROOT . $oPermalinks->permalink('page.php?i=site-edit&sid=' . $aAccount['pd_profile_sid'])
 				));
 
@@ -203,7 +203,7 @@ class BxSitesAccount
 					'Email' => $aAccount['email'],
 					'Amount' => $fAmount . ' ' . $this->_oModule->_oConfig->getCurrencyCode(),
 					'Status' => _t('_bx_sites_txt_status_' . $sActStatus),
-					'NextPaymentDate' => getLocaleDate($iPaidUntil),
+					'NextPaymentDate' => bx_time_js($iPaidUntil),
 					'DetailsFormUrl' => BX_DOL_URL_ROOT . $oPermalinks->permalink('page.php?i=site-edit&sid=' . $aAccount['pd_profile_sid'])
 				));
 			}
@@ -213,7 +213,7 @@ class BxSitesAccount
 				$aTemplate = BxDolEmailTemplates::getInstance()->parseTemplate('bx_sites_payment_received',  array(
 					'RealName' => $sFirstName . (!empty($sFirstName) && !empty($sLastName) ? ' ' . $sLastName : ''),
 					'Amount' => $fAmount . ' ' . $this->_oModule->_oConfig->getCurrencyCode(),
-					'NextPaymentDate' => getLocaleDate($iPaidUntil)
+					'NextPaymentDate' => bx_time_js($iPaidUntil)
 				));
 			}
 

+ 2 - 2
modules/boonex/sites/classes/BxSitesGridBrowse.php

@@ -125,7 +125,7 @@ class BxSitesGridBrowse extends BxTemplGrid {
     }
 
 	protected function _getCellCreated ($mixedValue, $sKey, $aField, $aRow) {
-        $mixedValue = _format_when(mktime() - (int)$mixedValue);
+        $mixedValue = bx_time_js((int)$mixedValue);
         return parent::_getCellDefault ($mixedValue, $sKey, $aField, $aRow);
     }
 
@@ -148,4 +148,4 @@ class BxSitesGridBrowse extends BxTemplGrid {
         return parent::_getDataSql($sFilter, $sOrderField, $sOrderDir, $iStart, $iPerPage);
     }
 }
-/** @} */
+/** @} */

+ 3 - 3
modules/boonex/sites/classes/BxSitesGridOverview.php

@@ -292,7 +292,7 @@ class BxSitesGridOverview extends BxTemplGrid {
     			'title' => '_bx_sites_grid_overview_txt_payment_last',
     			'type' => '_bx_sites_txt_payment_type_' . $aPayment['type'],
     			'transaction' => $aPayment['transaction'], 
-    			'when' => getLocaleDate($aPayment['when']),
+    			'when' => bx_time_js($aPayment['when']),
     			'amount' => number_format($aPayment['amount'], 2) . ' ' .$sCurrency
     		);
 
@@ -317,7 +317,7 @@ class BxSitesGridOverview extends BxTemplGrid {
 	    		'title' => '_bx_sites_grid_overview_txt_payment_next',
 	    		'type' => '',
 	    		'transaction' => '', 
-	    		'when' => getLocaleDate($iNextPayment),
+	    		'when' => bx_time_js($iNextPayment),
 	    		'amount' => number_format($aAmount, 2) . ' ' .$sCurrency
 	    	);
     	}
@@ -373,4 +373,4 @@ class BxSitesGridOverview extends BxTemplGrid {
 		return '';
     }
 }
-/** @} */
+/** @} */

+ 6 - 7
modules/boonex/sites/install/installer.php

@@ -3,7 +3,7 @@
  * Copyright (c) BoonEx Pty Limited - http://www.boonex.com/
  * CC-BY License - http://creativecommons.org/licenses/by/3.0/
  * 
- * @defgroup    Notes Notes
+ * @defgroup    Sites Sites
  * @ingroup     DolphinModules
  *
  * @{
@@ -18,14 +18,13 @@ class BxSitesInstaller extends BxDolStudioInstaller {
     }
 
     function enable($aParams) {
-        $aResult = parent::enable($aParams);
 
-        bx_import('BxDolImageTranscoder');
-        $oTranscoder = BxDolImageTranscoder::getObjectInstance('bx_notes_preview');
-        if ($oTranscoder)
-            $oTranscoder->registerHandlers();
+        return parent::enable($aParams);
+    }
+
+    function disable($aParams) {
 
-        return $aResult;
+        return parent::disable($aParams);
     }
 
     function install($aParams) {

Разница между файлами не показана из-за своего большого размера
+ 5 - 0
plugins/moment/moment+langs.min.js


+ 2 - 1
template/_header.html

@@ -1,5 +1,5 @@
 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US" lang="en-US">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="__lang__" lang="__lang__">
 <head>
     <meta http-equiv="Content-Type" content="text/html; charset=__page_charset__" />
     <meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0" />
@@ -63,6 +63,7 @@
         }); 
 
         $(document).ready(function () {
+            bx_time('__lang__');
             $('#bx-toolbar').css({opacity: 1});
         });
 

+ 4 - 14
template/comments_uploader_bs.html

@@ -1,14 +1,4 @@
-    <a href="javascript:void(0);" onclick="__uploader_instance_name__.showUploaderForm();" class="bx-btn bx-btn-small bx-def-margin-sec-top bx-def-margin-sec-left cmts-uploader-button">
-    	<i class="sys-icon __button_title__"></i>
-    </a>
-    <script>
-        $(document).ready(function(){
-            __uploader_instance_name__ = new BxDolUploaderSimple('__engine__', '__storage_object__', '__uniq_id__', {
-                'multiple': __multiple__,
-                'content_id': '__content_id__',
-                'images_transcoder' : '__images_transcoder__',
-                'template_error_msg': '<div class="bx-uploader-msg-err">{error}</div>',
-                'template_ghost': __template_ghost__
-            });
-        });                
-    </script>
+<a href="javascript:void(0);" onclick="__uploader_instance_name__.showUploaderForm();" class="bx-btn bx-btn-small bx-def-margin-sec-top bx-def-margin-sec-left cmts-uploader-button">
+    <i class="sys-icon __button_title__"></i>
+</a>
+<bx_include_auto:uploader_button_simple_js.html />

+ 2 - 2
template/scripts/BxBaseFormView.php

@@ -325,12 +325,12 @@ EOS;
 
             case 'datepicker':
                 $iTime = bx_process_input ($aInput['value'], BX_DATA_DATE_TS, false, false);
-                $sValue = getLocaleDate($iTime);
+                $sValue = bx_time_js ($iTime, BX_FORMAT_DATE);
             break;
             case 'date_time':
             case 'datetime':
                 $iTime = bx_process_input ($aInput['value'], BX_DATA_DATETIME_TS, false, false);
-                $sValue = defineTimeInterval ($iTime);
+                $sValue = bx_time_js ($iTime, BX_FORMAT_DATE_TIME);
             break;
 
             case 'checkbox_set':

+ 20 - 0
template/scripts/BxBaseFunctions.php

@@ -654,6 +654,26 @@ EOF;
         return $sRet;
     }
 
+    /**
+     * Output time wrapped in <time> tag in HTML.
+     * Then time is autoformatted using JS upon page load, this is aumatically converted to user's timezone and
+     * updated in realtime in case of short periods of 'from now' time format.
+     *
+     * Short version of this function:
+     * @see bx_time_js
+     *
+     * @param $iUnixTimestamp time as unixtimestamp
+     * @param $sFormatIdentifier output format identifier
+     *     @see BX_FORMAT_DATE
+     *     @see BX_FORMAT_TIME
+     *     @see BX_FORMAT_DATE_TIME
+     * @param $bForceFormat force provided format and don't use "from now" time autoformat.
+     */
+    function timeForJs ($iUnixTimestamp, $sFormatIdentifier = BX_FORMAT_DATE, $bForceFormat = false) {
+        $sDateUTC = bx_time_utc ($iUnixTimestamp);
+        return '<time datetime="' . $sDateUTC . '" data-bx-format="' . getParam($sFormatIdentifier) . '" data-bx-autoformat="' . ($bForceFormat ? 0 : getParam('sys_format_timeago')) . '">' . $sDateUTC . '</time>';
+    }
+
 }
 
 /** @} */

+ 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']);
 

+ 2 - 12
template/uploader_button_html5.html

@@ -1,12 +1,2 @@
-    <a href="javascript:void(0);" onclick="__uploader_instance_name__.showUploaderForm();" class="bx-btn bx-btn-small bx-def-margin-sec-left">__button_title__</a>
-    <script>
-        $(document).ready(function(){
-            __uploader_instance_name__ = new BxDolUploaderHTML5('__engine__', '__storage_object__', '__uniq_id__', {
-                'multiple': __multiple__,
-                'content_id': '__content_id__',
-                'images_transcoder' : '__images_transcoder__',
-                'template_error_msg': '<div class="bx-uploader-msg-err">{error}</div>',            
-                'template_ghost': __template_ghost__
-            });
-        });
-    </script>
+<a href="javascript:void(0);" onclick="__uploader_instance_name__.showUploaderForm();" class="bx-btn bx-btn-small bx-def-margin-sec-left">__button_title__</a>
+<bx_include_auto:uploader_button_html5_js.html />

+ 11 - 0
template/uploader_button_html5_js.html

@@ -0,0 +1,11 @@
+<script>
+    $(document).ready(function(){
+        __uploader_instance_name__ = new BxDolUploaderHTML5('__engine__', '__storage_object__', '__uniq_id__', {
+            'multiple': __multiple__,
+            'content_id': '__content_id__',
+            'images_transcoder' : '__images_transcoder__',
+            'template_error_msg': '<div class="bx-uploader-msg-err">{error}</div>',            
+            'template_ghost': __template_ghost__
+        });
+    });
+</script>

+ 2 - 12
template/uploader_button_simple.html

@@ -1,12 +1,2 @@
-    <a href="javascript:void(0);" onclick="__uploader_instance_name__.showUploaderForm();" class="bx-btn bx-btn-small bx-def-margin-sec-left">__button_title__</a>
-    <script>
-        $(document).ready(function(){
-            __uploader_instance_name__ = new BxDolUploaderSimple('__engine__', '__storage_object__', '__uniq_id__', {
-                'multiple': __multiple__,
-                'content_id': '__content_id__',
-                'images_transcoder' : '__images_transcoder__',
-                'template_error_msg': '<div class="bx-uploader-msg-err">{error}</div>',
-                'template_ghost': __template_ghost__
-            });
-        });                
-    </script>
+<a href="javascript:void(0);" onclick="__uploader_instance_name__.showUploaderForm();" class="bx-btn bx-btn-small bx-def-margin-sec-left">__button_title__</a>
+<bx_include_auto:uploader_button_simple_js.html />

+ 11 - 0
template/uploader_button_simple_js.html

@@ -0,0 +1,11 @@
+<script>
+    $(document).ready(function(){
+        __uploader_instance_name__ = new BxDolUploaderSimple('__engine__', '__storage_object__', '__uniq_id__', {
+            'multiple': __multiple__,
+            'content_id': '__content_id__',
+            'images_transcoder' : '__images_transcoder__',
+            'template_error_msg': '<div class="bx-uploader-msg-err">{error}</div>',
+            'template_ghost': __template_ghost__
+        });
+    });                
+</script>

Некоторые файлы не были показаны из-за большого количества измененных файлов