Sfoglia il codice sorgente

Ticket #194: Report engine.

AntonLV 10 anni fa
parent
commit
e5fc3ecd34

+ 234 - 0
inc/classes/BxDolReport.php

@@ -0,0 +1,234 @@
+<?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    TridentCore Trident Core
+ * @{
+ */
+
+bx_import('BxDolAcl');
+
+define('BX_DOL_REPORT_USAGE_BLOCK', 'block');
+define('BX_DOL_REPORT_USAGE_INLINE', 'inline');
+define('BX_DOL_REPORT_USAGE_DEFAULT', BX_DOL_REPORT_USAGE_BLOCK);
+
+/**
+ * @page objects
+ * @section reports Reports
+ * @ref BxDolReport
+ */
+
+/**
+ * Report any content
+ *
+ * Related classes:
+ * - BxDolReportQuery - report database queries
+ * - BxBaseReport - report base representation
+ * - BxTemplReport - custom template representation
+ *
+ * AJAX vote for any content. Stars and Plus based representations are supported.
+ *
+ * To add vote section to your feature you need to add a record to 'sys_objects_vote' table:
+ *
+ * - ID - autoincremented id for internal usage
+ * - Name - your unique module name, with vendor prefix, lowercase and spaces are underscored
+ * - TableMain - table name where summary votigs are stored
+ * - TableTrack - table name where each vote is stored
+ * - PostTimeout - number of seconds to not allow duplicate vote
+ * - MinValue - min vote value, 1 by default
+ * - MaxValue - max vote value, 5 by default
+ * - IsUndo - is Undo enabled for Plus based votes
+ * - IsOn - is this vote object enabled
+ * - TriggerTable - table to be updated upon each vote
+ * - TriggerFieldId - TriggerTable table field with unique record id, primary key
+ * - TriggerFieldRate - TriggerTable table field with average rate
+ * - TriggerFieldRateCount - TriggerTable table field with votes count
+ * - ClassName - your custom class name, if you overrride default class
+ * - ClassFile - your custom class path
+ *
+ * You can refer to BoonEx modules for sample record in this table.
+ *
+ *
+ *
+ * @section example Example of usage:
+ * To get Star based vote you need to have different values for MinValue and MaxValue (for example 1 and 5)
+ * and IsUndo should be equal to 0. To get Plus(Like) based vote you need to have equal values
+ * for MinValue and MaxValue (for example 1) and IsUndo should be equal to 1. After filling the other
+ * paramenters in the table you can show vote in any place, using the following code:
+ * @code
+ * $o = BxDolVote::getObjectInstance('system object name', $iYourEntryId);
+ * if (!$o->isEnabled()) return '';
+ *     echo $o->getElementBlock();
+ * @endcode
+ *
+ *
+ * @section acl Memberships/ACL:
+ * - vote
+ *
+ *
+ *
+ * @section alerts Alerts:
+ * Alerts type/unit - every module has own type/unit, it equals to ObjectName.
+ * The following alerts are rised:
+ *
+ * - rate - comment was posted
+ *      - $iObjectId - entry id
+ *      - $iSenderId - rater user id
+ *      - $aExtra['rate'] - rate
+ *
+ */
+
+class BxDolReport extends BxDolObject
+{
+	protected $_oTemplate;
+
+	protected $_sFormObject;
+    protected $_sFormDisplayPost;
+
+	protected $_aTypes;
+
+    public function __construct($sSystem, $iId, $iInit = true, $oTemplate = false)
+    {
+        parent::__construct($sSystem, $iId, $iInit);
+        if(empty($this->_sSystem))
+            return;
+
+        $this->_oQuery = new BxDolReportQuery($this);
+
+        if ($oTemplate)
+            $this->_oTemplate = $oTemplate;
+        else
+            $this->_oTemplate = BxDolTemplate::getInstance();
+
+		$this->_sFormObject = 'sys_report';
+		$this->_sFormDisplayPost = 'sys_report_post';
+
+		$this->_aTypes = array('spam', 'scam', 'fraud', 'nude', 'other');
+    }
+
+    /**
+     * get reports object instanse
+     * @param $sSys report object name
+     * @param $iId associated content id, where report is available
+     * @param $iInit perform initialization
+     * @return null on error, or ready to use class instance
+     */
+    public static function getObjectInstance($sSys, $iId, $iInit = true, $oTemplate = false)
+    {
+        if(isset($GLOBALS['bxDolClasses']['BxDolReport!' . $sSys . $iId]))
+            return $GLOBALS['bxDolClasses']['BxDolReport!' . $sSys . $iId];
+
+        $aSystems = self::getSystems();
+        if(!isset($aSystems[$sSys]))
+            return null;
+
+        $sClassName = 'BxTemplReport';
+        if(!empty($aSystems[$sSys]['class_name'])) {
+            $sClassName = $aSystems[$sSys]['class_name'];
+            if(!empty($aSystems[$sSys]['class_file']))
+                require_once(BX_DIRECTORY_PATH_ROOT . $aSystems[$sSys]['class_file']);
+        }
+
+        $o = new $sClassName($sSys, $iId, $iInit, $oTemplate);
+        return ($GLOBALS['bxDolClasses']['BxDolReport!' . $sSys . $iId] = $o);
+    }
+
+    public static function &getSystems()
+    {
+        if(!isset($GLOBALS['bx_dol_report_systems']))
+            $GLOBALS['bx_dol_report_systems'] = BxDolDb::getInstance()->fromCache('sys_objects_report', 'getAllWithKey', '
+                SELECT
+                    `id` as `id`,
+                    `name` AS `name`,
+                    `table_main` AS `table_main`,
+                    `table_track` AS `table_track`,
+                    `is_on` AS `is_on`,
+                    `trigger_table` AS `trigger_table`,
+                    `trigger_field_id` AS `trigger_field_id`,
+                    `trigger_field_author` AS `trigger_field_author`,
+                    `trigger_field_count` AS `trigger_field_count`,
+                    `class_name` AS `class_name`,
+                    `class_file` AS `class_file`
+                FROM `sys_objects_report`', 'name');
+
+        return $GLOBALS['bx_dol_report_systems'];
+    }
+
+    /**
+     * Interface functions for outer usage
+     */
+    public function getStatCounter()
+    {
+        $aReport = $this->_oQuery->getReport($this->getId());
+        return $aReport['count'];
+    }
+
+    /**
+     * Actions functions
+     */
+    public function actionReport()
+    {
+        return $this->_echoResultJson($this->_getReport());
+    }
+
+	public function actionGetReportedBy()
+    {
+        if (!$this->isEnabled())
+           return '';
+
+	    if(!$this->isAllowedReportView(true))
+            return $this->msgErrAllowedReportView();
+
+        return $this->_getReportedBy();
+    }
+
+    /**
+     * Permissions functions
+     */
+    public function isAllowedReport($isPerformAction = false)
+    {
+        if(isAdmin())
+            return true;
+
+        return $this->checkAction('report', $isPerformAction);
+    }
+
+    public function msgErrAllowedReport()
+    {
+        return $this->checkActionErrorMsg('report');
+    }
+
+    public function isAllowedReportView($isPerformAction = false)
+    {
+        if(isAdmin())
+            return true;
+
+        return $this->checkAction('report_view', $isPerformAction);
+    }
+
+    public function msgErrAllowedReportView()
+    {
+        return $this->checkActionErrorMsg('report_view');
+    }
+
+    /**
+     * Internal functions
+     */
+    protected function _getIconDoReport($bPerformed)
+    {
+    	return 'exclamation-circle';
+    }
+
+    protected function _getTitleDoReport($bPerformed)
+    {
+    	return '_report_do_report';
+    }
+
+	protected function _getFormObject()
+    {
+        return BxDolForm::getObjectInstance($this->_sFormObject, $this->_sFormDisplayPost);
+    }
+}
+
+/** @} */

+ 63 - 0
inc/classes/BxDolReportQuery.php

@@ -0,0 +1,63 @@
+<?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    TridentCore Trident Core
+ * @{
+ */
+
+/**
+ * @see BxDolReport
+ */
+class BxDolReportQuery extends BxDolObjectQuery
+{
+    public function __construct(&$oModule)
+    {
+        parent::__construct($oModule);
+
+        $this->_sMethodGetEntry = 'getReport';
+    }
+
+    public function getSqlParts($sMainTable, $sMainField)
+    {
+    	$aResult = parent::getSqlParts($sMainTable, $sMainField);
+        if(empty($aResult))
+            return $aResult;
+
+		$aResult['fields'] = ", `{$this->_sTable}`.`count` as `report_count` ";
+        return $aResult;
+    }
+
+	public function getPerformedBy($iObjectId)
+    {
+        $sQuery = $this->prepare("SELECT `author_id`, `type`, `text` FROM `{$this->_sTableTrack}` WHERE `object_id`=?", $iObjectId);
+        return $this->getAll($sQuery);
+    }
+
+	public function getReport($iObjectId)
+    {
+        $sQuery = $this->prepare("SELECT `count` as `count` FROM {$this->_sTable} WHERE `object_id` = ? LIMIT 1", $iObjectId);
+
+        $aResult = $this->getRow($sQuery);
+        if(empty($aResult) || !is_array($aResult))
+            $aResult = array('count' => 0);
+
+        return $aResult;
+    }
+
+	public function putReport($iObjectId)
+    {
+        $sQuery = $this->prepare("SELECT `object_id` FROM `{$this->_sTable}` WHERE `object_id` = ? LIMIT 1", $iObjectId);
+        $bExists = (int)$this->getOne($sQuery) != 0;
+
+        if(!$bExists)
+            $sQuery = $this->prepare("INSERT INTO {$this->_sTable} SET `object_id` = ?, `count` = '1'", $iObjectId);
+        else
+            $sQuery = $this->prepare("UPDATE `{$this->_sTable}` SET `count` = `count` + 1 WHERE `object_id` = ?", $iObjectId);
+
+        return (int)$this->query($sQuery) != 0;
+    }
+}
+
+/** @} */

+ 141 - 0
inc/js/classes/BxDolReport.js

@@ -0,0 +1,141 @@
+/**
+ * Copyright (c) BoonEx Pty Limited - http://www.boonex.com/
+ * CC-BY License - http://creativecommons.org/licenses/by/3.0/
+ *
+ * @defgroup    TridentCore Trident Core
+ * @{
+ */
+
+function BxDolReport(options)
+{
+	this._sObjName = undefined == options.sObjName ? 'oReport' : options.sObjName; // javascript object name, to run current object instance from onTimer
+	this._sSystem = options.sSystem; // current comment system
+	this._iAuthorId = options.iAuthorId; // this comment's author ID.
+    this._iObjId = options.iObjId; // this object id comments
+
+    this._sActionsUri = 'report.php';
+    this._sActionsUrl = options.sRootUrl + this._sActionsUri; // actions url address
+
+    this._sAnimationEffect = 'fade';
+    this._iAnimationSpeed = 'slow';
+    this._sSP = undefined == options.sStylePrefix ? 'bx-report' : options.sStylePrefix;
+    this._aHtmlIds = options.aHtmlIds;
+
+    this._oParent = null;
+}
+
+BxDolReport.prototype.toggleByPopup = function(oLink) {
+	var $this = this;
+    var oData = this._getDefaultParams();
+    oData['action'] = 'GetReportedBy';
+
+	$(oLink).dolPopupAjax({
+		id: this._aHtmlIds['by_popup'], 
+		url: bx_append_url_params(this._sActionsUri, oData)
+	});
+};
+
+BxDolReport.prototype.report = function(oLink) {
+	var $this = this;
+    var oData = this._getDefaultParams();
+    oData['action'] = 'Report';
+
+    this._oParent = oLink;
+
+    $.get(
+    	this._sActionsUrl,
+    	oData,
+    	function(oData) {
+    		$this.processJson(oData, oLink);
+    	},
+    	'json'
+    );
+};
+
+BxDolReport.prototype.onReport = function(oData, oElement)
+{
+	if(oData && oData.msg != undefined)
+        alert(oData.msg);
+
+	if(oData && oData.code != 0)
+        return;
+
+	if(oData && oData.label_icon)
+		$(oElement).find('.sys-icon').attr('class', 'sys-icon ' + oData.label_icon);
+
+	if(oData && oData.label_title) {
+		$(oElement).attr('title', oData.label_title);
+		$(oElement).find('span').html(oData.label_title);
+	}
+
+	if(oData && oData.disabled)
+		$(oElement).removeAttr('onclick').addClass($(oElement).hasClass('bx-btn') ? 'bx-btn-disabled' : 'bx-report-disabled');
+
+    var oCounter = this._getCounter(oElement);
+    if(oCounter && oCounter.length > 0) {
+    	oCounter.html(oData.countf);
+
+    	oCounter.parents('.' + this._sSP + '-counter-holder:first').bx_anim(oData.count > 0 ? 'show' : 'hide');
+    }
+};
+
+BxDolReport.prototype.processJson = function(oData, oElement) {
+	oElement = oElement != undefined ? oElement : this._oParent;
+
+    //--- Show Message
+    if(oData && oData.msg != undefined)
+        alert(oData.msg);
+    if(oData && oData.message != undefined)
+        alert(oData.message);
+
+    //--- Show Popup
+    if(oData && oData.popup != undefined) {
+    	$('#' + oData.popup_id).remove();
+
+    	$(oData.popup).hide().prependTo('body').dolPopup({
+    		pointer: {
+    			el: oElement
+    		},
+            fog: {
+				color: '#fff',
+				opacity: .7
+            }
+        });
+    }
+
+    //--- Evaluate JS code
+    if (oData && oData.eval != undefined)
+        eval(oData.eval);
+};
+
+BxDolReport.prototype._getButtons = function(oElement) {
+	if($(oElement).hasClass(this._sSP))
+		return $(oElement).find('.' + this._sSP + '-button');
+	else
+		return $(oElement).parents('.' + this._sSP + ':first').find('.' + this._sSP + '-button');
+};
+
+BxDolReport.prototype._getCounter = function(oElement) {
+	if($(oElement).hasClass(this._sSP))
+		return $(oElement).find('.' + this._sSP + '-counter');
+	else 
+		return $(oElement).parents('.' + this._sSP + ':first').find('.' + this._sSP + '-counter');
+};
+
+BxDolReport.prototype._loadingInButton = function(e, bShow) {
+	if($(e).length)
+		bx_loading_btn($(e), bShow);
+	else
+		bx_loading($('body'), bShow);	
+};
+
+BxDolReport.prototype._getDefaultParams = function() {
+	var oDate = new Date();
+    return {
+        sys: this._sSystem,
+        object_id: this._iObjId,
+        _t: oDate.getTime()
+    };
+};
+
+/** @} */

+ 69 - 6
install/sql/system.sql

@@ -450,6 +450,14 @@ INSERT INTO `sys_acl_actions` (`Module`, `Name`, `AdditionalParamName`, `Title`,
 ('system', 'vote', NULL, '_sys_acl_action_vote', '', 0, 0);
 SET @iIdActionVote = LAST_INSERT_ID();
 
+INSERT INTO `sys_acl_actions` (`Module`, `Name`, `AdditionalParamName`, `Title`, `Desc`, `Countable`, `DisabledForLevels`) VALUES
+('system', 'report', NULL, '_sys_acl_action_report', '', 0, 0);
+SET @iIdActionReport = LAST_INSERT_ID();
+
+INSERT INTO `sys_acl_actions` (`Module`, `Name`, `AdditionalParamName`, `Title`, `Desc`, `Countable`, `DisabledForLevels`) VALUES
+('system', 'report_view', NULL, '_sys_acl_action_report_view', '', 0, 0);
+SET @iIdActionReportView = LAST_INSERT_ID();
+
 INSERT INTO `sys_acl_actions` (`Module`, `Name`, `AdditionalParamName`, `Title`, `Desc`, `Countable`, `DisabledForLevels`) VALUES
 ('system', 'comments post', NULL, '_sys_acl_action_comments_post', '', 0, 3);
 SET @iIdActionCmtPost = LAST_INSERT_ID();
@@ -522,6 +530,16 @@ INSERT INTO `sys_acl_matrix` (`IDLevel`, `IDAction`) VALUES
 (@iAdministrator, @iIdActionVote),
 (@iPremium, @iIdActionVote),
 
+-- report 
+(@iStandard, @iIdActionReport),
+(@iModerator, @iIdActionReport),
+(@iAdministrator, @iIdActionReport),
+(@iPremium, @iIdActionReport),
+
+-- report view 
+(@iModerator, @iIdActionReportView),
+(@iAdministrator, @iIdActionReportView),
+
 -- comments post
 (@iStandard, @iIdActionCmtPost),
 (@iModerator, @iIdActionCmtPost),
@@ -996,6 +1014,25 @@ INSERT INTO `sys_alerts` (`unit`, `action`, `handler_id`) VALUES
 -- --------------------------------------------------------
 
 
+CREATE TABLE `sys_objects_report` (
+  `id` int(11) NOT NULL auto_increment,
+  `name` varchar(64) NOT NULL,
+  `table_main` varchar(32) NOT NULL,
+  `table_track` varchar(32) NOT NULL,
+  `is_on` tinyint(4) NOT NULL default '1',
+  `trigger_table` varchar(32) NOT NULL,
+  `trigger_field_id` varchar(32) NOT NULL,
+  `trigger_field_author` varchar(32) NOT NULL,
+  `trigger_field_count` varchar(32) NOT NULL,
+  `class_name` varchar(32) NOT NULL default '',
+  `class_file` varchar(256) NOT NULL default '',
+  PRIMARY KEY  (`id`)
+) ENGINE=MyISAM  DEFAULT CHARSET=utf8;
+
+
+-- --------------------------------------------------------
+
+
 CREATE TABLE `sys_objects_view` (
   `id` int(11) NOT NULL auto_increment,
   `name` varchar(64) NOT NULL,
@@ -2099,7 +2136,8 @@ INSERT INTO `sys_objects_form` (`object`, `module`, `title`, `action`, `form_att
 ('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_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, 'BxTemplCmtsForm', '');
+('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, 'BxTemplCmtsForm', ''),
+('sys_report', 'system', '_sys_form_report', 'report.php', 'a:3:{s:2:"id";s:0:"";s:4:"name";s:0:"";s:5:"class";s:17:"bx-report-do-form";}', 'submit', '', 'id', '', '', '', 0, 1, '', '');
 
 CREATE TABLE IF NOT EXISTS `sys_form_displays` (
   `id` int(11) NOT NULL AUTO_INCREMENT,
@@ -2124,7 +2162,8 @@ INSERT INTO `sys_form_displays` (`display_name`, `module`, `object`, `title`, `v
 ('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_comment_post', 'system', 'sys_comment', '_sys_form_display_comment_post', 0),
-('sys_comment_edit', 'system', 'sys_comment', '_sys_form_display_comment_edit', 0);
+('sys_comment_edit', 'system', 'sys_comment', '_sys_form_display_comment_edit', 0),
+('sys_report_post', 'system', 'sys_report', '_sys_form_display_report_post', 0);
 
 
 CREATE TABLE IF NOT EXISTS `sys_form_inputs` (
@@ -2196,7 +2235,15 @@ INSERT INTO `sys_form_inputs` (`object`, `module`, `name`, `value`, `values`, `c
 ('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);
+('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),
+
+('sys_report', 'system', 'sys', '', '', 0, 'hidden', '_sys_form_report_input_caption_system_sys', '', '', 0, 0, 0, '', '', '', '', '', '', '', '', 0, 0),
+('sys_report', 'system', 'object_id', '', '', 0, 'hidden', '_sys_form_report_input_caption_system_object_id', '', '', 0, 0, 0, '', '', '', '', '', '', 'Int', '', 0, 0),
+('sys_report', 'system', 'action', '', '', 0, 'hidden', '_sys_form_report_input_caption_system_action', '', '', 0, 0, 0, '', '', '', '', '', '', '', '', 0, 0),
+('sys_report', 'system', 'id', '', '', 0, 'hidden', '_sys_form_report_input_caption_system_id', '', '', 0, 0, 0, '', '', '', '', '', '', 'Int', '', 0, 0),
+('sys_report', 'system', 'type', '', '#!sys_report_types', 0, 'select', '_sys_form_report_input_caption_system_type', '_sys_form_report_input_caption_type', '', 1, 0, 0, '', '', '', 'Avail', '', '_Please select value', 'Xss', '', 1, 0),
+('sys_report', 'system', 'text', '', '', 0, 'textarea', '_sys_form_report_input_caption_system_text', '_sys_form_report_input_caption_text', '', 0, 0, 0, '', '', '', '', '', '', 'Xss', '', 1, 0),
+('sys_report', 'system', 'submit', '_sys_form_report_input_caption_submit', '', 0, 'submit', '_sys_form_report_input_caption_system_submit', '', '', 0, 0, 0, '', '', '', '', '', '', '', '', 0, 0);
 
 
 CREATE TABLE IF NOT EXISTS `sys_form_display_inputs` (
@@ -2279,7 +2326,15 @@ INSERT INTO `sys_form_display_inputs` (`display_name`, `input_name`, `visible_fo
 ('sys_comment_edit', 'cmt_parent_id', 2147483647, 1, 5),
 ('sys_comment_edit', 'cmt_text', 2147483647, 1, 6),
 ('sys_comment_edit', 'cmt_image', 2147483647, 0, 7),
-('sys_comment_edit', 'cmt_submit', 2147483647, 1, 8);
+('sys_comment_edit', 'cmt_submit', 2147483647, 1, 8),
+
+('sys_report_post', 'sys', 2147483647, 1, 1),
+('sys_report_post', 'object_id', 2147483647, 1, 2),
+('sys_report_post', 'action', 2147483647, 1, 3),
+('sys_report_post', 'id', 2147483647, 0, 4),
+('sys_report_post', 'type', 2147483647, 1, 5),
+('sys_report_post', 'text', 2147483647, 1, 6),
+('sys_report_post', 'submit', 2147483647, 1, 7);
 
 
 CREATE TABLE `sys_form_pre_lists` (
@@ -2296,7 +2351,8 @@ CREATE TABLE `sys_form_pre_lists` (
 INSERT INTO `sys_form_pre_lists`(`key`, `title`, `module`, `use_for_sets`) VALUES
 ('Country', '_adm_form_txt_pre_lists_country', 'system', '0'),
 ('Sex', '_adm_form_txt_pre_lists_sex', 'system', '1'),
-('Language', '_adm_form_txt_pre_lists_language', 'system', '0');
+('Language', '_adm_form_txt_pre_lists_language', 'system', '0'),
+('sys_report_types', '_sys_pre_lists_report_types', 'system', '0');
 
 
 CREATE TABLE `sys_form_pre_values` (
@@ -2310,7 +2366,7 @@ CREATE TABLE `sys_form_pre_values` (
   FULLTEXT KEY `KeyAndValue` (`Key`, `Value`)
 ) ENGINE=MyISAM DEFAULT CHARSET=utf8;
 
-INSERT INTO `sys_form_pre_values`(`Key`, `Value`, `Order`, `LKey`, `LKey2`) VALUES 
+INSERT INTO `sys_form_pre_values`(`Key`, `Value`, `Order`, `LKey`, `LKey2`) VALUES
 ('Country', 'AF', 1, '__Afghanistan', ''),
 ('Country', 'AX', 2, '__Aland_Islands', ''),
 ('Country', 'AL', 3, '__Albania', ''),
@@ -2617,6 +2673,13 @@ INSERT INTO `sys_form_pre_values`(`Key`, `Value`, `Order`, `LKey`, `LKey2`) VALU
 ('Language', '51', 51, '__Vietnamese', ''),
 ('Language', '52', 52, '__Visayan', '');
 
+INSERT INTO `sys_form_pre_values`(`Key`, `Value`, `Order`, `LKey`, `LKey2`) VALUES
+('sys_report_types', 'spam', 1, '_sys_pre_lists_report_types_spam', ''),
+('sys_report_types', 'scam', 2, '_sys_pre_lists_report_types_scam', ''),
+('sys_report_types', 'fraud', 3, '_sys_pre_lists_report_types_fraud', ''),
+('sys_report_types', 'nude', 4, '_sys_pre_lists_report_types_nude', ''),
+('sys_report_types', 'other', 5, '_sys_pre_lists_report_types_other', '');
+
 -- --------------------------------------------------------
 
 CREATE TABLE IF NOT EXISTS `sys_menu_templates` (

+ 21 - 0
modules/boonex/air/data/template/system/scripts/BxTemplReport.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    TridentCore Trident Core
+ * @{
+ */
+
+/**
+ * @see BxDolReport
+ */
+class BxTemplReport extends BxBaseReport
+{
+    function __construct($sSystem, $iId, $iInit = true, $oTemplate = false)
+    {
+        parent::__construct($sSystem, $iId, $iInit, $oTemplate);
+    }
+}
+
+/** @} */

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

@@ -61,7 +61,18 @@
 	<string name="_Period"><![CDATA[Period]]></string>
 	<string name="_Please Wait"><![CDATA[Please Wait]]></string>
 	<string name="_Please enter n1-n2 characters"><![CDATA[Please enter {0}-{1} characters]]></string>
+	<string name="_Please select value"><![CDATA[Please select a value from the list]]></string>
 	<string name="_Preview"><![CDATA[Preview]]></string>
+
+	<string name="_report_counter"><![CDATA[{0}]]></string>
+	<string name="_report_do_report"><![CDATA[Report]]></string>
+	<string name="_report_do_report_by"><![CDATA[Reported by]]></string>
+	<string name="_report_err_cannot_perform_action"><![CDATA[Cannot perform action.]]></string>
+	<string name="_report_err_duplicate_report"><![CDATA[You already reported this item.]]></string>
+	<string name="_report_err_not_enabled"><![CDATA[The feature is not available right now. Please, try again later.]]></string>
+	<string name="_report_err_wrong_type"><![CDATA[Wrong report type.]]></string>
+	<string name="_report_reported_as"><![CDATA[Reported as:]]></string>
+
 	<string name="_RSS_Feed_Title_Common"><![CDATA[{0} RSS]]></string>
 	<string name="_RSS_Feed_Title_Profile"><![CDATA[{0}'s Recent {1}]]></string>
 	<string name="_Rate"><![CDATA[Rate]]></string>
@@ -1365,6 +1376,8 @@
 	<string name="_sys_acl_action_unauthenticated"><![CDATA[Not logged in users can't '{1}'.]]></string>
 	<string name="_sys_acl_action_unconfirmed"><![CDATA[You didn't confirm your profile. Please check your email with profile activation link. Unconfirmed members can't <b>{1}</b>.]]></string>
 	<string name="_sys_acl_action_vote"><![CDATA[Vote]]></string>
+	<string name="_sys_acl_action_report"><![CDATA[Report]]></string>
+	<string name="_sys_acl_action_report_view"><![CDATA[View reports]]></string>
 	<string name="_sys_add_friend"><![CDATA[Add friend]]></string>
 	<string name="_sys_adm_installed"><![CDATA[Installed]]></string>
 	<string name="_sys_admin_apply"><![CDATA[Apply]]></string>
@@ -1627,6 +1640,7 @@ If it is not enabled then please consider implement this optimization, since it
 	<string name="_sys_form_display_confirm_email"><![CDATA[Email Confirmation]]></string>
 	<string name="_sys_form_display_forgot_password"><![CDATA[Forgot Password]]></string>
 	<string name="_sys_form_display_login"><![CDATA[Sign in]]></string>
+	<string name="_sys_form_display_report_post"><![CDATA[Report From Post]]></string>
 	<string name="_sys_form_display_unsubscribe_news"><![CDATA[Unsubscribe From Newsletters]]></string>
 	<string name="_sys_form_display_unsubscribe_updates"><![CDATA[Unsubscribe From Updates]]></string>
 	<string name="_sys_form_forgot_password"><![CDATA[Forgot Password]]></string>
@@ -1658,6 +1672,17 @@ If it is not enabled then please consider implement this optimization, since it
 	<string name="_sys_form_login_input_password"><![CDATA[Password]]></string>
 	<string name="_sys_form_login_input_remember_me"><![CDATA[Remember me]]></string>
 	<string name="_sys_form_login_input_submit"><![CDATA[Sign in]]></string>
+	<string name="_sys_form_report"><![CDATA[Report]]></string>
+	<string name="_sys_form_report_input_caption_submit"><![CDATA[Post]]></string>
+	<string name="_sys_form_report_input_caption_text"><![CDATA[Report Text]]></string>
+	<string name="_sys_form_report_input_caption_type"><![CDATA[Report Type]]></string>
+	<string name="_sys_form_report_input_caption_system_action"><![CDATA[Action]]></string>
+	<string name="_sys_form_report_input_caption_system_object_id"><![CDATA[Object ID]]></string>	
+	<string name="_sys_form_report_input_caption_system_id"><![CDATA[Report ID]]></string>
+	<string name="_sys_form_report_input_caption_system_submit"><![CDATA[Post Report]]></string>
+	<string name="_sys_form_report_input_caption_system_text"><![CDATA[Report Text]]></string>
+	<string name="_sys_form_report_input_caption_system_type"><![CDATA[Report Type]]></string>
+	<string name="_sys_form_report_input_caption_system_sys"><![CDATA[Object Type]]></string>
 	<string name="_sys_form_unsubscribe"><![CDATA[Unsubscribe]]></string>
 	<string name="_sys_form_unsubscribe_input_caption_system_code"><![CDATA[Security Code]]></string>
 	<string name="_sys_form_unsubscribe_input_caption_system_do_submit"><![CDATA[Submit]]></string>
@@ -1946,6 +1971,12 @@ If it is not enabled then please consider implement this optimization, since it
 	<string name="_sys_paginate_info"><![CDATA[{0}-{1}]]></string>
 	<string name="_sys_paginate_view_all"><![CDATA[View All]]></string>
 	<string name="_sys_please_select"><![CDATA[Please select...]]></string>
+	<string name="_sys_pre_lists_report_types"><![CDATA[Report Types]]></string>
+	<string name="_sys_pre_lists_report_types_spam"><![CDATA[spam]]></string>
+	<string name="_sys_pre_lists_report_types_scam"><![CDATA[scam]]></string>
+	<string name="_sys_pre_lists_report_types_fraud"><![CDATA[fraud]]></string>
+	<string name="_sys_pre_lists_report_types_nude"><![CDATA[nude]]></string>
+	<string name="_sys_pre_lists_report_types_other"><![CDATA[other]]></string>
 	<string name="_sys_profile_sample_single"><![CDATA[profile]]></string>
 	<string name="_sys_profile_subscription_added"><![CDATA[<a class="bx-ntfs-content-profile" href="{owner_link}">{owner_name}</a> subscribed to <a href="{entry_url}">{entry_caption}</a> {entry_sample}]]></string>
 	<string name="_sys_private"><![CDATA[Private]]></string>
@@ -2142,6 +2173,7 @@ If it is not enabled then please consider implement this optimization, since it
 	<string name="_top"><![CDATA[Top]]></string>
 	<string name="_uknown"><![CDATA[unknown]]></string>
 	<string name="_undefined"><![CDATA[undefined]]></string>
+	<string name="_vote_counter"><![CDATA[{0}]]></string>
 	<string name="_vote_do_like"><![CDATA[Thank you!]]></string>
 	<string name="_vote_do_unlike"><![CDATA[No thank you]]></string>
 	<string name="_vote_do_like_by"><![CDATA[Thanked by]]></string>

+ 21 - 0
modules/boonex/lagoon/data/template/system/scripts/BxTemplReport.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    TridentCore Trident Core
+ * @{
+ */
+
+/**
+ * @see BxDolReport
+ */
+class BxTemplReport extends BxBaseReport
+{
+    function __construct($sSystem, $iId, $iInit = true, $oTemplate = false)
+    {
+        parent::__construct($sSystem, $iId, $iInit, $oTemplate);
+    }
+}
+
+/** @} */

+ 21 - 0
modules/boonex/ocean/data/template/system/scripts/BxTemplReport.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    TridentCore Trident Core
+ * @{
+ */
+
+/**
+ * @see BxDolReport
+ */
+class BxTemplReport extends BxBaseReport
+{
+    function __construct($sSystem, $iId, $iInit = true, $oTemplate = false)
+    {
+        parent::__construct($sSystem, $iId, $iInit, $oTemplate);
+    }
+}
+
+/** @} */

+ 32 - 0
modules/boonex/russian/data/langs/system/ru.xml

@@ -61,7 +61,18 @@
 	<string name="_Period"><![CDATA[Период]]></string>
 	<string name="_Please Wait"><![CDATA[Пожалуйста, подождите]]></string>
 	<string name="_Please enter n1-n2 characters"><![CDATA[Пожалуйста, введите {0}-{1} символов]]></string>
+	<string name="_Please select value"><![CDATA[Пожалуйста, выберите значение из списка]]></string>
 	<string name="_Preview"><![CDATA[Предпросмотр]]></string>
+
+	<string name="_report_counter"><![CDATA[{0}]]></string>
+	<string name="_report_do_report"><![CDATA[Пожаловаться]]></string>
+	<string name="_report_do_report_by"><![CDATA[Пожаловались]]></string>
+	<string name="_report_err_cannot_perform_action"><![CDATA[Невозможно выполнить действие.]]></string>
+	<string name="_report_err_duplicate_report"><![CDATA[Ваша жалоба уже была принята ранее.]]></string>
+	<string name="_report_err_not_enabled"><![CDATA[Жалоба не может быть принята в данный момент. Пожалуйста, попробуйте позднее.]]></string>
+	<string name="_report_err_wrong_type"><![CDATA[Неправильный тип жалобы.]]></string>
+	<string name="_report_reported_as"><![CDATA[Тип жалобы:]]></string>
+
 	<string name="_RSS_Feed_Title_Common"><![CDATA[{0} RSS]]></string>
 	<string name="_RSS_Feed_Title_Profile"><![CDATA[{0} недавние {1}]]></string>
 	<string name="_Rate"><![CDATA[Оценить]]></string>
@@ -1365,6 +1376,8 @@
 	<string name="_sys_acl_action_unauthenticated"><![CDATA[Не вошедшие пользователи не могут '{1}'.]]></string>
 	<string name="_sys_acl_action_unconfirmed"><![CDATA[Вы не подтвердили свой профиль. Пожалуйста, проверьте эл. сообщение со ссылкой на активацию профиля. Неподтверждённые пользователи не могут <b>{1}</b>.]]></string>
 	<string name="_sys_acl_action_vote"><![CDATA[Голосовать]]></string>
+	<string name="_sys_acl_action_report"><![CDATA[Жаловаться]]></string>
+	<string name="_sys_acl_action_report_view"><![CDATA[Просматривать жалобы]]></string>
 	<string name="_sys_add_friend"><![CDATA[Добавить друга]]></string>
 	<string name="_sys_adm_installed"><![CDATA[Установленные]]></string>
 	<string name="_sys_admin_apply"><![CDATA[Применить]]></string>
@@ -1627,6 +1640,7 @@
 	<string name="_sys_form_display_confirm_email"><![CDATA[Подтверждение имейла]]></string>
 	<string name="_sys_form_display_forgot_password"><![CDATA[Забыли Пароль?]]></string>
 	<string name="_sys_form_display_login"><![CDATA[Войти]]></string>
+	<string name="_sys_form_display_report_post"><![CDATA[Форма добавления жалобы]]></string>
 	<string name="_sys_form_display_unsubscribe_news"><![CDATA[Отписаться от Новостей]]></string>
 	<string name="_sys_form_display_unsubscribe_updates"><![CDATA[Отписаться от Обновлений]]></string>
 	<string name="_sys_form_forgot_password"><![CDATA[Забыли Пароль?]]></string>
@@ -1658,6 +1672,17 @@
 	<string name="_sys_form_login_input_password"><![CDATA[Пароль]]></string>
 	<string name="_sys_form_login_input_remember_me"><![CDATA[Запомнить меня]]></string>
 	<string name="_sys_form_login_input_submit"><![CDATA[Вход]]></string>
+	<string name="_sys_form_report"><![CDATA[Пожаловаться]]></string>
+	<string name="_sys_form_report_input_caption_submit"><![CDATA[Пожаловаться]]></string>
+	<string name="_sys_form_report_input_caption_text"><![CDATA[Текст жалобы]]></string>
+	<string name="_sys_form_report_input_caption_type"><![CDATA[Тип жалобы]]></string>
+	<string name="_sys_form_report_input_caption_system_action"><![CDATA[Действие]]></string>
+	<string name="_sys_form_report_input_caption_system_object_id"><![CDATA[ID объекта]]></string>
+	<string name="_sys_form_report_input_caption_system_id"><![CDATA[ID жалобы]]></string>
+	<string name="_sys_form_report_input_caption_system_submit"><![CDATA[Пожаловаться]]></string>
+	<string name="_sys_form_report_input_caption_system_text"><![CDATA[Текст жалобы]]></string>
+	<string name="_sys_form_report_input_caption_system_type"><![CDATA[Тип жалобы]]></string>
+	<string name="_sys_form_report_input_caption_system_sys"><![CDATA[Тип объекта]]></string>
 	<string name="_sys_form_unsubscribe"><![CDATA[Отписаться]]></string>
 	<string name="_sys_form_unsubscribe_input_caption_system_code"><![CDATA[Код Безопасности]]></string>
 	<string name="_sys_form_unsubscribe_input_caption_system_do_submit"><![CDATA[Выполнить]]></string>
@@ -1946,6 +1971,12 @@
 	<string name="_sys_paginate_info"><![CDATA[{0}-{1}]]></string>
 	<string name="_sys_paginate_view_all"><![CDATA[Просмотреть Все]]></string>
 	<string name="_sys_please_select"><![CDATA[Пожалуйста, выберите...]]></string>
+	<string name="_sys_pre_lists_report_types"><![CDATA[Типы жалоб]]></string>
+	<string name="_sys_pre_lists_report_types_spam"><![CDATA[спам]]></string>
+	<string name="_sys_pre_lists_report_types_scam"><![CDATA[скам]]></string>
+	<string name="_sys_pre_lists_report_types_fraud"><![CDATA[обман]]></string>
+	<string name="_sys_pre_lists_report_types_nude"><![CDATA[обнаженность]]></string>
+	<string name="_sys_pre_lists_report_types_other"><![CDATA[другое]]></string>
 	<string name="_sys_profile_sample_single"><![CDATA[профиль]]></string>
 	<string name="_sys_profile_subscription_added"><![CDATA[<a class="bx-ntfs-content-profile" href="{owner_link}">{owner_name}</a> подписался на <a href="{entry_url}">{entry_caption}</a> {entry_sample}]]></string>
 	<string name="_sys_private"><![CDATA[Приватные]]></string>
@@ -2143,6 +2174,7 @@
 	<string name="_top"><![CDATA[Топ]]></string>
 	<string name="_uknown"><![CDATA[неизвестно]]></string>
 	<string name="_undefined"><![CDATA[неопределено]]></string>
+	<string name="_vote_counter"><![CDATA[{0}]]></string>
 	<string name="_vote_do_like"><![CDATA[Спасибо!]]></string>
 	<string name="_vote_do_unlike"><![CDATA[Нет, спасибо]]></string>
 	<string name="_vote_do_like_by"><![CDATA[Поблагодарил]]></string>

+ 30 - 0
report.php

@@ -0,0 +1,30 @@
+<?php
+/**
+ * Copyright (c) BoonEx Pty Limited - http://www.boonex.com/
+ * CC-BY License - http://creativecommons.org/licenses/by/3.0/
+ *
+ * @defgroup    TridentCore Trident Core
+ * @{
+ */
+
+require_once('./inc/header.inc.php');
+require_once(BX_DIRECTORY_PATH_INC . "design.inc.php");
+
+bx_import('BxDolLanguages');
+
+check_logged();
+
+$sSys = isset($_REQUEST['sys']) ? bx_process_input($_REQUEST['sys']) : false;
+$iObjectId = isset($_REQUEST['object_id']) ? bx_process_input($_REQUEST['object_id'], BX_DATA_INT) : 0;
+$sAction = isset($_REQUEST['action']) && preg_match ('/^[A-Za-z_-]+$/', $_REQUEST['action']) ? bx_process_input($_REQUEST['action']) : '';
+
+$oReport = BxDolReport::getObjectInstance($sSys, $iObjectId, true);
+
+if ($oReport && $sSys && $iObjectId && $sAction) {
+    header('Content-Type: text/html; charset=utf-8');
+    $sMethod = 'action' . ucfirst($sAction);
+    if(method_exists($oReport, $sMethod))
+        echo $oReport->$sMethod();
+}
+
+/** @} */

+ 66 - 0
template/css/report.css

@@ -0,0 +1,66 @@
+/*--- Do Form ---*/
+div.bx-report-do-form {}
+div.bx-report-do-form-cnt {
+	min-width: 220px;
+	min-width: 13.75rem;
+	overflow: hidden;
+}
+
+/*--- Reported By List ---*/
+div.bx-report-by-list {}
+div.bx-report-by-list-cnt {
+	max-height: 400px;
+	max-height: 25rem;
+	min-width: 220px;
+	min-width: 13.75rem;
+	max-width: 320px;
+	max-width: 20rem;
+	overflow: auto;
+}
+div.bx-report-by-list div.bx-base-pofile-unit {
+	float: none;
+	margin-right: 0px;
+	margin-bottom: 0px;
+}
+div.bx-report-bi-thumbnail,
+div.bx-report-bi-info {
+	position: relative;
+}
+div.bx-report-bi-info p {
+	margin: 0px; 
+}
+
+/*--- Report Element Styles ---*/
+div.bx-report div.bx-report-element-holder,
+div.bx-report div.bx-report-counter-holder {
+	position: relative;
+	float: left;
+}
+
+/*--- Report Element Styles ---*/
+.bx-report-report .bx-report-element-holder,
+.bx-report-report .bx-report-counter-holder {
+	line-height: 20px;
+	line-height: 1.25rem;
+}
+
+.bx-report-button .bx-report-element-holder,
+.bx-report-button .bx-report-counter-holder {
+	line-height: 36px;
+	line-height: 2.2rem;
+}
+
+.bx-report-button-small .bx-report-element-holder,
+.bx-report-button-small .bx-report-counter-holder {
+	line-height: 24px;
+	line-height: 1.6rem;
+}
+
+.bx-report-report .bx-report-element-holder .bx-report-do-report.bx-report-disabled {
+	color: #ddd;
+}
+
+.bx-report-button .bx-report-counter-holder,
+.bx-report-button-small .bx-report-counter-holder {
+	font-size: 1.5rem;
+}

+ 17 - 0
template/report_by_list.html

@@ -0,0 +1,17 @@
+<div class="__style_prefix__-by-list">
+	<div class="__style_prefix__-by-list-cnt">
+		<div class="__style_prefix__-by-items">
+			<bx_repeat:list>
+				<div class="__style_prefix__-by-item bx-def-padding-sec bx-clearfix">
+					<div class="__style_prefix__-bi-thumbnail">__user_unit__</div>
+					<div class="bx-report-bi-info">
+						<p class="bx-report-bii-type"><bx_text:_report_reported_as /> <span class="bx-def-font-bold">__type__</span></p>
+						<bx_if:show_text>
+							<p class="bx-report-bii-text bx-def-font-small bx-def-font-grayed">__text__</p>
+						</bx_if:show_text>
+					</div>
+				</div>
+			</bx_repeat:list>
+		</div>
+	</div>
+</div>

+ 1 - 0
template/report_counter.html

@@ -0,0 +1 @@
+<bx_include_auto:bx_a.html />

+ 1 - 0
template/report_do_report.html

@@ -0,0 +1 @@
+<a id="__html_id__" class="__style_prefix__-do-report __class__" href="javascript:void(0)" <bx_if:show_onclick>onclick="javascript:__js_object__.report(this)"</bx_if:show_onclick> title="__title__">__do_report__</a>

+ 22 - 0
template/report_do_report_form.html

@@ -0,0 +1,22 @@
+<div class="__style_prefix__-do-form">
+	<div class="__style_prefix__-do-form-cnt bx-def-padding">
+		__form__
+        <script type="text/javascript">
+            $(document).ready(function () {
+                $("#__form_id__").ajaxForm({ 
+                    dataType: "json",
+                    beforeSubmit: function (formData, jqForm, options) {
+                        bx_loading($("#__form_id__"), true);
+                    },
+                    success: function (oData) {
+                    	bx_loading($("#__form_id__"), false);
+
+                        $(".bx-popup-applied:visible").dolPopupHide();
+
+                        __js_object__.processJson(oData);
+                    }
+                });
+            });
+        </script>
+	</div>
+</div>

+ 1 - 0
template/report_do_report_label.html

@@ -0,0 +1 @@
+<bx_if:show_icon><i class="sys-icon __name__"></i></bx_if:show_icon><bx_if:show_text><span class="bx-def-margin-sec-left-auto">__text__</span></bx_if:show_text>

+ 7 - 0
template/report_element_block.html

@@ -0,0 +1,7 @@
+<div id="__html_id__" class="__style_prefix__ __class__ bx-def-margin-right-auto bx-def-margin-thd-topbottom bx-clearfix" bx_report_data_count="__count__">
+	<div class="__style_prefix__-element-holder">__do_report__</div>
+	<bx_if:show_counter>
+		<div class="__style_prefix__-counter-holder bx-def-margin-sec-left"<bx_if:show_hidden> style="display:none"</bx_if:show_hidden>>__counter__</div>
+	</bx_if:show_counter>
+</div>
+__script__

+ 4 - 0
template/report_element_inline.html

@@ -0,0 +1,4 @@
+<span id="__html_id__" class="__style_prefix__ __class__ bx-def-margin-right-auto bx-def-margin-thd-topbottom" bx_report_data_count="__count__">
+	<span class="__style_prefix__-element-holder">__do_report__</span><bx_if:show_counter><span class="__style_prefix__-counter-holder bx-def-margin-thd-left"<bx_if:show_hidden> style="display:none"</bx_if:show_hidden>>__counter__</span></bx_if:show_counter>
+</span>
+__script__

+ 354 - 0
template/scripts/BxBaseReport.php

@@ -0,0 +1,354 @@
+<?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    TridentCore Trident Core
+ * @{
+ */
+
+/**
+ * @see BxDolReport
+ */
+class BxBaseReport extends BxDolReport
+{
+	protected $_bCssJsAdded;
+
+	protected $_sJsObjClass;
+    protected $_sJsObjName;
+    protected $_sStylePrefix;
+
+    protected $_aHtmlIds;
+
+    protected $_aElementDefaults;
+
+    protected $_sTmplNameCounter;
+    protected $_sTmplNameDoReport;
+
+    public function __construct($sSystem, $iId, $iInit = true, $oTemplate = false)
+    {
+        parent::__construct($sSystem, $iId, $iInit, $oTemplate);
+
+        $this->_bCssJsAdded = false;
+
+        $this->_sJsObjClass = 'BxDolReport';
+        $this->_sJsObjName = 'oReport' . bx_gen_method_name($sSystem, array('_' , '-')) . $iId;
+        $this->_sStylePrefix = 'bx-report';
+
+        $sHtmlId = str_replace(array('_' , ' '), array('-', '-'), $sSystem) . '-' . $iId;
+        $this->_aHtmlIds = array(
+            'main' => 'bx-report-' . $sHtmlId,
+            'counter' => 'bx-report-counter-' . $sHtmlId,
+        	'do_link' => 'bx-report-do-link-' . $sHtmlId,
+        	'do_popup' => 'bx-report-do-popup-' . $sHtmlId,
+        	'do_form' => 'bx-report-do-form-' . $sHtmlId,
+            'by_popup' => 'bx-report-by-popup-' . $sHtmlId
+        );
+
+        $this->_aElementDefaults = array(
+			'show_do_report_as_button' => false,
+			'show_do_report_as_button_small' => false,
+			'show_do_report_icon' => true,
+			'show_do_report_label' => false,
+			'show_counter' => true
+        );
+
+        $this->_sTmplNameCounter = 'report_counter.html';
+        $this->_sTmplNameDoReport = 'report_do_report.html';
+    }
+
+    public function addCssJs($bDynamicMode = false)
+    {
+    	if($bDynamicMode || $this->_bCssJsAdded)
+    		return;
+
+    	$this->_oTemplate->addJs(array('BxDolReport.js'));
+        $this->_oTemplate->addCss(array('report.css'));
+
+        $this->_bCssJsAdded = true;
+    }
+
+    public function getJsObjectName()
+    {
+        return $this->_sJsObjName;
+    }
+
+    public function getJsScript($bDynamicMode = false)
+    {
+        $aParams = array(
+            'sObjName' => $this->_sJsObjName,
+            'sSystem' => $this->getSystemName(),
+            'iAuthorId' => $this->_getAuthorId(),
+            'iObjId' => $this->getId(),
+            'sRootUrl' => BX_DOL_URL_ROOT,
+            'sStylePrefix' => $this->_sStylePrefix,
+            'aHtmlIds' => $this->_aHtmlIds
+        );
+        $sCode = $this->_sJsObjName . " = new " . $this->_sJsObjClass . "(" . json_encode($aParams) . ");";
+
+        if($bDynamicMode) {
+			$sCode = "var " . $this->_sJsObjName . " = null; 
+			$.getScript('" . bx_js_string($this->_oTemplate->getJsUrl('BxDolReport.js'), BX_ESCAPE_STR_APOS) . "', function(data, textStatus, jqxhr) {
+				bx_get_style('" . bx_js_string($this->_oTemplate->getCssUrl('report.css'), BX_ESCAPE_STR_APOS) . "');
+				" . $sCode . "
+        	}); ";
+        }
+        else
+        	$sCode = "var " . $sCode;
+
+        $this->addCssJs($bDynamicMode);
+        return $this->_oTemplate->_wrapInTagJsCode($sCode);
+    }
+
+    public function getJsClick()
+    {
+        return $this->getJsObjectName() . '.report(this)';
+    }
+
+    public function getCounter($aParams = array())
+    {
+        $sJsObject = $this->getJsObjectName();
+
+        $aReport = $this->_oQuery->getReport($this->getId());
+
+        return $this->_oTemplate->parseHtmlByName($this->_sTmplNameCounter, array(
+            'href' => 'javascript:void(0)',
+            'title' => _t('_report_do_report_by'),
+            'bx_repeat:attrs' => array(
+                array('key' => 'id', 'value' => $this->_aHtmlIds['counter']),
+                array('key' => 'class', 'value' => $this->_sStylePrefix . '-counter'),
+                array('key' => 'onclick', 'value' => 'javascript:' . $sJsObject . '.toggleByPopup(this)')
+            ),
+            'content' => (int)$aReport['count'] > 0 ? $this->_getLabelCounter($aReport['count']) : ''
+        ));
+    }
+
+    public function getElementBlock($aParams = array())
+    {
+        $aParams['usage'] = BX_DOL_REPORT_USAGE_BLOCK;
+
+        return $this->getElement($aParams);
+    }
+
+    public function getElementInline($aParams = array())
+    {
+        $aParams['usage'] = BX_DOL_REPORT_USAGE_INLINE;
+
+        return $this->getElement($aParams);
+    }
+
+    public function getElement($aParams = array())
+    {
+    	$aParams = array_merge($this->_aElementDefaults, $aParams);
+    	$bDynamicMode = isset($aParams['dynamic_mode']) && $aParams['dynamic_mode'] === true;
+
+        $bShowDoReportAsButtonSmall = isset($aParams['show_do_report_as_button_small']) && $aParams['show_do_report_as_button_small'] == true;
+        $bShowDoReportAsButton = !$bShowDoReportAsButtonSmall && isset($aParams['show_do_report_as_button']) && $aParams['show_do_report_as_button'] == true;
+		$bShowCounter = isset($aParams['show_counter']) && $aParams['show_counter'] === true && $this->isAllowedReportView();
+
+		$iObjectId = $this->getId();
+		$iAuthorId = $this->_getAuthorId();
+        $aReport = $this->_oQuery->getReport($iObjectId);
+
+        if(!$this->isAllowedReport() && (int)$aReport['count'] == 0)
+            return '';
+
+        $aParams['is_reported'] = $this->_oQuery->isPerformed($iObjectId, $iAuthorId) ? true : false;
+
+        $sTmplName = 'report_element_' . (!empty($aParams['usage']) ? $aParams['usage'] : BX_DOL_REPORT_USAGE_DEFAULT) . '.html';
+        return $this->_oTemplate->parseHtmlByName($sTmplName, array(
+            'style_prefix' => $this->_sStylePrefix,
+            'html_id' => $this->_aHtmlIds['main'],
+            'class' => $this->_sStylePrefix . ($bShowDoReportAsButton ? '-button' : '') . ($bShowDoReportAsButtonSmall ? '-button-small' : ''),
+            'count' => $aReport['count'],
+            'do_report' => $this->_getDoReport($aParams),
+            'bx_if:show_counter' => array(
+                'condition' => $bShowCounter,
+                'content' => array(
+                    'style_prefix' => $this->_sStylePrefix,
+        			'bx_if:show_hidden' => array(
+        				'condition' => (int)$aReport['count'] == 0,
+        				'content' => array()
+        			),
+                    'counter' => $this->getCounter()
+                )
+            ),
+            'script' => $this->getJsScript($bDynamicMode)
+        ));
+    }
+
+    protected function _getDoReport($aParams = array())
+    {
+    	$bReported = isset($aParams['is_reported']) && $aParams['is_reported'] === true;
+        $bShowDoReportAsButtonSmall = isset($aParams['show_do_report_as_button_small']) && $aParams['show_do_report_as_button_small'] == true;
+        $bShowDoReportAsButton = !$bShowDoReportAsButtonSmall && isset($aParams['show_do_report_as_button']) && $aParams['show_do_report_as_button'] == true;
+		$bDisabled = !$this->isAllowedReport() || $bReported;
+
+        $sClass = '';
+		if($bShowDoReportAsButton)
+			$sClass = 'bx-btn';
+		else if ($bShowDoReportAsButtonSmall)
+			$sClass = 'bx-btn bx-btn-small';
+
+		if($bDisabled)
+			$sClass .= $bShowDoReportAsButton || $bShowDoReportAsButtonSmall ? ' bx-btn-disabled' : 'bx-report-disabled';
+
+        return $this->_oTemplate->parseHtmlByName($this->_sTmplNameDoReport, array(
+            'style_prefix' => $this->_sStylePrefix,
+        	'html_id' => $this->_aHtmlIds['do_link'],
+            'class' => $sClass,
+            'title' => _t('_report_do_report'),
+        	'bx_if:show_onclick' => array(
+        		'condition' => !$bDisabled,
+        		'content' => array(
+        			'js_object' => $this->getJsObjectName()
+        		)
+        	),
+            'do_report' => $this->_getLabelDoReport($aParams),
+        ));
+    }
+
+    protected function _getLabelCounter($iCount)
+    {
+        return _t('_report_counter', $iCount);
+    }
+
+    protected function _getLabelDoReport($aParams = array())
+    {
+    	$bReported = isset($aParams['is_reported']) && $aParams['is_reported'] === true;
+        return $this->_oTemplate->parseHtmlByName('report_do_report_label.html', array(
+        	'bx_if:show_icon' => array(
+        		'condition' => isset($aParams['show_do_report_icon']) && $aParams['show_do_report_icon'] == true,
+        		'content' => array(
+        			'name' => $this->_getIconDoReport($bReported)
+        		)
+        	),
+        	'bx_if:show_text' => array(
+        		'condition' => isset($aParams['show_do_report_label']) && $aParams['show_do_report_label'] == true,
+        		'content' => array(
+        			'text' => _t($this->_getTitleDoReport($bReported))
+        		)
+        	)
+        ));
+    }
+
+    protected function _getReport()
+    {
+    	if (!$this->isEnabled())
+           return array('code' => 1, 'msg' => _t('_report_err_not_enabled'));
+
+	    if(!$this->isAllowedReport())
+            return array('code' => 2, 'msg' => $this->msgErrAllowedReport());
+
+    	$oForm = $this->_getFormObject();
+		$oForm->setId($this->_aHtmlIds['do_form']);
+		$oForm->setName($this->_aHtmlIds['do_form']);
+		$oForm->aParams['db']['table'] = $this->_aSystem['table_track'];
+        $oForm->aInputs['sys']['value'] = $this->_sSystem;
+        $oForm->aInputs['object_id']['value'] = $this->_iId;
+        $oForm->aInputs['action']['value'] = 'Report';
+
+        $oForm->initChecker();
+        if($oForm->isSubmittedAndValid()) {
+        	$iObjectId = $oForm->getCleanValue('object_id');
+	        $iObjectAuthorId = $this->_oQuery->getObjectAuthorId($iObjectId);
+	        $iAuthorId = $this->_getAuthorId();
+	        $iAuthorNip = ip2long($this->_getAuthorIp());
+
+        	if(!$this->isAllowedReport(true))
+        		return array('code' => 2, 'msg' => $this->msgErrAllowedReport());
+
+	        $bPerformed = $this->_oQuery->isPerformed($iObjectId, $iAuthorId);
+	        if($bPerformed)
+	        	return array('code' => 4, 'msg' => _t('_report_err_duplicate_report'));
+
+			$sType = $oForm->getCleanValue('type');
+	        if(!in_array($sType, $this->_aTypes)) 
+	        	return array('code' => 5, 'msg' => _t('_report_err_wrong_type'));
+
+			$sText = $oForm->getCleanValue('text');
+            $sText = bx_process_input($sText, BX_DATA_TEXT_MULTILINE);
+            $oForm->setSubmittedValue('text', $sText, $oForm->aFormAttrs['method']);
+
+			$iId = (int)$oForm->insert(array('author_id' => $iAuthorId, 'author_nip' => $iAuthorNip, 'date' => time()));
+			if($iId != 0 && $this->_oQuery->putReport($iObjectId)) {
+				$this->_trigger();
+
+		        $oZ = new BxDolAlerts($this->_sSystem, 'doReport', $iObjectId, $iAuthorId, array('report_id' => $iId, 'report_author_id' => $iAuthorId, 'object_author_id' => $iObjectAuthorId, 'type' => $sType, 'text' => $sText));
+		        $oZ->alert();
+		
+		        $oZ = new BxDolAlerts('report', 'do', $iId, $iAuthorId, array('object_system' => $this->_sSystem, 'object_id' => $iObjectId, 'object_author_id' => $iObjectAuthorId, 'type' => $sType, 'text' => $sText));
+		        $oZ->alert();
+
+		        $aReport = $this->_oQuery->getReport($iObjectId);
+		        return array(
+		        	'eval' => $this->getJsObjectName() . '.onReport(oData, oElement)',
+		        	'code' => 0,
+		        	'id' => $iId, 
+		        	'count' => $aReport['count'], 
+		        	'countf' => (int)$aReport['count'] > 0 ? $this->_getLabelCounter($aReport['count']) : '',
+		        	'label_icon' => $this->_getIconDoReport(!$bPerformed),
+		        	'label_title' => _t($this->_getTitleDoReport(!$bPerformed)),
+		        	'disabled' => !$bPerformed
+		        );
+			}
+
+			return array('code' => 3, 'msg' => _t('_report_err_cannot_perform_action'));
+        }
+
+        $sPopupId = $this->_aHtmlIds['do_popup'];
+        $sPopupContent = BxTemplFunctions::getInstance()->transBox($sPopupId, $this->_oTemplate->parseHtmlByName('report_do_report_form.html', array(
+            'style_prefix' => $this->_sStylePrefix,
+        	'js_object' => $this->getJsObjectName(),
+        	'form' => $oForm->getCode(),
+        	'form_id' => $oForm->id,
+        )));
+
+        return array('popup' => $sPopupContent, 'popup_id' => $sPopupId);
+    }
+
+    protected function _getReportedBy()
+    {
+        $aTmplReports = array();
+        $aTypes = BxDolForm::getDataItems('sys_report_types');
+
+        $aReports = $this->_oQuery->getPerformedBy($this->getId());
+        foreach($aReports as $aReport) {
+            list($sUserName, $sUserUrl, $sUserIcon, $sUserUnit) = $this->_getAuthorInfo($aReport['author_id']);
+
+            $sText = bx_process_output($aReport['text'], BX_DATA_TEXT_MULTILINE);
+
+            $aTmplReports[] = array(
+                'style_prefix' => $this->_sStylePrefix,
+                'user_unit' => $sUserUnit,
+            	'type' => $aTypes[$aReport['type']],
+            	'bx_if:show_text' => array(
+            		'condition' => strlen($sText) > 0,
+            		'content' => array(
+            			'text' => $sText
+            		)
+            	)
+            );
+        }
+
+        if(empty($aTmplReports))
+            $aTmplReports = MsgBox(_t('_Empty'));
+
+        return $this->_oTemplate->parseHtmlByName('report_by_list.html', array(
+            'style_prefix' => $this->_sStylePrefix,
+            'bx_repeat:list' => $aTmplReports
+        ));
+    }
+
+    protected function _echoResultJson($a, $isAutoWrapForFormFileSubmit = false)
+    {
+        header('Content-type: text/html; charset=utf-8');
+
+        $s = json_encode($a);
+        if ($isAutoWrapForFormFileSubmit && !empty($_FILES))
+            $s = '<textarea>' . $s . '</textarea>'; // http://jquery.malsup.com/form/#file-upload
+        echo $s;
+    }
+}
+
+/** @} */