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

#1 - Comments
1. Minor fixes and improvements.
2. Refactoring and implementation of DB forms.
3. Image uploader.

AntonLV 13 лет назад
Родитель
Сommit
38b0fb58c2

+ 183 - 231
inc/classes/BxDolCmts.php

@@ -11,6 +11,9 @@ bx_import('BxDolCmtsQuery');
 
 define('BX_OLD_CMT_VOTES', 365*86400); ///< comment votes older than this number of seconds will be deleted automatically 
 
+define('BX_CMT_ACTION_POST', 'post');
+define('BX_CMT_ACTION_EDIT', 'edit');
+
 define('BX_CMT_DISPLAY_FLAT', 'flat');
 define('BX_CMT_DISPLAY_THREADED', 'threaded');
 
@@ -127,6 +130,17 @@ define('BX_CMT_RATE_VALUE_MINUS', -1);
 class BxDolCmts extends BxDol
 {
 	protected $_oQuery = null;
+
+	protected $_sFormObject;
+	protected $_sFormDisplayPost;
+	protected $_sFormDisplayEdit;
+
+	protected $_sStorageObject;
+	protected $_sTranscoderPreview;
+
+	protected $_sTableImages;
+	protected $_sTableImages2Entries;
+
 	protected $_sViewUrl = '';
 	protected $_sBaseUrl = '';
 
@@ -135,7 +149,6 @@ class BxDolCmts extends BxDol
     protected $_iId = 0; ///< obect id to be commented
 
     protected $_aMarkers = array ();
-    protected $_aPostElements = array (); ///< comment submit form elements
 
     protected $_sDisplayType = '';
     protected $_sDpSessionKey = '';
@@ -164,12 +177,8 @@ class BxDolCmts extends BxDol
         else
             return;
 
-		$iCmtTextMin = (int)$this->_aSystem['chars_post_min'];
-		$iCmtTextMax = (int)$this->_aSystem['chars_post_max'];
-		$this->_aPostElements = array (
-            'CmtParent' => array ('reg' => '^[0-9]+$', 'msg' => _t('_bad comment parent id')),
-            'CmtText' => array ('reg' => '^.{' . $iCmtTextMin . ',' . $iCmtTextMax . '}$', 'msg' => _t('_Please enter n1-n2 characters', $iCmtTextMin, $iCmtTextMax))
-        );
+		$this->_aSystem['table_images'] = 'sys_images_cmts';
+		$this->_aSystem['table_images2entries'] = 'sys_images_cmts2entries';
 
         $this->_iDpMaxLevel = (int)$this->_aSystem['number_of_levels'];
         $this->_sDisplayType = $this->_iDpMaxLevel == 0 ? BX_CMT_DISPLAY_FLAT : BX_CMT_DISPLAY_THREADED;
@@ -189,13 +198,20 @@ class BxDolCmts extends BxDol
 		if(!empty($mixedUserDp))
 			$this->_sDisplayType = $mixedUserDp;
 
-        $this->_oQuery = new BxDolCmtsQuery($this);
-
         $this->_sViewUrl = BX_DOL_URL_ROOT . 'cmts.php';
         $this->_sBaseUrl = $this->_aSystem['base_url'];
         if(get_mb_substr($this->_sBaseUrl, 0, 4) != 'http')
         	$this->_sBaseUrl = BX_DOL_URL_ROOT . $this->_sBaseUrl;
 
+		$this->_oQuery = new BxDolCmtsQuery($this);
+
+		$this->_sFormObject = 'sys_comment';
+		$this->_sFormDisplayPost = 'sys_comment_post';
+		$this->_sFormDisplayEdit = 'sys_comment_edit';
+
+		$this->_sStorageObject = 'sys_images_cmts';
+		$this->_sTranscoderPreview = 'sys_images_cmts_preview';
+
         if ($iInit)
             $this->init($iId);
     }
@@ -206,7 +222,7 @@ class BxDolCmts extends BxDol
             $GLOBALS['bx_dol_cmts_systems'] = BxDolDb::getInstance()->fromCache('sys_objects_cmts', 'getAllWithKey', '
                 SELECT
                     `ID` as `system_id`,
-                    `ObjectName` AS `name`,
+                    `Name` AS `name`,
                     `TableCmts` AS `table_cmts`,
                     `TableTrack` AS `table_track`,
                     `CharsPostMin` AS `chars_post_min`,
@@ -293,11 +309,6 @@ class BxDolCmts extends BxDol
     	return $this->_replaceMarkers($this->_sBaseUrl);
     }
 
-	function isValidSystem ($sSystem)
-    {
-        return isset($this->_aSystems[$sSystem]);
-    }
-
     function isNl2br ()
     {
         return $this->_aSystem['nl2br'];
@@ -332,8 +343,36 @@ class BxDolCmts extends BxDol
         return $iDeletedRecords;
     }
 
-    /** comments functions
-     *********************************************/
+	/**
+     * Add replace markers.
+     * @param $a array of markers as key => value
+     * @return true on success or false on error
+     */
+    public function addMarkers ($a) {
+        if (empty($a) || !is_array($a))
+            return false;
+        $this->_aMarkers = array_merge ($this->_aMarkers, $a);
+        return true;
+    }
+
+    /** 
+     * Database functions
+     */
+	function getCommentsTableName ()
+    {
+        return $this->_oQuery->getTableName ();
+    }
+
+    function getObjectTitle ($iObjectId = 0)
+    {
+    	return $this->_oQuery->getObjectTitle ($iObjectId ? $iObjectId : $this->getId());
+    }
+
+    function getObjectCommentsCount ($iObjectId = 0)
+    {
+        return $this->_oQuery->getObjectCommentsCount ($iObjectId ? $iObjectId : $this->getId());
+    }
+
     function getCommentsArray ($iVParentId, $aOrder, $iStart = 0, $iCount = -1)
     {
         return $this->_oQuery->getComments ($this->getId(), $iVParentId, $this->_getAuthorId(), $aOrder, $iStart, $iCount);
@@ -349,47 +388,18 @@ class BxDolCmts extends BxDol
         return $this->_oQuery->deleteObjectComments ($iObjectId ? $iObjectId : $this->getId());
     }
 
-    /**
-     * delete all profiles comments in all systems, if some replies exist, set this comment to anonymous
-     */
     function onAuthorDelete ($iAuthorId)
     {
-        for ( reset($this->_aSystems) ; list ($sSystem, $aSystem) = each ($this->_aSystems) ; )
-        {
+    	foreach($this->_aSystems as $sSystem => $aSystem) {
             $oQuery = new BxDolCmtsQuery($aSystem);
-            $oQuery->deleteAuthorComments ($iAuthorId);
+            $oQuery->deleteAuthorComments($iAuthorId);
         }
         return true;
     }
 
-    function getCommentsTableName ()
-    {
-        return $this->_oQuery->getTableName ();
-    }
-
-    function getObjectTitle ($iObjectId = 0)
-    {
-    	return $this->_oQuery->getObjectTitle ($iObjectId ? $iObjectId : $this->getId());
-    }
-
-    function getObjectCommentsCount ($iObjectId = 0)
-    {
-        return $this->_oQuery->getObjectCommentsCount ($iObjectId ? $iObjectId : $this->getId());
-    }
-	/**
-     * Add replace markers.
-     * @param $a array of markers as key => value
-     * @return true on success or false on error
+    /** 
+     * Permissions functions
      */
-    public function addMarkers ($a) {
-        if (empty($a) || !is_array($a))
-            return false;
-        $this->_aMarkers = array_merge ($this->_aMarkers, $a);
-        return true;
-    }
-
-    /** permissions functions
-    *********************************************/
     function checkAction ($iAction, $isPerformAction = false)
     {
         $iId = $this->_getAuthorId();
@@ -414,9 +424,6 @@ class BxDolCmts extends BxDol
         return $this->checkActionErrorMsg(ACTION_ID_COMMENTS_VOTE);
     }
 
-    /**
-     * is post comment allowed
-     */
     function isPostReplyAllowed ($isPerformAction = false) {
         return $this->checkAction (ACTION_ID_COMMENTS_POST, $isPerformAction);
     }
@@ -426,9 +433,6 @@ class BxDolCmts extends BxDol
         return $this->checkActionErrorMsg(ACTION_ID_COMMENTS_POST);
     }
 
-    /**
-     * is edit own comment allowed
-     */
     function isEditAllowed ($isPerformAction = false)
     {
         return $this->checkAction (ACTION_ID_COMMENTS_EDIT_OWN, $isPerformAction);
@@ -439,9 +443,6 @@ class BxDolCmts extends BxDol
         return $this->checkActionErrorMsg (ACTION_ID_COMMENTS_EDIT_OWN);
     }
 
-    /**
-     * is removing own comment allowed
-     */
     function isRemoveAllowed ($isPerformAction = false)
     {
         return $this->checkAction (ACTION_ID_COMMENTS_REMOVE_OWN, $isPerformAction);
@@ -452,37 +453,20 @@ class BxDolCmts extends BxDol
         return $this->checkActionErrorMsg(ACTION_ID_COMMENTS_REMOVE_OWN);
     }
 
-    /**
-     * is edit any comment allowed
-     */
     function isEditAllowedAll ($isPerformAction = false)
     {
         return isAdmin() || $this->checkAction (ACTION_ID_COMMENTS_EDIT_ALL, $isPerformAction) ? true : false;
     }
 
-    /**
-     * is removing any comment allowed
-     */
     function isRemoveAllowedAll ($isPerformAction = false)
     {
         return isAdmin() || $this->checkAction (ACTION_ID_COMMENTS_REMOVE_ALL, $isPerformAction) ? true : false;
     }
 
     /**
-     * actions functions
+     * Actions functions
      */
-    function actionPaginateGet () {
-        if (!$this->isEnabled())
-           return '';
-
-        $iCmtStart = isset($_REQUEST['CmtStart']) ? bx_process_input($_REQUEST['CmtStart'], BX_DATA_INT) : 0;
-        $iCmtNum = isset($_REQUEST['CmtNum']) ? bx_process_input($_REQUEST['CmtNum'], BX_DATA_INT) : -1;
-        $iCmtPerPage= isset($_REQUEST['CmtPerPage']) ? bx_process_input($_REQUEST['CmtPerPage'], BX_DATA_INT) : $this->getPerView();
-
-        return $this->getPaginate($iCmtStart, $iCmtNum, $iCmtPerPage);
-    }
-
-    function actionFormGet () {
+    function actionGetFormPost () {
         if (!$this->isEnabled())
            return '';
 
@@ -490,31 +474,29 @@ class BxDolCmts extends BxDol
         $sCmtBrowse = isset($_REQUEST['CmtBrowse']) ? bx_process_input($_REQUEST['CmtBrowse'], BX_DATA_TEXT) : '';
         $sCmtDisplay = isset($_REQUEST['CmtDisplay']) ? bx_process_input($_REQUEST['CmtDisplay'], BX_DATA_TEXT) : '';
 
-        return $this->getFormBox(array('parent_id' => $iCmtParentId, 'type' => $sCmtBrowse), array('type' => $sCmtDisplay));
+        return $this->getFormBoxPost(array('parent_id' => $iCmtParentId, 'type' => $sCmtBrowse), array('type' => $sCmtDisplay));
     }
 
-	function actionPlusedByGet () {
-        if (!$this->isEnabled())
-           return '';
+	function actionGetFormEdit ()
+    {
+        if (!$this->isEnabled()){
+        	$this->_echoResultJson(array());
+        	return;
+        }
 
-        $iCmtId= isset($_REQUEST['CmtId']) ? bx_process_input($_REQUEST['CmtId'], BX_DATA_INT) : 0;
-        return $this->getPlusedBy($iCmtId);
+		$iCmtId = bx_process_input(bx_get('Cmt'), BX_DATA_INT);
+        $this->_echoResultJson($this->getFormEdit($iCmtId));
     }
 
-    function actionCmtsGet () {
+	function actionGetPlusedBy () {
         if (!$this->isEnabled())
            return '';
 
-        $iCmtVParentId = bx_process_input($_REQUEST['CmtParent'], BX_DATA_INT);
-        $iCmtStart = isset($_REQUEST['CmtStart']) ? bx_process_input($_REQUEST['CmtStart'], BX_DATA_INT) : -1;
-        $iCmtPerView = isset($_REQUEST['CmtPerView']) ? bx_process_input($_REQUEST['CmtPerView'], BX_DATA_INT) : -1;
-        $sCmtBrowse = isset($_REQUEST['CmtBrowse']) ? bx_process_input($_REQUEST['CmtBrowse'], BX_DATA_TEXT) : '';
-        $sCmtDisplay = isset($_REQUEST['CmtDisplay']) ? bx_process_input($_REQUEST['CmtDisplay'], BX_DATA_TEXT) : '';
-
-        return $this->getComments(array('vparent_id' => $iCmtVParentId, 'start' => $iCmtStart, 'per_view' => $iCmtPerView, 'type' => $sCmtBrowse), array('type' => $sCmtDisplay));
+        $iCmtId= isset($_REQUEST['CmtId']) ? bx_process_input($_REQUEST['CmtId'], BX_DATA_INT) : 0;
+        return $this->getPlusedBy($iCmtId);
     }
 
-    function actionCmtGet () {
+    function actionGetCmt () {
         if (!$this->isEnabled())
            return '';
 
@@ -523,195 +505,165 @@ class BxDolCmts extends BxDol
         $sCmtDisplay = isset($_REQUEST['CmtDisplay']) ? bx_process_input($_REQUEST['CmtDisplay'], BX_DATA_TEXT) : '';
 
         $aCmt = $this->getCommentRow($iCmtId);
-        
-        require_once( BX_DIRECTORY_PATH_PLUGINS . 'Services_JSON.php' );
-        $oJson = new Services_JSON();
-
-        return $oJson->encode(array(
+        $this->_echoResultJson(array(
         	'parent_id' => $aCmt['cmt_parent_id'],
         	'vparent_id' => $aCmt['cmt_vparent_id'],
         	'content' => $this->getComment($aCmt, array('type' => $sCmtBrowse), array('type' => $sCmtDisplay))
         ));
     }
 
-    function actionCmtPost ()
-    {
-        if(!$this->isEnabled())
-        	return '';
-
-        if(!$this->isPostReplyAllowed())
-        	return '';
-
-        $iCmtParentId = bx_process_input($_REQUEST['CmtParent'], BX_DATA_INT);
-		$iCmtAuthorId = $this->_getAuthorId();
-
-        $sCmtText = bx_process_input($_REQUEST['CmtText']);
-        if($this->_isSpam($sCmtText))
-            return sprintf(_t("_sys_spam_detected"), BX_DOL_URL_ROOT . 'contact.php');
-
-        $sText = $this->_prepareTextForSave ($sCmtText);
-
-        $iCmtNewId = $this->_oQuery->addComment ($this->getId(), $iCmtParentId, $iCmtAuthorId, $sText);
-        if(false === $iCmtNewId)
-            return '';
-
-        $this->_triggerComment();
-
-        $this->isPostReplyAllowed(true);
+    function actionGetCmts () {
+        if (!$this->isEnabled())
+           return '';
 
-        bx_import('BxDolAlerts');
-        $oZ = new BxDolAlerts($this->_sSystem, 'commentPost', $this->getId(), $iCmtAuthorId, array('comment_id' => $iCmtNewId, 'comment_author_id' => $iCmtAuthorId));
-        $oZ->alert();
+        $iCmtVParentId = bx_process_input($_REQUEST['CmtParent'], BX_DATA_INT);
+        $iCmtStart = isset($_REQUEST['CmtStart']) ? bx_process_input($_REQUEST['CmtStart'], BX_DATA_INT) : -1;
+        $iCmtPerView = isset($_REQUEST['CmtPerView']) ? bx_process_input($_REQUEST['CmtPerView'], BX_DATA_INT) : -1;
+        $sCmtBrowse = isset($_REQUEST['CmtBrowse']) ? bx_process_input($_REQUEST['CmtBrowse'], BX_DATA_TEXT) : '';
+        $sCmtDisplay = isset($_REQUEST['CmtDisplay']) ? bx_process_input($_REQUEST['CmtDisplay'], BX_DATA_TEXT) : '';
 
-        return $iCmtNewId;
+        return $this->getComments(array('vparent_id' => $iCmtVParentId, 'start' => $iCmtStart, 'per_view' => $iCmtPerView, 'type' => $sCmtBrowse), array('type' => $sCmtDisplay));
     }
 
-
-
-    /**
-     * returns error string on error, or empty string on success
-     */
-    function actionCmtRemove ()
+    function actionSubmitPostForm()
     {
-        if (!$this->isEnabled()) return '';
-
-        $iCmtId = bx_process_input($_REQUEST['Cmt'], BX_DATA_INT);
-        $aCmt = $this->_oQuery->getCommentSimple ($this->getId(), $iCmtId);
-
-        if (!$aCmt)
-            return _t('_No such comment');
-
-        if ($aCmt['cmt_replies'] > 0)
-            return _t('_Can not delete comments with replies');
-
-        $isRemoveAllowed = $this->isRemoveAllowedAll() || ($aCmt['cmt_author_id'] == $this->_getAuthorId() && $this->isRemoveAllowed());
-        if (!$isRemoveAllowed)
-            return $aCmt['cmt_author_id'] == $this->_getAuthorId() && !$this->isRemoveAllowed() ? strip_tags($this->msgErrRemoveAllowed()) : _t('_Access denied');
+        if(!$this->isEnabled() || !$this->isPostReplyAllowed()) {
+        	$this->_echoResultJson(array());
+        	return;
+        }
 
-        if (!$this->_oQuery->removeComment ($this->getId(), $aCmt['cmt_id'], $aCmt['cmt_parent_id']))
-            return _t('_Database Error');
+        $iCmtParentId = 0;
+        if(bx_get('cmt_parent_id') !== false)
+			$iCmtParentId = bx_process_input(bx_get('cmt_parent_id'), BX_DATA_INT);
 
-        $this->_triggerComment();
+		$this->_echoResultJson($this->getFormPost($iCmtParentId));
+    }
 
-        if ($aCmt['cmt_author_id'] == $this->_getAuthorId())
-           $this->isRemoveAllowed(true);
+	function actionSubmitEditForm()
+	{
+        if (!$this->isEnabled()) {
+        	$this->_echoResultJson(array());
+        	return;
+        };
 
-        bx_import('BxDolAlerts');
-        $oZ = new BxDolAlerts($this->_sSystem, 'commentRemoved', $this->getId(), $this->_getAuthorId(), array('comment_id' => $aCmt['cmt_id'], 'comment_author_id' => $aCmt['cmt_author_id']));
-        $oZ->alert();
+        $iCmtId = 0;
+        if(bx_get('cmt_id') !== false)
+			$iCmtId = bx_process_input(bx_get('cmt_id'), BX_DATA_INT);
 
-        return '';
+        $this->_echoResultJson($this->getFormEdit($iCmtId));
     }
 
-
-
-    /**
-     * returns string with "err" prefix on error, or string with html form on success
-     */
-    function actionCmtEdit ()
+    function actionRemove()
     {
-        if (!$this->isEnabled())
-        	return '';
+        if (!$this->isEnabled()) {
+        	$this->_echoResultJson(array());
+        	return;
+        };
 
-        $iCmtId = bx_process_input($_REQUEST['Cmt'], BX_DATA_INT);
+        $iCmtId = 0;
+        if(bx_get('Cmt') !== false)
+        	$iCmtId = bx_process_input(bx_get('Cmt'), BX_DATA_INT);
 
         $aCmt = $this->_oQuery->getCommentSimple ($this->getId(), $iCmtId);
-        if (!$aCmt)
-            return 'err'._t('_No such comment');
-
-        $isEditAllowed = $this->isEditAllowedAll() || ($aCmt['cmt_author_id'] == $this->_getAuthorId() && $this->isEditAllowed());
-        if(!$isEditAllowed)
-            return 'err' . ($aCmt['cmt_author_id'] == $this->_getAuthorId() && !$this->isEditAllowed() ? strip_tags($this->msgErrEditAllowed()) : _t('_Access denied'));
-
-        return $this->getForm(0, $this->_prepareTextForEdit($aCmt['cmt_text']), 'cmtUpdate(this, ' . $iCmtId . ')');
-    }
-
-    function actionCmtEditSubmit() {
+        if(!$aCmt) {
+        	$this->_echoResultJson(array('msg' => _t('_No such comment')));
+        	return;
+        }
 
-        if (!$this->isEnabled()) return '{}';
+        if ($aCmt['cmt_replies'] > 0) {
+        	$this->_echoResultJson(array('msg' => _t('_Can not delete comments with replies')));
+        	return;
+        }
 
-        require_once( BX_DIRECTORY_PATH_PLUGINS . 'Services_JSON.php' );
-        $oJson = new Services_JSON();
+        $iCmtAuthorId = $this->_getAuthorId();
+        if(!$this->isRemoveAllowedAll() && ($aCmt['cmt_author_id'] != $iCmtAuthorId || !$this->isRemoveAllowed())) {
+        	$this->_echoResultJson(array('msg' => $aCmt['cmt_author_id'] == $iCmtAuthorId && !$this->isRemoveAllowed() ? strip_tags($this->msgErrRemoveAllowed()) : _t('_Access denied')));
+        	return;
+        }
 
-        $iCmtId = bx_process_input($_REQUEST['Cmt'], BX_DATA_INT);
-        $sCmtText = bx_process_input($_REQUEST['CmtText']);
+        if($this->_oQuery->removeComment ($this->getId(), $aCmt['cmt_id'], $aCmt['cmt_parent_id'])) {
+        	$this->_triggerComment();
 
-        if ($this->_isSpam($sCmtText))
-            return $oJson->encode(array('err' => sprintf(_t("_sys_spam_detected"), BX_DOL_URL_ROOT . 'contact.php')));
+	        if($aCmt['cmt_author_id'] == $iCmtAuthorId)
+				$this->isRemoveAllowed(true);
 
-        $sText = $this->_prepareTextForSave ($sCmtText);
+	        bx_import('BxDolAlerts');
+	        $oZ = new BxDolAlerts($this->_sSystem, 'commentRemoved', $this->getId(), $iCmtAuthorId, array('comment_id' => $aCmt['cmt_id'], 'comment_author_id' => $aCmt['cmt_author_id']));
+	        $oZ->alert();
 
-        $aCmt = $this->_oQuery->getCommentSimple ($this->getId(), $iCmtId);
-        if(!$aCmt)
-            return '{}';
+	        $this->_echoResultJson(array('id' => $iCmtId));
+	        return;
+        }
 
-        $isEditAllowed = $this->isEditAllowedAll() || ($aCmt['cmt_author_id'] == $this->_getAuthorId() && $this->isEditAllowed());
-        if (!$isEditAllowed)
-            return '{}';
+        $this->_echoResultJson(array('msg' => _t('_cmt_err_cannot_perform_action')));
+    }
 
-        if ($sText != $aCmt['cmt_text'] && $this->_oQuery->updateComment ($this->getId(), $aCmt['cmt_id'], $sText)) {
-            if ($aCmt['cmt_author_id'] == $this->_getAuthorId())
-               $this->isEditAllowed(true);
+    function actionRate()
+    {
+        if (!$this->isEnabled() || !$this->isRatable()) {
+        	$this->_echoResultJson(array('msg' => _t('_Error occured')));
+        	return;
+        }
 
-            bx_import('BxDolAlerts');
-            $oZ = new BxDolAlerts($this->_sSystem, 'commentUpdated', $this->getId(), $this->_getAuthorId(), array('comment_id' => $aCmt['cmt_id'], 'comment_author_id' => $aCmt['cmt_author_id']));
-            $oZ->alert();
+        if (!$this->isRateAllowed()) {
+        	$this->_echoResultJson(array('msg' => _t('_Access denied')));
+        	return ;
         }
 
-        $aCmt = $this->_oQuery->getCommentSimple ($this->getId(), $iCmtId);
-        return $oJson->encode(array('text' => $aCmt['cmt_text']));
-    }
+        $iCmtId = 0;
+        if(bx_get('Cmt') !== false)
+        	$iCmtId = bx_process_input(bx_get('Cmt'), BX_DATA_INT);
 
-    function actionCmtRate () {
-        if (!$this->isEnabled() || !$this->isRatable()) 
-        	return _t('_Error occured');
-        if (!$this->isRateAllowed()) 
-        	return _t('_Access denied');
+		$iRate = 0;
+		if(bx_get('Rate') !== false)
+        	$iRate = bx_process_input(bx_get('Rate'), BX_DATA_INT);
 
-        $iCmtId = bx_process_input($_REQUEST['Cmt'], BX_DATA_INT);
-        $iRate = bx_process_input($_REQUEST['Rate'], BX_DATA_INT);
+		if($iCmtId == 0 || $iRate == 0) {
+			$this->_echoResultJson(array('msg' => _t('_Error occured')));
+        	return;
+		}
 
         if($iRate >= 1)
             $iRate = BX_CMT_RATE_VALUE_PLUS;
         elseif($iRate <= -1)
             $iRate = BX_CMT_RATE_VALUE_MINUS;
-        else
-            return _t('_Error occured');
 
-        if(!$this->_oQuery->rateComment($this->getSystemId(), $iCmtId, $iRate, $this->_getAuthorId(), $this->_getAuthorIp()))
-            return _t('_Duplicate vote');
+		$iCmtAuthorId = $this->_getAuthorId();
+        if($this->_oQuery->rateComment($this->getSystemId(), $iCmtId, $iRate, $iCmtAuthorId, $this->_getAuthorIp())) {
+        	$aCmt = $this->_oQuery->getCommentSimple($this->getId(), $iCmtId);
 
-        $aCmt = $this->_oQuery->getCommentSimple ($this->getId(), $iCmtId);
+	        $this->isRateAllowed(true);
 
-        $this->isRateAllowed(true);
+	        bx_import('BxDolAlerts');
+	        $oZ = new BxDolAlerts($this->_sSystem, 'commentRated', $this->getId(), $iCmtAuthorId, array('comment_id' => $iCmtId, 'comment_author_id' => $aCmt['cmt_author_id'], 'rate' => $iRate));
+	        $oZ->alert();
 
-        bx_import('BxDolAlerts');
-        $oZ = new BxDolAlerts($this->_sSystem, 'commentRated', $this->getId(), $this->_getAuthorId(), array('comment_id' => $iCmtId, 'comment_author_id' => $aCmt['cmt_author_id'], 'rate' => $iRate));
-        $oZ->alert();
+	        $this->_echoResultJson(array('id' => $iCmtId, 'rate' => $iRate));
+	        return;
+        }
 
-        return '';
+        $this->_echoResultJson(array('msg' => _t('_cmt_err_cannot_perform_action')));
     }
 
-
-    /** private functions
-    *********************************************/
-
-    function _getAuthorId ()
+    /** 
+     * Internal functions
+     */
+    protected function _getAuthorId ()
     {
         return isMember() ? bx_get_logged_profile_id() : 0;
     }
 
-    function _getAuthorPassword ()
+    protected function _getAuthorPassword ()
     {
         return isMember() ? $_COOKIE['memberPassword'] : "";
     }
 
-    function _getAuthorIp ()
+    protected function _getAuthorIp ()
     {
         return $_SERVER['REMOTE_ADDR'];
     }
 
-	function _getAuthorInfo($iAuthorId = 0)
+	protected function _getAuthorInfo($iAuthorId = 0)
     {
     	bx_import('BxDolProfile');
 		$oProfile = BxDolProfile::getInstance($iAuthorId);
@@ -728,20 +680,20 @@ class BxDolCmts extends BxDol
 		);
     }
 
-    function _prepareTextForEdit ($s)
+    protected function _prepareTextForEdit ($s)
     {
         if ($this->isNl2br())
             return str_replace('<br />', "", $s);
         return $s;
     }
 
-    function _prepareTextForSave ($s) 
+    protected function _prepareTextForSave ($s) 
     {
     	$iDataAction = $this->isNl2br() ? BX_DATA_TEXT_MULTILINE : BX_DATA_TEXT; // TODO: make sure that it is processed before output !
 		return bx_process_input($s, $iDataAction);
     }
 
-    function _prepareTextForOutput ($s)
+    protected function _prepareTextForOutput ($s)
     {
     	$iDataAction = $this->isNl2br() ? BX_DATA_TEXT_MULTILINE : BX_DATA_TEXT;
 
@@ -751,7 +703,7 @@ class BxDolCmts extends BxDol
 		return $s; 
     }
 
-	function _prepareParams(&$aBp, &$aDp)
+	protected function _prepareParams(&$aBp, &$aDp)
     {
     	$aBp['type'] = isset($aBp['type']) && !empty($aBp['type']) ? $aBp['type'] : $this->_sBrowseType;
     	$aBp['parent_id'] = isset($aBp['parent_id']) ? $aBp['parent_id'] : 0;
@@ -805,7 +757,7 @@ class BxDolCmts extends BxDol
 		$this->_setUserChoice($aBp['type'], $aDp['type']);
     }
 
-    function _triggerComment()
+    protected function _triggerComment()
     {
         if (!$this->_aSystem['trigger_table'])
             return false;
@@ -816,7 +768,7 @@ class BxDolCmts extends BxDol
         return $this->_oQuery->updateTriggerTable($iId, $iCount);
     }
 
-    function _isSpam($s) {
+    protected function _isSpam($s) {
         return bx_is_spam($s);
     }
 
@@ -840,7 +792,7 @@ class BxDolCmts extends BxDol
         return $mixed;
     }
 
-    function _getUserChoice()
+    protected function _getUserChoice()
     {
     	$mixedBp = $mixedDp = false;
     	if(!isLogged())
@@ -857,7 +809,7 @@ class BxDolCmts extends BxDol
     	return array($mixedBp, $mixedDp);
     }
 
-    function _setUserChoice($sBp, $sDp)
+    protected function _setUserChoice($sBp, $sDp)
     {
     	if(!isLogged())
     		return;

+ 22 - 45
inc/classes/BxDolCmtsQuery.php

@@ -22,6 +22,9 @@ class BxDolCmtsQuery extends BxDolDb
     protected $_sTriggerFieldTitle;
     protected $_sTriggerFieldComments;
 
+    protected $_sTableImages;
+    protected $_sTableImages2Entries;
+
     function BxDolCmtsQuery(&$oMain)
     {
     	$this->_oMain = $oMain;
@@ -34,6 +37,9 @@ class BxDolCmtsQuery extends BxDolDb
         $this->_sTriggerFieldTitle = $aSystem['trigger_field_title'];
         $this->_sTriggerFieldComments = $aSystem['trigger_field_comments'];
 
+        $this->_sTableImages = $aSystem['table_images'];
+        $this->_sTableImages2Entries = $aSystem['table_images2entries'];
+
         parent::BxDolDb();
     }
 
@@ -103,11 +109,10 @@ class BxDolCmtsQuery extends BxDolDb
                 `c`.`cmt_author_id`,
                 `c`.`cmt_level`,
                 `c`.`cmt_text`,
-                `c`.`cmt_mood`,
                 `c`.`cmt_rate`,
                 `c`.`cmt_rate_count`,
                 `c`.`cmt_replies`,
-                (? - UNIX_TIMESTAMP(`c`.`cmt_time`)) AS `cmt_secs_ago`
+                (? - `c`.`cmt_time`) AS `cmt_secs_ago`
             FROM `{$this->_sTable}` AS `c`
             $sJoin
             WHERE `c`.`cmt_object_id` = ?" . $sWhereParent . $sOder . $sLimit, $iTimestamp, $iId);
@@ -142,11 +147,10 @@ class BxDolCmtsQuery extends BxDolDb
                 `c`.`cmt_author_id`,
                 `c`.`cmt_level`,
                 `c`.`cmt_text`,
-                `c`.`cmt_mood`,
                 `c`.`cmt_rate`,
                 `c`.`cmt_rate_count`,
                 `c`.`cmt_replies`,
-                ($iTimestamp - UNIX_TIMESTAMP(`c`.`cmt_time`)) AS `cmt_secs_ago`
+                ($iTimestamp - `c`.`cmt_time`) AS `cmt_secs_ago`
             FROM {$this->_sTable} AS `c`
             $sJoin
             WHERE `c`.`cmt_object_id` = ? AND `c`.`cmt_id` = ?
@@ -164,62 +168,35 @@ class BxDolCmtsQuery extends BxDolDb
         $iTimestamp = time();
         $sQuery = $this->prepare("
             SELECT
-                *, ($iTimestamp - UNIX_TIMESTAMP(`c`.`cmt_time`)) AS `cmt_secs_ago`
+                *, ($iTimestamp - `c`.`cmt_time`) AS `cmt_secs_ago`
             FROM {$this->_sTable} AS `c`
             WHERE `cmt_object_id` = ? AND `cmt_id` = ?
             LIMIT 1", $iId, $iCmtId);
         return $this->getRow($sQuery);
     }
 
-    function addComment ($iId, $iCmtParentId, $iAuthorId, $sText)
-    {
-    	$iLevel = 0;
-    	$iCmtVisualParentId = 0;
-    	if((int)$iCmtParentId > 0) {
-    		$sQuery = $this->prepare("SELECT `cmt_vparent_id`, `cmt_level` FROM {$this->_sTable} WHERE `cmt_id`=? LIMIT 1", $iCmtParentId);
-    		$aParent = $this->getRow($sQuery);
-
-    		$iLevel = (int)$aParent['cmt_level'] + 1;
-    		$iCmtVisualParentId = $iLevel > $this->_oMain->getMaxLevel() ? $aParent['cmt_vparent_id'] : $iCmtParentId;
-    	}
-
-        $sQuery = $this->prepare("INSERT INTO {$this->_sTable} SET
-            `cmt_parent_id` = ?,
-            `cmt_vparent_id` = ?,
-            `cmt_object_id` = ?,
-            `cmt_author_id` = ?,
-            `cmt_level` = ?,
-            `cmt_text` = ?,
-            `cmt_time` = NOW()", $iCmtParentId, $iCmtVisualParentId, $iId, $iAuthorId, $iLevel, $sText);
-        if(!$this->query($sQuery))
-            return false;
-
-        $iRet = $this->lastId();
-
-        if($iCmtParentId) {
-            $sQuery = $this->prepare("UPDATE {$this->_sTable} SET `cmt_replies` = `cmt_replies` + 1 WHERE `cmt_id` = ? LIMIT 1", $iCmtParentId);
-            $this->query ($sQuery);
-        }
-
-        return $iRet;
-    }
-
     function removeComment ($iId, $iCmtId, $iCmtParentId)
     {
         $sQuery = $this->prepare("DELETE FROM {$this->_sTable} WHERE `cmt_object_id` = ? AND `cmt_id` = ? LIMIT 1", $iId, $iCmtId);
         if (!$this->query($sQuery))
             return false;
 
-        $sQuery = $this->prepare("UPDATE {$this->_sTable} SET `cmt_replies` = `cmt_replies` - 1 WHERE `cmt_id` = ? LIMIT 1", $iCmtParentId);
-        $this->query ($sQuery);
+		if($iCmtParentId) 
+        	$this->updateRepliesCount($iCmtParentId, -1);
 
         return true;
     }
 
-    function updateComment ($iId, $iCmtId, $sText)
+	function saveImages($iSystemId, $iCmtId, $iImageId)
+	{
+		$sQuery = $this->prepare("INSERT IGNORE INTO `{$this->_sTableImages2Entries}` SET `system_id`=?, `cmt_id`=?, `image_id`=?", $iSystemId, $iCmtId, $iImageId);
+		return (int)$this->query($sQuery) > 0;
+	}
+
+    function updateRepliesCount($iCmtId, $iCount)
     {
-        $sQuery = $this->prepare("UPDATE {$this->_sTable} SET `cmt_text` = ?  WHERE `cmt_object_id` = ? AND `cmt_id` = ? LIMIT 1", $sText, $iId, $iCmtId);
-        return $this->query($sQuery);
+    	$sQuery = $this->prepare("UPDATE `{$this->_sTable}` SET `cmt_replies`=`cmt_replies`+? WHERE `cmt_id`=? LIMIT 1", $iCount, $iCmtId);
+		return $this->query($sQuery);
     }
 
     function rateComment ($iSystemId, $iCmtId, $iRate, $iAuthorId, $sAuthorIp)
@@ -312,7 +289,8 @@ class BxDolCmtsQuery extends BxDolDb
         return $this->query($sQuery);
     }
 
-    function maintenance() {
+    function maintenance()
+    {
         $iTimestamp = time();
         $iDeletedRecords = $this->query("DELETE FROM {$this->_sTableTrack} WHERE `cmt_rate_ts` < ($iTimestamp - " . (int)BX_OLD_CMT_VOTES . ")");
         if ($iDeletedRecords)
@@ -320,4 +298,3 @@ class BxDolCmtsQuery extends BxDolDb
         return $iDeletedRecords;
     }
 }
-

+ 10 - 1
inc/classes/BxDolForm.php

@@ -891,6 +891,15 @@ class BxDolForm extends BxDol {
         return BxDolForm::getSubmittedValue($this->aParams['db']['submit_name'], $this->aFormAttrs['method'], $this->_aSpecificValues) ? true : false;
     }
 
+    function setId ($sId) {
+    	$this->id = $sId;
+    	$this->aFormAttrs['id'] = $sId;
+    }
+
+    function setName($sName) {
+    	$this->aFormAttrs['name'] = $sName;
+    }
+
     function setValid ($isValid) {
         $this->_isValid = $isValid;
     }
@@ -1130,7 +1139,7 @@ class BxDolFormChecker {
                     continue;
 
                 ++$iErrors;
-                $aInputs[$k]['error'] = sprintf(_t("_sys_spam_detected"), BX_DOL_URL_ROOT . 'contact.php');
+                $aInputs[$k]['error'] = _t('_sys_spam_detected', BX_DOL_URL_ROOT . 'contact.php');
 
             }
         }

+ 178 - 216
inc/js/classes/BxDolCmts.js

@@ -5,7 +5,6 @@
  */
 
 function BxDolCmts (options) {
-    this.oCmtElements = {}; // form elements
     this._sObjName = undefined == options.sObjName ? 'oCmts' : options.sObjName;    // javascript object name, to run current object instance from onTimer
     this._sSystem = options.sSystem; // current comment system
     this._sSystemTable = options.sSystemTable; // current comment system table name
@@ -31,140 +30,106 @@ function BxDolCmts (options) {
 }
 
 /*--- Main layout functionality ---*/
-BxDolCmts.prototype.cmtSubmit = function (f)
+BxDolCmts.prototype.cmtInitFormPost = function(sCmtFormId)
 {
-    var eSubmit = $(f).children().find(':submit').get();
-    var $this = this;
-    var oData = this._getDefaultActions();
-
-    // hide any errors before submitting
-    $this._error(eSubmit, false);
-
-    // get and check form elements
-    if (!this._getCheckElements (f, oData)) 
-    	return;
-
-    // submit form
-    oData['action'] = 'CmtPost';
-
-    this._loadingInButton(eSubmit, true);
-
-    jQuery.post (
-        this._sActionsUrl,
-        oData,
-        function (s) {
-            $this._loadingInButton(eSubmit, false);
+	var $this = this;
+	var oCmtForm = $('#' + sCmtFormId);
 
-            var iNewCmtId = parseInt(s);
-            if(iNewCmtId > 0) {
-                $(f).find(':input:not(:button,:submit,[type = hidden],[type = radio],[type = checkbox])').val('');
-                $this._getCmt(f, oData['CmtParent'], iNewCmtId); // display just posted comment
-            }
-            else if (!jQuery.trim(s).length) {
-                $this._error(eSubmit, true, aDolLang['_Error occured']); // display error
-            }
-            else {
-                $this._error(eSubmit, true, s); // display error
-            }
+	oCmtForm.ajaxForm({
+        dataType: "json",
+        beforeSubmit: function (formData, jqForm, options) {
+        	window[$this._sObjName].cmtBeforePostSubmit(oCmtForm);
+        },
+        success: function (oData) {
+        	window[$this._sObjName].cmtAfterPostSubmit(oCmtForm, oData);
         }
-    );
+    });
 };
 
-BxDolCmts.prototype.cmtUpdate = function (f, iCmtId)
+BxDolCmts.prototype.cmtBeforePostSubmit = function(oCmtForm)
 {
-    var eSubmit = $(f).find(':submit').get();
-    var $this = this;
-    var oData = this._getDefaultActions();
+	this._loadingInButton($(oCmtForm).children().find(':submit'), true);
+};
 
-    $this._error(eSubmit, false); // hide any errors before submitting
+BxDolCmts.prototype.cmtAfterPostSubmit = function (oCmtForm, oData)
+{
+	this._loadingInButton($(oCmtForm).children().find(':submit'), false);
 
-    if (!this._getCheckElements (f, oData)) return; // get and check form elements
+	if(oData && oData.msg != undefined)
+        alert(oData.msg);
 
-    this._oSavedTexts[iCmtId] = '';
+	if(oData && oData.id != undefined) {
+		var iCmtId = parseInt(oData.id);
+        if(iCmtId > 0) {
+            $(oCmtForm).find(':input:not(:button,:submit,[type = hidden],[type = radio],[type = checkbox])').val('');
+            $(oCmtForm).find('.bx-form-warn').hide().html('');
+            this._getCmt(oCmtForm, iCmtId);
+        }
 
-    // submit form
-    oData['action'] = 'CmtEditSubmit';
-    oData['Cmt'] = iCmtId;
-    this._loadingInBlock (eSubmit, true);
-    jQuery.post (
-        this._sActionsUrl,
-        oData,
-        function (oResponse) {
-            $this._loadingInBlock (eSubmit, false);
-            if (!jQuery.trim(oResponse.text).length)
-                $this._error(eSubmit, true, jQuery.trim(oResponse.err).length ? oResponse.err : aDolLang['_Error occured']); // display error
-            else
-                $('#cmt' + iCmtId + ' .cmt-body').bx_anim(
-                    'hide',
-                    $this._sAnimationEffect,
-                    $this._iAnimationSpeed,
-                    function() {
-                        $(this).html(oResponse.text).bx_anim('show', $this._sAnimationEffect, $this._iAnimationSpeed);
-                    });
-        },
-        'json'
-    );
-};
+        return;
+	}
 
-BxDolCmts.prototype.cmtReload = function(iCmtId) {
-    var $this = this;
-    var oData = this._getDefaultActions();
-    oData['action'] = 'CmtGet';
-    oData['Cmt'] = iCmtId;
-    oData['Type'] = 'reload';
+	if(oData && oData.form != undefined && oData.form_id != undefined) {
+		$('#' + oData.form_id).replaceWith(oData.form);
+		this.cmtInitFormPost(oData.form_id);
 
-    var eUl = $('#cmts-box-' + $this._sSystem + '-' + $this._iObjId + ' > div.cmts > ul').get();
-    this._loadingInBlock (eUl, true);
+		return;
+	}
+};
 
-    jQuery.post (
-        this._sActionsUrl,
-        oData,
-        function (s) {
-            $this._loadingInBlock (eUl, false);
-            $('#cmts-box-' + $this._sSystem + '-' + $this._iObjId + ' li#cmt' + iCmtId).bx_anim('hide', $this._sAnimationEffect, $this._iAnimationSpeed, function() {
-                $(this).replaceWith(s);
-            });
+BxDolCmts.prototype.cmtInitFormEdit = function(sCmtFormId)
+{
+	var $this = this;
+	var oCmtForm = $('#' + sCmtFormId);
 
+	oCmtForm.ajaxForm({
+        dataType: "json",
+        beforeSubmit: function (formData, jqForm, options) {
+        	window[$this._sObjName].cmtBeforeEditSubmit(oCmtForm);
+        },
+        success: function (oData) {
+        	window[$this._sObjName].cmtAfterEditSubmit(oCmtForm, oData);
         }
-    );
+    });
+};
 
+BxDolCmts.prototype.cmtBeforeEditSubmit = function(oCmtForm)
+{
+	this._loadingInButton($(oCmtForm).children().find(':submit'), true);
 };
 
-BxDolCmts.prototype.cmtRemove = function(e, iCmtId) {
-    if (!this._confirm()) return;
+BxDolCmts.prototype.cmtAfterEditSubmit = function (oCmtForm, oData)
+{
+	var $this = this;
+	this._loadingInButton($(oCmtForm).children().find(':submit'), false);
 
-    var $this = this;
-    var oData = this._getDefaultActions();
-    oData['action'] = 'CmtRemove';
-    oData['Cmt'] = iCmtId;
+	if(oData && oData.msg != undefined)
+        alert(oData.msg);
 
-    this._loadingInContent(e, true);
+	if(oData && oData.id != undefined && oData.text != undefined) {
+		var iCmtId = parseInt(oData.id);
+		if(iCmtId > 0) {
+			$('#cmt' + iCmtId + ' .cmt-body').bx_anim('hide', this._sAnimationEffect, this._iAnimationSpeed, function() {
+				$(this).html(oData.text).bx_anim('show', $this._sAnimationEffect, $this._iAnimationSpeed);
+			});
+        }
 
-    jQuery.post (
-        this._sActionsUrl,
-        oData,
-        function(s) {
-            $this._loadingInContent(e, false);
+        return;
+	}
 
-            if (jQuery.trim(s).length)
-                alert(s);
-            else
-                $('#cmt' + iCmtId).bx_anim('hide', $this._sAnimationEffect, $this._iAnimationSpeed, function() {
-                	var oCounter = $(this).parent('ul.cmts').siblings('.cmt-cont').find('.cmt-actions a.cmt-comment-replies span');
-                	if(oCounter)
-                		oCounter.html(oCounter.html() - 1);
+	if(oData && oData.form != undefined && oData.form_id != undefined) {
+		$('#' + oData.form_id).replaceWith(oData.form);
+		this.cmtInitFormEdit(oData.form_id);
 
-                	$(this).remove();
-                });
-        }
-    );
+		return;
+	}
 };
 
 BxDolCmts.prototype.cmtEdit = function(oLink, iCmtId) {
     var $this = this;
-    var oData = this._getDefaultActions();
-    oData['action'] = 'CmtEdit';
-    oData['Cmt'] = iCmtId;
+    var oParams = this._getDefaultActions();
+    oParams['action'] = 'GetFormEdit';
+    oParams['Cmt'] = iCmtId;
 
     $(oLink).parents('.cmt-comment-manage:first').dolPopupHide();
 
@@ -182,50 +147,90 @@ BxDolCmts.prototype.cmtEdit = function(oLink, iCmtId) {
 
     jQuery.post (
         this._sActionsUrl,
-        oData,
-        function (s) {
+        oParams,
+        function (oData) {
         	$this._loadingInContent (oLink, false);
 
-        	if(s.substring(0,3) == 'err')
-        		alert(s.substring(3));
-            else
-                $(sBodyId).bx_anim('hide', $this._sAnimationEffect, $this._iAnimationSpeed, function() {
-                    $(this).html(s).bx_anim('show', $this._sAnimationEffect, $this._iAnimationSpeed);
+        	if(oData && oData.msg != undefined)
+                alert(oData.msg);
+
+        	if(oData && oData.form != undefined && oData.form_id != undefined) {
+        		$(sBodyId).bx_anim('hide', $this._sAnimationEffect, $this._iAnimationSpeed, function() {
+                    $(this).html(oData.form).bx_anim('show', $this._sAnimationEffect, $this._iAnimationSpeed, function() {
+                    	$this.cmtInitFormEdit(oData.form_id);
+                    });
                 });
-        }
+        	}
+        },
+        'json'
+    );
+};
+
+BxDolCmts.prototype.cmtRemove = function(e, iCmtId) {
+    if (!this._confirm()) 
+    	return;
+
+    var $this = this;
+    var oParams = this._getDefaultActions();
+    oParams['action'] = 'Remove';
+    oParams['Cmt'] = iCmtId;
+
+    this._loadingInContent(e, true);
+
+    jQuery.post (
+        this._sActionsUrl,
+        oParams,
+        function(oData) {
+            $this._loadingInContent(e, false);
+
+            if(oData && oData.msg != undefined)
+                alert(oData.msg);
+
+            if(oData && oData.id != undefined) {
+            	$('#cmt' + oData.id).bx_anim('hide', $this._sAnimationEffect, $this._iAnimationSpeed, function() {
+                	var oCounter = $(this).parent('ul.cmts').siblings('.cmt-cont').find('.cmt-actions a.cmt-comment-replies span');
+                	if(oCounter)
+                		oCounter.html(oCounter.html() - 1);
+
+                	$(this).remove();
+                });
+            }
+        },
+        'json'
     );
 };
 
 BxDolCmts.prototype.cmtRate = function(e, iCmtId, iRate) 
 {
     var $this = this;
-    var oData = this._getDefaultActions();
-    oData['action'] = 'CmtRate';
-    oData['Cmt'] = iCmtId;
-    oData['Rate'] = iRate;
+    var oParams = this._getDefaultActions();
+    oParams['action'] = 'Rate';
+    oParams['Cmt'] = iCmtId;
+    oParams['Rate'] = iRate;
 
     this._loadingInContent (e, true);
 
     jQuery.post (
         this._sActionsUrl,
-        oData,
-        function (s) {
+        oParams,
+        function(oData) {
             $this._loadingInContent (e, false);
 
-            if(jQuery.trim(s).length) {
-                alert(s);
-                return;
-            }
-
-            var oPoints = $(e).parents('.cmt:first').find('.cmt-points span');
-            oPoints.html(parseInt(oPoints.html()) + iRate).parents('.cmt-points-wrp:first').bx_anim(parseInt(oPoints.html()) > 0 ? 'show' : 'hide');
+            if(oData && oData.msg != undefined)
+                alert(oData.msg);
 
-            $(e).hide().siblings('.cmt-comment-vote:hidden').show();
-        }
+            if(oData && oData.id != undefined && oData.rate != undefined) {
+	            var oPoints = $(e).parents('.cmt:first').find('.cmt-points span');
+	            oPoints.html(parseInt(oPoints.html()) + oData.rate).parents('.cmt-points-wrp:first').bx_anim(parseInt(oPoints.html()) > 0 ? 'show' : 'hide');
+	
+	            $(e).hide().siblings('.cmt-comment-vote:hidden').show();
+            }
+        },
+        'json'
     );
 };
 
-BxDolCmts.prototype.cmtMore = function(oLink, iCmtParentId, iStart, iPerView)
+BxDolCmts.prototype.cmtLoad = function(oLink, iCmtParentId, iStart, iPerView)
 {
 	var $this = this;
 	var bButton = $(oLink).hasClass('bx-btn');
@@ -270,7 +275,7 @@ BxDolCmts.prototype.showReplacement = function(iCmtId)
     });
 };
 
-BxDolCmts.prototype.seeMore = function(oLink)
+BxDolCmts.prototype.showMore = function(oLink)
 {
 	$(oLink).parent('span').next('span').show().prev('span').remove();
 };
@@ -285,7 +290,7 @@ BxDolCmts.prototype.toggleReply = function(e, iCmtParentId)
     else {
         var $this = this;
         var oData = this._getDefaultActions();
-        oData['action'] = 'FormGet';
+        oData['action'] = 'GetFormPost';
         oData['CmtType'] = 'reply';
         oData['CmtParent'] = iCmtParentId;
         oData['CmtBrowse'] = this._sBrowseType;
@@ -346,7 +351,7 @@ BxDolCmts.prototype.toggleManagePopup = function(oLink, iCmtId) {
 BxDolCmts.prototype.togglePlusedByPopup = function(oLink, iCmtId) {
 	var $this = this;
     var oData = this._getDefaultActions();
-    oData['action'] = 'PlusedByGet';
+    oData['action'] = 'GetPlusedBy';
     oData['CmtId'] = iCmtId;
 
     var oPopup = $(".bx-popup-applied:visible");
@@ -375,12 +380,47 @@ BxDolCmts.prototype.togglePlusedByPopup = function(oLink, iCmtId) {
 	);
 };
 
-// get comment replies via ajax request
+
+BxDolCmts.prototype._getCmt = function (e, iCmtId)
+{
+    var $this = this;
+    var oData = this._getDefaultActions();
+    oData['action'] = 'GetCmt';
+    oData['Cmt'] = iCmtId;
+    oData['CmtBrowse'] = this._sBrowseType;
+    oData['CmtDisplay'] = this._sDisplayType;
+
+    this._loadingInBlock (e);
+
+    jQuery.post (
+        this._sActionsUrl,
+        oData,
+        function (oData) {
+            $this._loadingInBlock (e, false);
+
+            var sListId = $this._sRootId + ' #cmt' + oData.vparent_id + ' > ul';
+            var sReplyFormId = $this._sRootId + ' #cmt' + oData.parent_id + ' > .cmt-reply';
+
+            //--- Hide reply form ---//
+            if($(sReplyFormId).length)
+            	$(sReplyFormId).bx_anim('hide', $this._sAnimationEffect, $this._iAnimationSpeed);
+
+            //--- Some number of comments already loaded ---//
+            if($(sListId + ' > li.cmt').length)
+                $(sListId + ' > li.cmt:last').after($(oData.content).hide()).next('li.cmt:hidden').bx_anim('toggle', $this._sAnimationEffect, $this._iAnimationSpeed);
+            //-- There is no comments at all ---//
+            else
+            	$(sListId).hide().html(oData.content).bx_anim('show', $this._sAnimationEffect, $this._iAnimationSpeed);
+        },
+        'json'
+    );
+};
+
 BxDolCmts.prototype._getCmts = function (e, iCmtParentId, iStart, iPerView, sBrowseType, sDisplayType, onLoad)
 {
     var $this = this;
     var oData = this._getDefaultActions();    
-    oData['action'] = 'CmtsGet';
+    oData['action'] = 'GetCmts';
     oData['CmtParent'] = iCmtParentId;
     if(parseInt(iStart) >= 0)
         oData['CmtStart'] = iStart;
@@ -437,78 +477,6 @@ BxDolCmts.prototype._cmtsReplaceContent = function(oParent, sContent)
 	});
 };
 
-// get just posted 1 comment via ajax request
-BxDolCmts.prototype._getCmt = function (f, iCmtParentId, iCmtId)
-{
-    var $this = this;
-    var oData = this._getDefaultActions();
-    oData['action'] = 'CmtGet';
-    oData['Cmt'] = iCmtId;
-    oData['CmtBrowse'] = this._sBrowseType;
-    oData['CmtDisplay'] = this._sDisplayType;
-
-    this._loadingInBlock (f);
-
-    jQuery.post (
-        this._sActionsUrl,
-        oData,
-        function (oData) {
-            $this._loadingInBlock (f, false);
-
-            var sListId = $this._sRootId + ' #cmt' + oData.vparent_id + ' > ul';
-            var sReplyFormId = $this._sRootId + ' #cmt' + oData.parent_id + ' > .cmt-reply';
-
-            //--- Hide reply form ---//
-            if($(sReplyFormId).length)
-            	$(sReplyFormId).bx_anim('hide', $this._sAnimationEffect, $this._iAnimationSpeed);
-
-            //--- Some number of comments already loaded ---//
-            if($(sListId + ' > li.cmt').length)
-                $(sListId + ' > li.cmt:last').after($(oData.content).hide()).next('li.cmt:hidden').bx_anim('toggle', $this._sAnimationEffect, $this._iAnimationSpeed);
-            //-- There is no comments at all ---//
-            else
-            	$(sListId).hide().html(oData.content).bx_anim('show', $this._sAnimationEffect, $this._iAnimationSpeed);
-        },
-        'json'
-    );
-};
-
-// check and get post new comment form elements
-BxDolCmts.prototype._getCheckElements = function(f, oData) {
-    var $this = this;
-    var bSuccess = true;
-    // check/get form elements
-    jQuery.each( $(f).find(':input'), function () {
-        if (this.name.length && $this.oCmtElements[this.name]) {
-            var isValid = true;
-
-            //--- Check form's data ---//
-            if ($this.oCmtElements[this.name]['reg']) {
-                try {
-                	var r = new RegExp($this.oCmtElements[this.name]['reg']); 
-                 	isValid = r.test(this.value.replace(/(\n|\r)/g, ''));
-                } catch (ex) {};
-            }
-            if (!isValid) {
-                bSuccess = false;
-                $this._error(this, true, $this.oCmtElements[this.name]['msg']);
-            }
-            else {
-                $this._error(this, false);
-            }
-
-            //--- Fill in data array ---//
-            if(this.type == 'radio') {
-                if(this.checked)
-                    oData[this.name] = this.value;
-            }
-            else
-                oData[this.name] = this.value;
-        }
-    });
-    return bSuccess;
-};
-
 BxDolCmts.prototype._getDefaultActions = function() {
     return {
         'sys': this._sSystem,
@@ -530,6 +498,7 @@ BxDolCmts.prototype._loadingInContent = function(e, bShow) {
 	var oParent = $(e).length ? $(e).parents('li.cmt:first,.cmt-reply:first') : $('body'); 
 	bx_loading(oParent, bShow);
 };
+
 BxDolCmts.prototype._loadingInButton = function(e, bShow) {
 	if($(e).length)
 		bx_loading_btn($(e), bShow);
@@ -537,13 +506,6 @@ BxDolCmts.prototype._loadingInButton = function(e, bShow) {
 		bx_loading($('body'), bShow);	
 };
 
-BxDolCmts.prototype._error = function(e, bShow, s) {
-    if (bShow && !$(e).next('.cmt-err').length)
-        $(e).after(' <b class="cmt-err">' + s + '</b>');
-    else if (!bShow && $(e).next('.cmt-err').length)
-        $(e).next('.cmt-err').remove();
-};
-
 BxDolCmts.prototype._confirm = function() {
     return confirm(aDolLang['_Are you sure?']);
 };

+ 77 - 11
install/sql/v70.sql

@@ -123,7 +123,7 @@ CREATE TABLE `sys_objects_categories` (
 
 CREATE TABLE `sys_objects_cmts` (
   `ID` int(10) unsigned NOT NULL auto_increment,
-  `ObjectName` varchar(50) NOT NULL,
+  `Name` varchar(50) NOT NULL,
   `TableCmts` varchar(50) NOT NULL,
   `TableTrack` varchar(50) NOT NULL,
   `CharsPostMin` int(10) NOT NULL,
@@ -983,9 +983,42 @@ CREATE TABLE `sys_images` (
   UNIQUE KEY `remote_id` (`remote_id`)
 );
 
+-- --------------------------------------------------------
+
+--
+-- Table structure for table `sys_images_cmts`
+--
+CREATE TABLE IF NOT EXISTS `sys_images_cmts` (
+  `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`)
+);
 
 -- --------------------------------------------------------
 
+--
+-- Table structure for table `sys_images_cmts2entries`
+--
+CREATE TABLE IF NOT EXISTS `sys_images_cmts2entries` (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `system_id` int(11) NOT NULL DEFAULT '0',
+  `cmt_id` int(11) NOT NULL DEFAULT '0',
+  `image_id` int(11) NOT NULL DEFAULT '0',
+  PRIMARY KEY (`id`),
+  UNIQUE KEY `image` (`system_id`,`cmt_id`,`image_id`)
+) ENGINE=MyISAM  DEFAULT CHARSET=utf8;
+
+-- --------------------------------------------------------
 
 CREATE TABLE `sys_injections` (
   `id` int(11) unsigned NOT NULL auto_increment,
@@ -999,7 +1032,7 @@ CREATE TABLE `sys_injections` (
   PRIMARY KEY  (`id`)
 ) ENGINE=MyISAM  DEFAULT CHARSET=utf8;
 
-
+-- --------------------------------------------------------
 
 CREATE TABLE `sys_injections_admin` (
   `id` int(11) unsigned NOT NULL auto_increment,
@@ -1267,7 +1300,8 @@ CREATE TABLE IF NOT EXISTS `sys_objects_storage` (
 ) ENGINE=MyISAM DEFAULT CHARSET=utf8;
 
 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
-('sys_images', 'Local', '', 360, 2592000, 0, 'sys_images', 'allow-deny', 'jpg,jpeg,jpe,gif,png', '', 0, 0, 0, 0, 0, 0);
+('sys_images', 'Local', '', 360, 2592000, 0, 'sys_images', 'allow-deny', 'jpg,jpeg,jpe,gif,png', '', 0, 0, 0, 0, 0, 0),
+('sys_images_cmts', 'Local', '', 360, 2592000, 3, 'sys_images_cmts', 'allow-deny', 'jpg,jpeg,jpe,gif,png', '', 0, 0, 0, 0, 0, 0);
 
 CREATE TABLE IF NOT EXISTS `sys_storage_user_quotas` (
   `profile_id` int(11) NOT NULL,
@@ -2220,7 +2254,8 @@ CREATE TABLE IF NOT EXISTS `sys_objects_uploader` (
 
 INSERT INTO `sys_objects_uploader` (`object`, `active`, `override_class_name`, `override_class_file`) VALUES
 ('sys_simple', 1, 'BxTemplUploaderSimple', ''),
-('sys_html5', 1, 'BxTemplUploaderHTML5', '');
+('sys_html5', 1, 'BxTemplUploaderHTML5', ''),
+('sys_simple_cmts', 1, 'BxTemplCmtsUploaderSimple', '');
 
 
 -- --------------------------------------------------------
@@ -2252,7 +2287,8 @@ INSERT INTO `sys_objects_form` (`object`, `module`, `title`, `action`, `form_att
 ('sys_account', 'system', '_sys_form_account', '', '', 'do_submit', 'sys_accounts', 'id', '', '', 'a:1:{s:14:"checker_helper";s:26:"BxFormAccountCheckerHelper";}', 0, 1, 'BxTemplFormAccount', ''),
 ('sys_forgot_password', 'system', '_sys_form_forgot_password', '', '', 'do_submit', '', '', '', '', 'a:1:{s:14:"checker_helper";s:33:"BxFormForgotPasswordCheckerHelper";}', 0, 1, 'BxTemplFormForgotPassword', ''),
 ('sys_confirm_email', 'system', '_sys_form_confirm_email', '', '', 'do_submit', '', '', '', '', 'a:1:{s:14:"checker_helper";s:31:"BxFormConfirmEmailCheckerHelper";}', 0, 1, 'BxTemplFormConfirmEmail', ''),
-('sys_unsubscribe', 'system', '_sys_form_unsubscribe', '', '', 'do_submit', 'sys_accounts', 'id', '', '', '', 0, 1, 'BxTemplFormAccount', '');
+('sys_unsubscribe', 'system', '_sys_form_unsubscribe', '', '', 'do_submit', 'sys_accounts', 'id', '', '', '', 0, 1, 'BxTemplFormAccount', ''),
+('sys_comment', 'system', '_sys_form_comment', 'cmts.php', 'a:3:{s:2:"id";s:17:"cmt-%s-form-%s-%d";s:4:"name";s:17:"cmt-%s-form-%s-%d";s:5:"class";s:14:"cmt-post-reply";}', 'cmt_submit', '', 'cmt_id', '', '', '', 0, 1, '', '');
 
 CREATE TABLE IF NOT EXISTS `sys_form_displays` (
   `id` int(11) NOT NULL AUTO_INCREMENT,
@@ -2275,7 +2311,9 @@ INSERT INTO `sys_form_displays` (`display_name`, `module`, `object`, `title`, `v
 ('sys_forgot_password', 'system', 'sys_forgot_password', '_sys_form_display_forgot_password', 0),
 ('sys_confirm_email', 'system', 'sys_confirm_email', '_sys_form_display_confirm_email', 0),
 ('sys_unsubscribe_updates', 'system', 'sys_unsubscribe', '_sys_form_display_unsubscribe_updates', 0),
-('sys_unsubscribe_news', 'system', 'sys_unsubscribe', '_sys_form_display_unsubscribe_news', 0);
+('sys_unsubscribe_news', 'system', 'sys_unsubscribe', '_sys_form_display_unsubscribe_news', 0),
+('sys_comment_post', 'system', 'sys_comment', '_sys_form_display_comment_post', 0),
+('sys_comment_edit', 'system', 'sys_comment', '_sys_form_display_comment_edit', 0);
 
 
 CREATE TABLE IF NOT EXISTS `sys_form_inputs` (
@@ -2339,7 +2377,16 @@ INSERT INTO `sys_form_inputs` (`object`, `module`, `name`, `value`, `values`, `c
 ('sys_unsubscribe', 'system', 'code', '', '', 0, 'hidden', '_sys_form_unsubscribe_input_caption_system_code', '', '', 0, 0, 0, '', '', '', '', '', '', '', '', 0, 0),
 ('sys_unsubscribe', 'system', 'receive_updates', '1', '', 0, 'switcher', '_sys_form_unsubscribe_input_caption_system_receive_updates', '_sys_form_unsubscribe_input_receive_updates', '', 0, 0, 0, '', '', '', '', '', '', 'Int', '', 0, 0),
 ('sys_unsubscribe', 'system', 'receive_news', '1', '', 0, 'switcher', '_sys_form_unsubscribe_input_caption_system_receive_news', '_sys_form_unsubscribe_input_receive_news', '', 0, 0, 0, '', '', '', '', '', '', 'Int', '', 0, 0),
-('sys_unsubscribe', 'system', 'do_submit', '_sys_form_unsubscribe_input_submit', '', 0, 'submit', '_sys_form_unsubscribe_input_caption_system_do_submit', '', '', 0, 0, 0, '', '', '', '', '', '', '', '', 0, 0);
+('sys_unsubscribe', 'system', 'do_submit', '_sys_form_unsubscribe_input_submit', '', 0, 'submit', '_sys_form_unsubscribe_input_caption_system_do_submit', '', '', 0, 0, 0, '', '', '', '', '', '', '', '', 0, 0),
+
+('sys_comment', 'system', 'sys', '', '', 0, 'hidden', '_sys_form_comment_input_caption_system_sys', '', '', 0, 0, 0, '', '', '', '', '', '', '', '', 0, 0),
+('sys_comment', 'system', 'id', '', '', 0, 'hidden', '_sys_form_comment_input_caption_system_id', '', '', 0, 0, 0, '', '', '', '', '', '', '', '', 0, 0),
+('sys_comment', 'system', 'action', '', '', 0, 'hidden', '_sys_form_comment_input_caption_system_action', '', '', 0, 0, 0, '', '', '', '', '', '', '', '', 0, 0),
+('sys_comment', 'system', 'cmt_id', '', '', 0, 'hidden', '_sys_form_comment_input_caption_system_cmt_id', '', '', 0, 0, 0, '', '', '', '', '', '', 'Int', '', 0, 0),
+('sys_comment', 'system', 'cmt_parent_id', '', '', 0, 'hidden', '_sys_form_comment_input_caption_system_cmt_parent_id', '', '', 0, 0, 0, '', '', '', '', '', '', 'Int', '', 0, 0),
+('sys_comment', 'system', 'cmt_text', '', '', 0, 'textarea', '_sys_form_comment_input_caption_system_cmt_text', '', '', 0, 0, 0, '', '', '', 'Length', 'a:2:{s:3:"min";i:1;s:3:"max";i:5000;}', '_Please enter n1-n2 characters', 'Xss', '', 1, 0),
+('sys_comment', 'system', 'cmt_image', '', '', 0, 'files', '_sys_form_comment_input_caption_system_cmt_image', '', '', 0, 0, 0, '', '', '', '', '', '', '', '', 1, 0),
+('sys_comment', 'system', 'cmt_submit', '_sys_form_comment_input_submit', '', 0, 'submit', '_sys_form_comment_input_caption_system_cmt_submit', '', '', 0, 0, 0, '', '', '', '', '', '', '', '', 0, 0);
 
 
 CREATE TABLE IF NOT EXISTS `sys_form_display_inputs` (
@@ -2405,7 +2452,25 @@ INSERT INTO `sys_form_display_inputs` (`display_name`, `input_name`, `visible_fo
 ('sys_unsubscribe_news', 'id', 2147483647, 1, 1),
 ('sys_unsubscribe_news', 'code', 2147483647, 1, 2),
 ('sys_unsubscribe_news', 'receive_news', 2147483647, 1, 3),
-('sys_unsubscribe_news', 'do_submit', 2147483647, 1, 4);
+('sys_unsubscribe_news', 'do_submit', 2147483647, 1, 4),
+
+('sys_comment_post', 'sys', 2147483647, 1, 1),
+('sys_comment_post', 'id', 2147483647, 1, 2),
+('sys_comment_post', 'action', 2147483647, 1, 3),
+('sys_comment_post', 'cmt_id', 2147483647, 0, 4),
+('sys_comment_post', 'cmt_parent_id', 2147483647, 1, 5),
+('sys_comment_post', 'cmt_text', 2147483647, 1, 6),
+('sys_comment_post', 'cmt_image', 2147483647, 1, 7),
+('sys_comment_post', 'cmt_submit', 2147483647, 1, 8),
+
+('sys_comment_edit', 'sys', 2147483647, 1, 1),
+('sys_comment_edit', 'id', 2147483647, 1, 2),
+('sys_comment_edit', 'action', 2147483647, 1, 3),
+('sys_comment_edit', 'cmt_id', 2147483647, 1, 4),
+('sys_comment_edit', 'cmt_parent_id', 2147483647, 1, 5),
+('sys_comment_edit', 'cmt_text', 2147483647, 1, 6),
+('sys_comment_edit', 'cmt_image', 2147483647, 1, 7),
+('sys_comment_edit', 'cmt_submit', 2147483647, 1, 8);
 
 
 CREATE TABLE `sys_form_pre_lists` (
@@ -3106,8 +3171,8 @@ CREATE TABLE IF NOT EXISTS `sys_objects_transcoder_images` (
 INSERT INTO `sys_objects_transcoder_images` (`object`, `storage_object`, `source_type`, `source_params`, `private`, `atime_tracking`, `atime_pruning`, `ts`) VALUES 
 ('sys_icon_apple', 'sys_images', 'Storage', 'a:1:{s:6:"object";s:10:"sys_images";}', 'no', '0', '0', '0'),
 ('sys_icon_facebook', 'sys_images', 'Storage', 'a:1:{s:6:"object";s:10:"sys_images";}', 'no', '0', '0', '0'),
-('sys_icon_favicon', 'sys_images', 'Storage', 'a:1:{s:6:"object";s:10:"sys_images";}', 'no', '0', '0', '0');
-
+('sys_icon_favicon', 'sys_images', 'Storage', 'a:1:{s:6:"object";s:10:"sys_images";}', 'no', '0', '0', '0'),
+('sys_images_cmts_preview', 'sys_images_cmts', 'Storage', 'a:1:{s:6:"object";s:15:"sys_images_cmts";}', 'no', '1', '2592000', '0');
 
 
 CREATE TABLE IF NOT EXISTS `sys_transcoder_images_files` (
@@ -3132,7 +3197,8 @@ CREATE TABLE IF NOT EXISTS `sys_transcoder_images_filters` (
 INSERT INTO `sys_transcoder_images_filters` (`transcoder_object`, `filter`, `filter_params`, `order`) VALUES 
 ('sys_icon_apple', 'Resize', 'a:4:{s:1:"w";s:3:"129";s:1:"h";s:3:"129";s:13:"square_resize";s:1:"1";s:10:"force_type";s:3:"png";}', '0'),
 ('sys_icon_facebook', 'Resize', 'a:4:{s:1:"w";s:3:"100";s:1:"h";s:3:"100";s:13:"square_resize";s:1:"1";s:10:"force_type";s:3:"png";}', '0'),
-('sys_icon_favicon', 'Resize', 'a:4:{s:1:"w";s:2:"16";s:1:"h";s:2:"16";s:13:"square_resize";s:1:"1";s:10:"force_type";s:3:"png";}', '0');
+('sys_icon_favicon', 'Resize', 'a:4:{s:1:"w";s:2:"16";s:1:"h";s:2:"16";s:13:"square_resize";s:1:"1";s:10:"force_type";s:3:"png";}', '0'),
+('sys_images_cmts_preview', 'Resize', 'a:4:{s:1:"w";s:3:"100";s:1:"h";s:3:"100";s:13:"square_resize";s:1:"1";s:10:"force_type";s:3:"jpg";}', '0');
 
 
 -- --------------------------------------------------------

+ 22 - 5
modules/boonex/english/data/langs/system.xml

@@ -1180,9 +1180,9 @@ Please click "Continue" below to navigate to the home page of the site.]]></stri
 	<string name="_cmt_browse_connection"><![CDATA[Connection]]></string>
 	<string name="_cmt_page_view_header"><![CDATA[Comment to {0}]]></string>
 	<string name="_cmt_page_view_title"><![CDATA[Comment to <a href="{0}">{1}</a>]]></string>
+	<string name="_cmt_err_cannot_perform_action"><![CDATA[Cannot perform action. Please report.]]></string>
 	<string name="_Reply_to_this_comment"><![CDATA[Reply]]></string>
 	<string name="_Add Your Comment"><![CDATA[Comment]]></string>
-	<string name="_Submit_Comment"><![CDATA[Post]]></string>
 	<string name="_load_more_comments_head"><![CDATA[See Newer Comments...]]></string>
 	<string name="_load_more_comments_tail"><![CDATA[See Older Comments...]]></string>
 	<string name="_load_more_comments_popular"><![CDATA[See More Comments...]]></string>
@@ -2136,7 +2136,7 @@ Please click "Continue" below to navigate to the home page of the site.]]></stri
     <string name="_adm_form_err_field_edit"><![CDATA[Cannot update field]]></string>
     <string name="_adm_form_btn_field_delete"><![CDATA[Delete field]]></string>
     <string name="_adm_from_err_field_delete"><![CDATA[Cannot delete field]]></string>
-    <string name="_adm_form_txt_field_show_to_popup"><![CDATA[Show "{0}" menu item to: ]]></string>
+    <string name="_adm_form_txt_field_show_to_popup"><![CDATA[Show "{0}" form field to: ]]></string>
     <string name="_adm_form_err_field_show_to"><![CDATA[Cannot update field]]></string>
     <string name="_adm_form_txt_field_visible_for"><![CDATA[Visible For]]></string>
     <string name="_adm_form_txt_field_visible_for_all"><![CDATA[Anyone]]></string>
@@ -3153,7 +3153,6 @@ Please click "Continue" below to navigate to the home page of the site.]]></stri
 	<string name="_edit_profile_info"><![CDATA[Edit profile info]]></string>
 	<string name="_edit_profile_privacy"><![CDATA[Edit profile privacy]]></string>
 	<string name="_edit_profile_privacy_save"><![CDATA[Save]]></string>
-	<string name="_bad comment parent id"><![CDATA[bad comment parent id]]></string>
 	<string name="_Please enter n1-n2 characters"><![CDATA[Please enter {0}-{1} characters]]></string>
 	<string name="_Remove friend"><![CDATA[Remove friend]]></string>
 	<string name="_Friend was removed"><![CDATA[Friend was removed]]></string>
@@ -3199,7 +3198,7 @@ More info about URI DNSBL: <br />
 	<string name="_sys_adm_fld_dnsbl_recheck"><![CDATA[Recheck IP]]></string>
 	<string name="_sys_adm_fld_dnsbluri_recheck"><![CDATA[Recheck Domain]]></string>
 	<string name="_sys_sucess_result"><![CDATA[Data has been succesfully submited.]]></string>
-	<string name="_sys_spam_detected"><![CDATA[Sorry, it looks like you are trying to submit spam, if you believe that it is not spam please submit false positive report here: %s]]></string>
+	<string name="_sys_spam_detected"><![CDATA[Sorry, it looks like you are trying to submit spam, if you believe that it is not spam please submit false positive report here: {0}]]></string>
 	<string name="_sys_adm_enabled"><![CDATA[Enabled]]></string>
 	<string name="_sys_adm_disabled"><![CDATA[Disabled]]></string>
 	<string name="_sys_adm_akismet_key_valid"><![CDATA[Your Akismet key is valid.]]></string>
@@ -3400,6 +3399,7 @@ More info about URI DNSBL: <br />
     <string name="_sys_form_forgot_password"><![CDATA[Forgot Password]]></string>
     <string name="_sys_form_confirm_email"><![CDATA[Email Confirmation]]></string>
     <string name="_sys_form_unsubscribe"><![CDATA[Unsubscribe]]></string>
+    <string name="_sys_form_comment"><![CDATA[Comment]]></string>
 
     <string name="_sys_form_display_login"><![CDATA[Login]]></string>
     <string name="_sys_form_display_account_create"><![CDATA[Create Account]]></string>
@@ -3411,6 +3411,9 @@ More info about URI DNSBL: <br />
     <string name="_sys_form_display_confirm_email"><![CDATA[Email Confirmation]]></string>
     <string name="_sys_form_display_unsubscribe_updates"><![CDATA[Unsubscribe From Updates]]></string>
     <string name="_sys_form_display_unsubscribe_news"><![CDATA[Unsubscribe From Newsletters]]></string>
+    <string name="_sys_form_display_comment_post"><![CDATA[Comment From Post]]></string>
+    <string name="_sys_form_display_comment_edit"><![CDATA[Comment From Edit]]></string>
+    
 
     <string name="_sys_form_login_input_caption_system_role"><![CDATA[Role]]></string>
     <string name="_sys_form_login_input_caption_system_relocate"><![CDATA[Relocate]]></string>
@@ -3475,7 +3478,21 @@ More info about URI DNSBL: <br />
     <string name="_sys_form_unsubscribe_input_caption_system_receive_news"><![CDATA[Receive Newsletters]]></string>
     <string name="_sys_form_unsubscribe_input_receive_news"><![CDATA[Receive Newsletters]]></string>    
     <string name="_sys_form_unsubscribe_input_caption_system_do_submit"><![CDATA[Submit]]></string>
-    <string name="_sys_form_unsubscribe_input_submit"><![CDATA[Submit]]></string>    
+    <string name="_sys_form_unsubscribe_input_submit"><![CDATA[Submit]]></string>
+    
+    <string name="_sys_form_comment_input_caption_system_sys"><![CDATA[Object Type]]></string>
+    <string name="_sys_form_comment_input_caption_system_id"><![CDATA[Object ID]]></string>
+    <string name="_sys_form_comment_input_caption_system_action"><![CDATA[Action]]></string>
+    <string name="_sys_form_comment_input_caption_system_cmt_id"><![CDATA[Comment ID]]></string>
+    <string name="_sys_form_comment_input_caption_system_cmt_parent_id"><![CDATA[Parent ID]]></string>
+    <string name="_sys_form_comment_input_caption_system_cmt_text"><![CDATA[Text]]></string>
+    <string name="_sys_form_comment_input_caption_system_cmt_image"><![CDATA[Image]]></string>
+    <string name="_sys_form_comment_input_caption_system_cmt_submit"><![CDATA[Submit]]></string>
+    <string name="_sys_form_comment_input_submit"><![CDATA[Submit]]></string>
+    <string name=""><![CDATA[]]></string>
+    <string name=""><![CDATA[]]></string>
+    <string name=""><![CDATA[]]></string>
+    <string name=""><![CDATA[]]></string>
 
     <string name="_sys_page_lang_block_about"><![CDATA[This site is powered by BoonEx Dolphin. The rest is a mystery.]]></string>
 

+ 1 - 2
modules/boonex/russian/data/langs/system.xml

@@ -3071,7 +3071,6 @@ Without doing that you won't be submitted to our database.</p>
 	<string name="_edit_profile_info"><![CDATA[Edit profile info]]></string>
 	<string name="_edit_profile_privacy"><![CDATA[Edit profile privacy]]></string>
 	<string name="_edit_profile_privacy_save"><![CDATA[Save]]></string>
-	<string name="_bad comment parent id"><![CDATA[bad comment parent id]]></string>
 	<string name="_Please enter 3-2048 characters"><![CDATA[Please enter 3-2048 characters]]></string>
 	<string name="_You need to select the mood"><![CDATA[You need to select the mood]]></string>
 	<string name="_Remove friend"><![CDATA[Remove friend]]></string>
@@ -3118,7 +3117,7 @@ More info about URI DNSBL: <br />
 	<string name="_sys_adm_fld_dnsbl_recheck"><![CDATA[Recheck IP]]></string>
 	<string name="_sys_adm_fld_dnsbluri_recheck"><![CDATA[Recheck Domain]]></string>
 	<string name="_sys_sucess_result"><![CDATA[Data has been succesfully submited.]]></string>
-	<string name="_sys_spam_detected"><![CDATA[Sorry, it looks like you are trying to submit spam, if you believe that it is not spam please submit false positive report here: %s]]></string>
+	<string name="_sys_spam_detected"><![CDATA[Sorry, it looks like you are trying to submit spam, if you believe that it is not spam please submit false positive report here: {0}]]></string>
 	<string name="_sys_adm_enabled"><![CDATA[Enabled]]></string>
 	<string name="_sys_adm_disabled"><![CDATA[Disabled]]></string>
 	<string name="_sys_adm_akismet_key_valid"><![CDATA[Your Akismet key is valid.]]></string>

+ 21 - 0
modules/boonex/uni/data/template/system/scripts/BxTemplCmtsUploaderSimple.php

@@ -0,0 +1,21 @@
+<?php defined('BX_DOL') or die('hack attempt');
+/**
+ * Copyright (c) BoonEx Pty Limited - http://www.boonex.com/
+ * CC-BY License - http://creativecommons.org/licenses/by/3.0/
+ *
+ * @defgroup    DolphinCore Dolphin Core
+ * @{
+ */
+
+bx_import ('BxBaseCmtsUploaderSimple');
+
+/**
+ * @see BxDolUploader
+ */
+class BxTemplCmtsUploaderSimple extends BxBaseCmtsUploaderSimple {
+    function __construct($aObject, $sStorageObject, $sUniqId) {
+        parent::__construct($aObject, $sStorageObject, $sUniqId);
+    }
+}
+
+/** @} */

+ 2 - 3
samples/comments.php

@@ -15,7 +15,7 @@
 /**
  * DB Queries.
 
-INSERT INTO `sys_objects_cmts` (`ID`, `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` (`ID`, `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
 (1, 'sample', 'sample_cmts', 'sample_cmts_track', 1, 5000, 1000, 1, 5, 3, 'tail', 1, 'bottom', 1, 1, 1, -3, 1, 'cmt', 'samples/comments.php', 'sample_cmts_trigger', 'id', 'title', 'comments', '', '');
 
 CREATE TABLE IF NOT EXISTS `sample_cmts` (
@@ -26,10 +26,9 @@ CREATE TABLE IF NOT EXISTS `sample_cmts` (
   `cmt_author_id` int(10) unsigned NOT NULL DEFAULT '0',
   `cmt_level` int(11) NOT NULL DEFAULT '0',
   `cmt_text` text NOT NULL,
-  `cmt_mood` tinyint(4) NOT NULL DEFAULT '0',
   `cmt_rate` int(11) NOT NULL DEFAULT '0',
   `cmt_rate_count` int(11) NOT NULL DEFAULT '0',
-  `cmt_time` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
+  `cmt_time` int(11) unsigned NOT NULL DEFAULT '0',
   `cmt_replies` int(11) NOT NULL DEFAULT '0',
   PRIMARY KEY (`cmt_id`),
   KEY `cmt_object_id` (`cmt_object_id`,`cmt_parent_id`)

+ 1 - 1
studio/template/scripts/BxBaseStudioFormsFields.php

@@ -260,7 +260,7 @@ class BxBaseStudioFormsFields extends BxDolStudioFormsFields {
         }
         else {
             bx_import('BxTemplStudioFunctions');
-            $sContent = BxTemplStudioFunctions::getInstance()->popupBox('adm-form-field-show-to-popup', _t('_adm_form_txt_field_show_to_popup', _t($aField['caption'])), $this->_oTemplate->parseHtmlByName('form_add_field.html', array(
+            $sContent = BxTemplStudioFunctions::getInstance()->popupBox('adm-form-field-show-to-popup', _t('_adm_form_txt_field_show_to_popup', _t($aField['caption_system'])), $this->_oTemplate->parseHtmlByName('form_add_field.html', array(
                 'form_id' => $aForm['form_attrs']['id'],
                 'form' => $oForm->getCode(true),
                 'object' => $this->_sObject,

+ 1 - 1
studio/template/scripts/BxBaseStudioPermissionsLevels.php

@@ -368,7 +368,7 @@ class BxBaseStudioPermissionsLevels extends BxDolStudioPermissionsLevels {
             if(!empty($_FILES['Icon']['tmp_name'])) {
                 bx_import('BxDolStorage');
                 $oStorage = BxDolStorage::getObjectInstance(BX_DOL_STORAGE_OBJ_IMAGES);
-    
+
                 if(is_numeric($aLevel['icon']) && (int)$aLevel['icon'] != 0 && !$oStorage->deleteFile((int)$aLevel['icon'], 0)) {
                     $this->_echoResultJson(array('msg' => _t('_adm_prm_err_level_icon_remove')), true);
                     return;

+ 2 - 2
template/comment.html

@@ -18,7 +18,7 @@
 				<bx_if:show_reply_to>
 					<span class="bx-def-font-grayed"><bx_text:_in_reply_to />&nbsp;</span><a href="__par_cmt_link__">__par_cmt_author__</a><span class="bullet">&#183;</span>
 				</bx_if:show_reply_to>
-				<a class="__style_prefix__-ago" href="__view_link__">__ago__</a>
+				<a class="__style_prefix__-ago" href="__view_link__" rel="nofollow">__ago__</a>
 				<span class="__style_prefix__-points-wrp" <bx_if:hide_rate_count>style="display:none;"</bx_if:hide_rate_count>>
 					<span class="bullet">&#183;</span><a class="__style_prefix__-points" href="javascript:void(0)" onclick="__js_object__.togglePlusedByPopup(this, __id__); return false;" title="<bx_text:_Plused_by_popup />">__points__</a>
 				</span>
@@ -28,7 +28,7 @@
 	<div class="__style_prefix__-cont bx-def-margin-sec-top bx-def-color-bg-box bx-def-border bx-def-round-corners bx-def-shadow">
 		<div class="__style_prefix__-cont-cnt bx-def-padding-leftright bx-def-padding-sec-topbottom">
 			<div class="__style_prefix__-body bx-def-margin-thd-topbottom">
-				__text__<bx_if:show_more><span class="__style_prefix__-body-see-more">... <a class="bx-def-font-small" href="javascript:void(0)" onclick="__js_object__.seeMore(this);"><bx_text:_see_more /></a></span><span style="display:none;"> __text_more__</span></bx_if:show_more>
+				__text__<bx_if:show_more><span class="__style_prefix__-body-see-more">... <a class="bx-def-font-small" href="javascript:void(0)" onclick="__js_object__.showMore(this);"><bx_text:_see_more /></a></span><span style="display:none;"> __text_more__</span></bx_if:show_more>
 			</div>
 		</div>
 	</div>

+ 1 - 1
template/comment_more.html

@@ -1,6 +1,6 @@
 <li class="__style_prefix__-more<bx_if:is_root>-root bx-def-margin-top</bx_if:is_root>  bx-def-margin-bottom">
 	<div class="__style_prefix__-more-cont">
 		<div class="__style_prefix__-more-line bx-def-hr"></div>
-		<a class="<bx_if:is_button>bx-btn</bx_if:is_button>" href="javascript:void(0)" onclick="javascript:__js_object__.cmtMore(this, __parent_id__, __start__, __per_view__)">__title__</a>
+		<a class="<bx_if:is_button>bx-btn</bx_if:is_button>" href="javascript:void(0)" onclick="javascript:__js_object__.cmtLoad(this, __parent_id__, __start__, __per_view__)">__title__</a>
 	</div>
 </li>

+ 5 - 0
template/comment_reply_box.html

@@ -18,6 +18,11 @@
 	<div class="__style_prefix__-cont __style_prefix__-post-reply bx-def-margin-sec-top bx-def-color-bg-box bx-def-border bx-def-round-corners bx-def-shadow">
 		<div class="__style_prefix__-cont-cnt bx-def-padding-leftright bx-def-padding-sec-topbottom">
 			<div class="__style_prefix__-body bx-def-margin-thd-topbottom">__form__</div>
+			<script type="text/javascript">
+            $(document).ready(function () {
+            	__js_object__.cmtInitFormPost("__form_id__");
+            });
+        </script>
 		</div>
 	</div>
 </div>

+ 14 - 0
template/comments_uploader_bs.html

@@ -0,0 +1,14 @@
+    <a href="javascript:void(0);" onclick="__uploader_instance_name__.showUploaderForm();" class="bx-btn bx-btn-small 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>

+ 9 - 0
template/comments_uploader_nfw.html

@@ -0,0 +1,9 @@
+<div id="bx-uploader-file-{file_id}" class="cmts-uploader-file bx-def-margin-sec-top bx-def-margin-sec-left-auto">
+    <div class="cmts-uploader-file-preview bx-def-border">
+        <img src="{file_icon}" />
+    </div>
+    <div class="cmts-uploader-file-actions bx-def-margin-thd-top bx-clearfix">
+    	<a class="bx-btn bx-btn-small" href="javascript:void(0);" onclick="{js_instance_name}.deleteGhost('{file_id}')"><bx_text:_Delete /></a>
+    	__nested_form__
+    </div>
+</div>

+ 18 - 0
template/css/cmts.css

@@ -195,6 +195,7 @@
 	}
     div.cmt-comment-manage {
     	position: relative;
+    	min-width: 150px; 
     	text-align: left;
     }
 
@@ -231,9 +232,26 @@
 	div.cmt-post-reply {
         position: relative;
     }
+
+    /*--- Add Comment/Reply Form Styles ---*/
     form.cmt-post-reply .bx-form-input-textarea {
 		height: 64px;
     }
     form.cmt-post-reply .bx-form-input-submit {
     	text-transform: uppercase;
+    }
+    form.cmt-post-reply .bx-form-input-files-uploaders {
+		text-align: right;
+    }
+
+    a.cmts-uploader-button {
+		
+    }
+    div.cmts-uploader-file {
+		position: relative;
+    	float: left;
+    }
+    div.cmts-uploader-file-preview {
+		width: 100px;
+    	height: 100px;
     }

+ 1 - 1
template/form_field_uploader.html

@@ -6,7 +6,7 @@
 __info__
 __error__
 <div id="__id_container_errors__" class="bx-form-input-files-errors"></div>
-<div id="__id_container_result__" class="bx-form-input-files-result bx-def-margin-sec-top"></div>
+<div id="__id_container_result__" class="bx-form-input-files-result bx-clearfix"></div>
 <script>
     $(document).ready(function(){
         if (__is_init_ghosts__)

+ 23 - 0
template/scripts/BxBaseCmtsUploaderSimple.php

@@ -0,0 +1,23 @@
+<?php defined('BX_DOL') or die('hack attempt');
+/**
+ * Copyright (c) BoonEx Pty Limited - http://www.boonex.com/
+ * CC-BY License - http://creativecommons.org/licenses/by/3.0/
+ *
+ * @defgroup    DolphinCore Dolphin Core
+ * @{
+ */
+
+bx_import ('BxTemplUploaderSimple');
+
+/**
+ * Upload files using standard HTML forms.
+ * @see BxBaseUploaderSimple, BxDolUploader
+ */
+class BxBaseCmtsUploaderSimple extends BxTemplUploaderSimple {
+    function __construct ($aObject, $sStorageObject, $sUniqId) {
+        parent::__construct($aObject, $sStorageObject, $sUniqId);
+        $this->_sButtonTemplate = 'comments_uploader_bs.html';
+    }
+}
+
+/** @} */

+ 169 - 77
template/scripts/BxBaseCmtsView.php

@@ -45,7 +45,7 @@ class BxBaseCmtsView extends BxDolCmts {
      */
     function getExtraJs ()
     {
-        BxDolTemplate::getInstance()->addJs(array('common_anim.js', 'BxDolCmts.js'));
+        BxDolTemplate::getInstance()->addJs(array('common_anim.js', 'jquery.form.js', 'BxDolCmts.js'));
     }
 
 	/**
@@ -69,13 +69,7 @@ class BxBaseCmtsView extends BxDolCmts {
                     iObjId: '" . $this->getId () . "',
                     sPostFormPosition: '" . $this->_aSystem['post_form_position'] . "',
     				sBrowseType: '" . $this->_sBrowseType . "',
-    				sDisplayType: '" . $this->_sDisplayType . "'});
-                " . $this->_sJsObjName . ".oCmtElements = {";
-        for (reset($this->_aPostElements); list($k,$r) = each ($this->_aPostElements); ) {
-            $ret .= "\n'$k' : { 'reg' : '{$r['reg']}', 'msg' : \"". bx_js_string(trim($r['msg'])) . "\" },";
-        }
-        $ret = substr($ret, 0, -1);
-        $ret .= "\n};\n";
+    				sDisplayType: '" . $this->_sDisplayType . "'});\n";
         $ret .= "</script>";
 
         $this->getExtraJs();
@@ -107,8 +101,8 @@ class BxBaseCmtsView extends BxDolCmts {
 			),
 			'controls' => $this->_getControlsBox(),
     		'comments' => $sCmts,
-    		'post_form_top' => $this->_getPostReplyBox($aBp, array('type' => $this->_sDisplayType, 'position' => BX_CMT_PFP_TOP)),
-			'post_form_bottom'  => $this->_getPostReplyBox($aBp, array('type' => $this->_sDisplayType, 'position' => BX_CMT_PFP_BOTTOM)),
+    		'post_form_top' => $this->getFormBoxPost($aBp, array('type' => $this->_sDisplayType, 'position' => BX_CMT_PFP_TOP)),
+			'post_form_bottom'  => $this->getFormBoxPost($aBp, array('type' => $this->_sDisplayType, 'position' => BX_CMT_PFP_BOTTOM)),
     		'script' => $this->getScript()
     	));
     }
@@ -275,14 +269,24 @@ class BxBaseCmtsView extends BxDolCmts {
         ));
     }
 
-    function getFormBox($aBp = array(), $aDp = array())
+    function getFormBoxPost($aBp = array(), $aDp = array())
+    {
+        return $this->_getFormBox(BX_CMT_ACTION_POST, $aBp, $aDp);
+    }
+
+	function getFormBoxEdit($aBp = array(), $aDp = array())
     {
-        return $this->_getPostReplyBox($aBp, $aDp);
+        return $this->_getFormBox(BX_CMT_ACTION_EDIT, $aBp, $aDp);
+    }
+
+	function getFormPost($iCmtParentId = 0)
+	{
+        return $this->_getFormPost($iCmtParentId);
     }
 
-	function getForm($iCmtParentId, $sText, $sFunction)
+	function getFormEdit($aCmt)
 	{
-        return $this->_getPostReplyForm($iCmtParentId, $sText, $sFunction);
+        return $this->_getFormEdit($aCmt);
     }
 
     function getPlusedBy($iCmtId)
@@ -316,7 +320,7 @@ class BxBaseCmtsView extends BxDolCmts {
     /**
      * private functions
      */
-    function _getControlsBox()
+    protected function _getControlsBox()
     {
     	$oTemplate = BxDolTemplate::getInstance();
 
@@ -365,7 +369,7 @@ class BxBaseCmtsView extends BxDolCmts {
 		));
     }
 
-	function _getActionsBox(&$a, $aDp = array())
+	protected function _getActionsBox(&$a, $aDp = array())
     {
     	$oTemplate = BxDolTemplate::getInstance();
 
@@ -376,15 +380,16 @@ class BxBaseCmtsView extends BxDolCmts {
 		$sManagePopupId = $sManagePopupText = '';
         if($isEditAllowedPermanently || $isRemoveAllowedPermanently) {
 			$aMenu = array(
-				array('name' => 'cmt-edit', 'icon' => '', 'onclick' => $this->_sJsObjName . ".cmtEdit(this, " . $a['cmt_id'] . ")", 'title' => _t('_Edit')),
-				array('name' => 'cmt-delete', 'icon' => '', 'onclick' => $this->_sJsObjName . ".cmtRemove(this, " . $a['cmt_id'] . ")", 'title' => _t('_Delete')),
+				array('name' => 'cmt-edit', 'icon' => 'pencil', 'onclick' => $this->_sJsObjName . ".cmtEdit(this, " . $a['cmt_id'] . ")", 'title' => _t('_Edit')),
+				array('name' => 'cmt-delete', 'icon' => 'remove', 'onclick' => $this->_sJsObjName . ".cmtRemove(this, " . $a['cmt_id'] . ")", 'title' => _t('_Delete')),
 			);
 
         	bx_import('BxTemplStudioMenu');
-        	$oMenu = new BxTemplStudioMenu(array('template' => 'menu_vertical_lite.html', 'menu_items' => $aMenu));
+        	$oMenu = new BxTemplStudioMenu(array('template' => 'menu_vertical.html', 'menu_items' => $aMenu));
 
         	bx_import('BxTemplStudioFunctions');
 	        $sManagePopupText = BxTemplStudioFunctions::getInstance()->transBox($oTemplate->parseHtmlByName('comment_manage.html', array(
+	        	'style_prefix' => $this->_sStylePrefix,
 	        	'content' => $oMenu->getCode()
 	        )));
         }
@@ -438,7 +443,7 @@ class BxBaseCmtsView extends BxDolCmts {
         ));
     }
 
-    function _getPostReplyBox($aBp, $aDp)
+    protected function _getFormBox($sType, $aBp, $aDp)
     {
     	$iCmtParentId = isset($aBp['parent_id']) ? (int)$aBp['parent_id'] : 0;
     	$sPosition = isset($aDp['position']) ? $aDp['position'] : '';
@@ -452,8 +457,12 @@ class BxBaseCmtsView extends BxDolCmts {
 		if(!empty($sPosition) && $sPositionSystem != BX_CMT_PFP_BOTH && $sPositionSystem != $sPosition)
 			return '';
 
+		$sMethod = '_getForm' . ucfirst($sType);
+		$aForm = $this->$sMethod($iCmtParentId);
+
 		$bAuthorIcon = !empty($sAuthorIcon);
     	return BxDolTemplate::getInstance()->parseHtmlByName('comment_reply_box.html', array(
+    		'js_object' => $this->_sJsObjName,
     		'style_prefix' => $this->_sStylePrefix,
     		'bx_if:show_class' => array(
     			'condition' => !empty($sPosition),
@@ -484,56 +493,145 @@ class BxBaseCmtsView extends BxDolCmts {
         			'author_name' => $sAuthorName
         		)
         	),
-			'form' => $this->_getPostReplyForm($iCmtParentId)
+			'form' => $aForm['form'],
+        	'form_id' => $aForm['form_id'],
     	));
     }
 
-    function _getPostReplyForm($iCmtParentId = 0, $sText = "", $sFunction = "cmtSubmit(this)")
+    protected function _getFormPost($iCmtParentId = 0)
     {
-    	$aForm = array(
-			'form_attrs' => array(
-				'name' => 'cmt-post-reply-' . $this->_sSystem,
-				'method' => 'post',
-    			'onsubmit' => $this->_sJsObjName . '.' . $sFunction . '; return false;',
-    			'class' => 'cmt-post-reply'
-			 ), 
-			'params' => array (
-				'csrf' => array(
-					'disable' => true,
-				)
-			),
-			'inputs' => array(
-				'CmtParent' => array(
-					'type' => 'hidden',
-					'name' => 'CmtParent',
-					'value' => $iCmtParentId
-				),
-				'CmtType' => array(
-					'type' => 'hidden',
-					'name' => 'CmtType',
-					'value' => 'text'
-				),
-				'CmtText' => array(
-					'type' => 'textarea',
-					'name' => 'CmtText',
-					'caption' => '',
-					'value' => $sText,
-					'required' => false,
-				),
-				'CmtSubmit' => array(
-					'type' => 'submit', 
-					'name' => 'CmtSubmit', 
-					'value' => _t('_Submit_Comment')
-				)
-			)
-		);
+    	$oForm = $this->_getFormObject(BX_CMT_ACTION_POST, $iCmtParentId);
+        $oForm->aInputs['cmt_parent_id']['value'] = $iCmtParentId;
+    	$oForm->initChecker();
+
+        if($oForm->isSubmittedAndValid()) {
+        	$iCmtAuthorId = $this->_getAuthorId();
+        	$iCmtParentId = $oForm->getCleanValue('cmt_parent_id');
+
+        	$sCmtText = $oForm->getCleanValue('cmt_text');
+	        if($this->_isSpam($sCmtText))
+	            return array('msg' => _t('_sys_spam_detected', BX_DOL_URL_ROOT . 'contact.php'));
+
+			$sCmtText = $this->_prepareTextForSave ($sCmtText);
+			$oForm->setSubmittedValue('cmt_text', $sCmtText, $oForm->aFormAttrs['method']);
+
+	        $iLevel = 0;
+	    	$iCmtVisualParentId = 0;
+	    	if((int)$iCmtParentId > 0) {
+	    		$aParent = $this->getCommentRow($iCmtParentId);
+
+	    		$iLevel = (int)$aParent['cmt_level'] + 1;
+	    		$iCmtVisualParentId = $iLevel > $this->getMaxLevel() ? $aParent['cmt_vparent_id'] : $iCmtParentId;
+	    	}
+
+			$iCmtId = (int)$oForm->insert(array('cmt_vparent_id' => $iCmtVisualParentId, 'cmt_object_id' => $this->_iId, 'cmt_author_id' => $iCmtAuthorId, 'cmt_level' => $iLevel, 'cmt_time' => mktime()));
+			if($iCmtId != 0) {
+				$aImages = $oForm->getCleanValue('cmt_image');
+				if(!empty($aImages) || is_array($aImages))
+					foreach($aImages as $iImage)
+						$this->_oQuery->saveImages($this->_aSystem['system_id'], $iCmtId, $iImage);
+
+				if($iCmtParentId) 
+        			$this->_oQuery->updateRepliesCount($iCmtParentId, 1);
+
+				$this->_triggerComment();
+
+		        $this->isPostReplyAllowed(true);
+
+		        bx_import('BxDolAlerts');
+		        $oZ = new BxDolAlerts($this->_sSystem, 'commentPost', $this->getId(), $iCmtAuthorId, array('comment_id' => $iCmtId, 'comment_author_id' => $iCmtAuthorId));
+		        $oZ->alert();
+
+		        return array('id' => $iCmtId);
+			}
+
+			return array('msg' => _t('_cmt_err_cannot_perform_action'));
+        }
+
+        return array('form' => $oForm->getCode(), 'form_id' => $oForm->id);
+    }
+
+	protected function _getFormEdit($iCmtId)
+    {
+	    $aCmt = $this->_oQuery->getCommentSimple ($this->getId(), $iCmtId);
+        if(!$aCmt)
+        	return array('msg' => _t('_No such comment'));
+
+		$iCmtAuthorId = $this->_getAuthorId();
+        if(!$this->isEditAllowedAll() && ($aCmt['cmt_author_id'] != $iCmtAuthorId || !$this->isEditAllowed()))
+        	return array('msg' => $aCmt['cmt_author_id'] == $iCmtAuthorId && !$this->isEditAllowed() ? strip_tags($this->msgErrEditAllowed()) : _t('_Access denied'));
+
+		$oForm = $this->_getFormObject(BX_CMT_ACTION_EDIT, $aCmt['cmt_id']);
+
+		$oForm->initChecker($aCmt);
+		if($oForm->isSubmittedAndValid()) {
+			$sCmtText = $oForm->getCleanValue('cmt_text');
+	        if($this->_isSpam($sCmtText))
+	            return array('msg' => _t('_sys_spam_detected', BX_DOL_URL_ROOT . 'contact.php'));
+
+			$sCmtText = $this->_prepareTextForSave ($sCmtText);
+			$oForm->setSubmittedValue('cmt_text', $sCmtText, $oForm->aFormAttrs['method']);
 
-		bx_import('BxTemplFormView');
-		$oForm = new BxTemplFormView ($aForm);
-		return $oForm->getCode();
+	        if($oForm->update($iCmtId)) {
+				if ($aCmt['cmt_author_id'] == $iCmtAuthorId)
+               		$this->isEditAllowed(true);
+
+	            bx_import('BxDolAlerts');
+	            $oZ = new BxDolAlerts($this->_sSystem, 'commentUpdated', $this->getId(), $iCmtAuthorId, array('comment_id' => $aCmt['cmt_id'], 'comment_author_id' => $aCmt['cmt_author_id']));
+	            $oZ->alert();
+
+	            return array('id' => $iCmtId, 'text' => $sCmtText);
+	        }
+
+	        return array('msg' => _t('_cmt_err_cannot_perform_action'));
+		}
+
+		return array('form' => $oForm->getCode(), 'form_id' => $oForm->id);
     }
 
-	function _getMoreLink($sCmts, $aBp = array(), $aDp = array())
+	protected function _getFormObject($sAction, $iId)
+    {
+    	$sActionCap = ucfirst($sAction);
+    	$sDisplayName = '_sFormDisplay' . $sActionCap;
+
+    	bx_import('BxDolForm');
+        $oForm = BxDolForm::getObjectInstance($this->_sFormObject, $this->$sDisplayName);
+        $oForm->setId(sprintf($oForm->aFormAttrs['id'], $sAction, $this->_sSystem, $iId));
+        $oForm->setName(sprintf($oForm->aFormAttrs['name'], $sAction, $this->_sSystem, $iId));
+        $oForm->aParams['db']['table'] = $this->_aSystem['table_cmts'];
+        $oForm->aInputs['sys']['value'] = $this->_sSystem;
+        $oForm->aInputs['id']['value'] = $this->_iId;
+        $oForm->aInputs['action']['value'] = 'Submit' . $sActionCap . 'Form';
+
+        $aFormNested = array(
+        	'params' =>array(
+        		'nested_form_template' => 'comments_uploader_nfw.html'
+        	),
+	        'inputs' => array(),
+	    );
+
+	    bx_import('BxDolFormNested');
+	    $oFormNested = new BxDolFormNested('cmt_image', $aFormNested, 'cmt_submit');
+
+        $oForm->aInputs['cmt_image']['storage_object'] = $this->_sStorageObject;
+        $oForm->aInputs['cmt_image']['images_transcoder'] = $this->_sTranscoderPreview;
+        $oForm->aInputs['cmt_image']['uploaders'] = array('sys_simple_cmts');
+        $oForm->aInputs['cmt_image']['upload_buttons_titles'] = array('Simple' => 'camera');
+        $oForm->aInputs['cmt_image']['multiple'] = true;
+        $oForm->aInputs['cmt_image']['ghost_template'] = $oFormNested;
+
+        if(isset($oForm->aInputs['cmt_text'])) {
+        	$iCmtTextMin = (int)$this->_aSystem['chars_post_min'];
+			$iCmtTextMax = (int)$this->_aSystem['chars_post_max'];
+
+        	$oForm->aInputs['cmt_text']['checker']['params'] = array($iCmtTextMin, $iCmtTextMax);
+        	$oForm->aInputs['cmt_text']['checker']['error'] = _t('_Please enter n1-n2 characters', $iCmtTextMin, $iCmtTextMax);
+        }
+
+        return $oForm;
+    }
+
+	protected function _getMoreLink($sCmts, $aBp = array(), $aDp = array())
     {
     	$iStart = $iPerView = 0;
     	switch($aBp['type']) {
@@ -597,22 +695,16 @@ class BxBaseCmtsView extends BxDolCmts {
     	return $sCmts;
     }
 
-    function _getLevelGap($a, $aDp = array())
-    {
-    	if($aDp['type'] != BX_CMT_DISPLAY_THREADED || !is_array($a) || !isset($a['cmt_level']))
-    		return 0;
-
-    	return 84 * ((int)$a['cmt_level'] <= $this->_iDpMaxLevel ? (int)$a['cmt_level'] : $this->_iDpMaxLevel);
-    }
+	protected function _echoResultJson($a, $isAutoWrapForFormFileSubmit = false) {
 
-    function _getLevelGapByParent($iParentId, $aDp = array()) {
-		if($aDp['type'] != BX_CMT_DISPLAY_THREADED || (int)$iParentId == 0)
-    		return 0;
+        header('Content-type: text/html; charset=utf-8');    
 
-		$a = $this->getCommentRow($iParentId);
-		if(isset($a['cmt_level']))
-			$a['cmt_level'] += 1;
+        require_once(BX_DIRECTORY_PATH_PLUGINS . 'Services_JSON.php');
 
-		return $this->_getLevelGap($a, $aDp);
+        $oParser = new Services_JSON();
+        $s = $oParser->encode($a);
+        if ($isAutoWrapForFormFileSubmit && !empty($_FILES)) 
+            $s = '<textarea>' . $s . '</textarea>'; // http://jquery.malsup.com/form/#file-upload
+        echo $s;
     }
 }

+ 1 - 1
template/uploader_nested_form_wrapper.html

@@ -5,7 +5,7 @@
     <div class="bx-uploader-ghost-form ">
         <div class="bx-uploader-ghost-form-filename bx-def-padding-top bx-def-padding-bottom bx-def-font-grayed">{file_name}</div>
         __nested_form__
-        <div class="bx-uploader-ghost-form-actions bx-def-margin-top"><a class="bx-btn bx-btn-small" href="javascript:void(0);" onclick="{js_instance_name}.deleteGhost('{file_id}')"><bx_text:_Delete /></a></div>
+        <div class="bx-uploader-ghost-form-actions bx-def-margin-top bx-clearfix"><a class="bx-btn bx-btn-small" href="javascript:void(0);" onclick="{js_instance_name}.deleteGhost('{file_id}')"><bx_text:_Delete /></a></div>
     </div>
     <div class="bx-clear"></div>
 </div>