/**
 * Checks if a given action is allowed for a given member and updates action information if the
 * action is performed.
 *
 * @param int     $iMemberId        - ID of a member that is going to perform an action
 * @param int     $actionID         - ID of the action itself
 * @param boolean $performAction    - if true, then action information is updated, i.e. action
 *                                  is 'performed'
 *
 * @return array(    CHECK_ACTION_RESULT => CHECK_ACTION_RESULT_ constant,
 *                    CHECK_ACTION_MESSAGE => CHECK_ACTION_MESSAGE_ constant,
 *                    CHECK_ACTION_PARAMETER => additional action parameter (string) )
 *
 *
 * NOTES:
 *
 * $result[CHECK_ACTION_MESSAGE] contains a message with detailed information about the result,
 * already processed by the language file
 *
 * if $result[CHECK_ACTION_RESULT] == CHECK_ACTION_RESULT_ALLOWED then this node contains
 * an empty string
 *
 * The error messages themselves are stored in the language file. Additional variables are
 * passed to the languages.inc.php function _t_ext() as an array and can be used there in the form of
 * {0}, {1}, {2} ...
 *
 * Additional variables passed to the lang. file on errors (can be used in error messages):
 *
 *    For all errors:
 *
 *        $arg0[CHECK_ACTION_LANG_FILE_ACTION]    = name of the action
 *        $arg0[CHECK_ACTION_LANG_FILE_MEMBERSHIP]= name of the current membership
 *
 *    CHECK_ACTION_RESULT_LIMIT_REACHED:
 *
 *        $arg0[CHECK_ACTION_LANG_FILE_LIMIT]        = limit on number of actions allowed for the member
 *        $arg0[CHECK_ACTION_LANG_FILE_PERIOD]    = period that the limit is set for (in hours, 0 if unlimited)
 *
 *    CHECK_ACTION_RESULT_NOT_ALLOWED_BEFORE:
 *
 *        $arg0[CHECK_ACTION_LANG_FILE_BEFORE]    = date/time since when the action is allowed
 *
 *    CHECK_ACTION_RESULT_NOT_ALLOWED_AFTER:
 *
 *        $arg0[CHECK_ACTION_LANG_FILE_AFTER]        = date/time since when the action is not allowed
 *
 * $result[CHECK_ACTION_PARAMETER] contains an additional parameter that can be considered
 * when performing the action (like the number of profiles to show in search result)
 */
function checkAction($iMemberId, $actionID, $performAction = false, $iForcedProfID = 0, $isCheckMemberStatus = true)
{
    global $logged;
    global $site;
    //output array initialization
    $result = array();
    $arrLangFileParams = array();
    $dateFormat = "F j, Y, g:i a";
    //used when displaying error messages
    //input validation
    $iMemberId = (int) $iMemberId;
    $actionID = (int) $actionID;
    $performAction = $performAction ? true : false;
    //get current member's membership information
    $arrMembership = getMemberMembershipInfo($iMemberId);
    $arrLangFileParams[CHECK_ACTION_LANG_FILE_MEMBERSHIP] = $arrMembership['Name'];
    $arrLangFileParams[CHECK_ACTION_LANG_FILE_SITE_EMAIL] = $site['email'];
    //profile active check
    if ($arrMembership['ID'] != MEMBERSHIP_ID_NON_MEMBER || $logged['admin'] || $logged['moderator']) {
        $iDestID = $iMemberId;
        if ((isAdmin() || isModerator()) && $iForcedProfID > 0) {
            $iDestID = $iForcedProfID;
            $performAction = false;
        }
        if ($isCheckMemberStatus) {
            $active = getProfileInfo($iDestID);
            if ($active['Status'] != 'Active') {
                $result[CHECK_ACTION_RESULT] = CHECK_ACTION_RESULT_NOT_ACTIVE;
                $result[CHECK_ACTION_MESSAGE] = _t_ext(CHECK_ACTION_MESSAGE_NOT_ACTIVE, $arrLangFileParams);
                return $result;
            }
        }
    }
    //get permissions for the current action
    $resMembershipAction = db_res("\n        SELECT\tName,\n                IDAction,\n                AllowedCount,\n                AllowedPeriodLen,\n                UNIX_TIMESTAMP(AllowedPeriodStart) as AllowedPeriodStart,\n                UNIX_TIMESTAMP(AllowedPeriodEnd) as AllowedPeriodEnd,\n                AdditionalParamValue\n        FROM\t`sys_acl_actions`\n                LEFT JOIN `sys_acl_matrix`\n                ON\t`sys_acl_matrix`.IDAction = `sys_acl_actions`.ID\n                    AND `sys_acl_matrix`.IDLevel = {$arrMembership['ID']}\n        WHERE\t`sys_acl_actions`.ID = {$actionID}");
    //no such action
    if ($resMembershipAction->rowCount() < 1) {
        echo "<br /><b>checkAction()</b> fatal error. Unknown action ID: {$actionID}<br />";
        exit;
    }
    $arrAction = $resMembershipAction->fetch();
    $result[CHECK_ACTION_PARAMETER] = $arrAction['AdditionalParamValue'];
    $arrLangFileParams[CHECK_ACTION_LANG_FILE_ACTION] = _t('_mma_' . str_replace(' ', '_', $arrAction['Name']));
    //action is not allowed for the current membership
    if (is_null($arrAction['IDAction'])) {
        $result[CHECK_ACTION_RESULT] = CHECK_ACTION_RESULT_NOT_ALLOWED;
        $result[CHECK_ACTION_MESSAGE] = _t_ext(CHECK_ACTION_MESSAGE_NOT_ALLOWED, $arrLangFileParams);
        return $result;
    }
    //Check fixed period limitations if present (also for non-members)
    if ($arrAction['AllowedPeriodStart'] && time() < $arrAction['AllowedPeriodStart']) {
        $arrLangFileParams[CHECK_ACTION_LANG_FILE_BEFORE] = date($dateFormat, $arrAction['AllowedPeriodStart']);
        $result[CHECK_ACTION_RESULT] = CHECK_ACTION_RESULT_NOT_ALLOWED_BEFORE;
        $result[CHECK_ACTION_MESSAGE] = _t_ext(CHECK_ACTION_MESSAGE_NOT_ALLOWED_BEFORE, $arrLangFileParams);
        return $result;
    }
    if ($arrAction['AllowedPeriodEnd'] && time() > $arrAction['AllowedPeriodEnd']) {
        $arrLangFileParams[CHECK_ACTION_LANG_FILE_AFTER] = date($dateFormat, $arrAction['AllowedPeriodEnd']);
        $result[CHECK_ACTION_RESULT] = CHECK_ACTION_RESULT_NOT_ALLOWED_AFTER;
        $result[CHECK_ACTION_MESSAGE] = _t_ext(CHECK_ACTION_MESSAGE_NOT_ALLOWED_AFTER, $arrLangFileParams);
        return $result;
    }
    //if non-member, allow action without performing further checks
    if ($arrMembership['ID'] == MEMBERSHIP_ID_NON_MEMBER) {
        $result[CHECK_ACTION_RESULT] = CHECK_ACTION_RESULT_ALLOWED;
        return $result;
    }
    //check other limitations (for members only)
    $allowedCnt = (int) $arrAction['AllowedCount'];
    //number of allowed actions
    //if not specified or 0, number of
    //actions is unlimited
    $periodLen = (int) $arrAction['AllowedPeriodLen'];
    //period for AllowedCount in hours
    //if not specified, AllowedCount is
    //treated as total number of actions
    //permitted
    //number of actions is limited
    if ($allowedCnt > 0) {
        //get current action info for the member
        $actionTrack = db_res("SELECT ActionsLeft,\n                                      UNIX_TIMESTAMP(ValidSince) as ValidSince\n                               FROM `sys_acl_actions_track`\n                               WHERE IDAction = {$actionID} AND IDMember = {$iMemberId}");
        $actionsLeft = $performAction ? $allowedCnt - 1 : $allowedCnt;
        $validSince = time();
        //member is requesting/performing this action for the first time,
        //and there is no corresponding record in sys_acl_actions_track table
        if ($actionTrack->rowCount() <= 0) {
            //add action to sys_acl_actions_track table
            db_res("\n                INSERT INTO `sys_acl_actions_track` (IDAction, IDMember, ActionsLeft, ValidSince)\n                VALUES ({$actionID}, {$iMemberId}, {$actionsLeft}, FROM_UNIXTIME({$validSince}))");
            $result[CHECK_ACTION_RESULT] = CHECK_ACTION_RESULT_ALLOWED;
            return $result;
        }
        //action has been requested/performed at least once at this point
        //and there is a corresponding record in sys_acl_actions_track table
        $actionTrack = $actionTrack->fetch();
        //action record in sys_acl_actions_track table is out of date
        $periodEnd = (int) $actionTrack['ValidSince'] + $periodLen * 3600;
        //ValidSince is in seconds, PeriodLen is in hours
        if ($periodLen > 0 && $periodEnd < time()) {
            db_res("\n                UPDATE\t`sys_acl_actions_track`\n                SET\t\tActionsLeft = {$actionsLeft}, ValidSince = FROM_UNIXTIME({$validSince})\n                WHERE\tIDAction = {$actionID} AND IDMember = {$iMemberId}");
            $result[CHECK_ACTION_RESULT] = CHECK_ACTION_RESULT_ALLOWED;
            return $result;
        }
        //action record is up to date
        $actionsLeft = (int) $actionTrack['ActionsLeft'];
        //action limit reached for now
        if ($actionsLeft <= 0) {
            $arrLangFileParams[CHECK_ACTION_LANG_FILE_LIMIT] = $allowedCnt;
            $arrLangFileParams[CHECK_ACTION_LANG_FILE_PERIOD] = $periodLen;
            $result[CHECK_ACTION_RESULT] = CHECK_ACTION_RESULT_LIMIT_REACHED;
            $result[CHECK_ACTION_MESSAGE] = '<div style="width: 80%">' . _t_ext(CHECK_ACTION_MESSAGE_LIMIT_REACHED, $arrLangFileParams) . ($periodLen > 0 ? _t_ext(CHECK_ACTION_MESSAGE_MESSAGE_EVERY_PERIOD, $arrLangFileParams) : '') . '.</div>';
            return $result;
        }
        if ($performAction) {
            $actionsLeft--;
            db_res("\n                UPDATE `sys_acl_actions_track`\n                SET ActionsLeft = {$actionsLeft}\n                WHERE IDAction = {$actionID} AND IDMember = {$iMemberId}");
        }
    }
    $result[CHECK_ACTION_RESULT] = CHECK_ACTION_RESULT_ALLOWED;
    return $result;
}
Exemple #2
0
 /**
  * Checks if a given action is allowed for a given profile and updates action information if the
  * action is performed.
  *
  * @param  int     $iProfileId     ID of a profile that is going to perform an action
  * @param  int     $iActionId      ID of the action itself
  * @param  boolean $bPerformAction if true, then action information is updated, i.e. action is 'performed'
  * @return array(
  *                                CHECK_ACTION_RESULT => CHECK_ACTION_RESULT_ constant,
  *                                CHECK_ACTION_MESSAGE => CHECK_ACTION_MESSAGE_ constant,
  *                                CHECK_ACTION_PARAMETER => additional action parameter (string)
  *                                )
  *
  * NOTES:
  *
  * $aResult[CHECK_ACTION_MESSAGE] contains a message with detailed information about the result,
  * already processed by the language file
  *
  * if $aResult[CHECK_ACTION_RESULT] === CHECK_ACTION_RESULT_ALLOWED then this node contains
  * an empty string
  *
  * The error messages themselves are stored in the language file. Additional variables are
  * passed to the languages.inc.php function _t_ext() as an array and can be used there in the form of
  * {0}, {1}, {2} ...
  *
  * Additional variables passed to the lang. file on errors (can be used in error messages):
  *
  * 	For all errors:
  *
  * 		$arg0[CHECK_ACTION_LANG_FILE_ACTION]	= name of the action
  * 		$arg0[CHECK_ACTION_LANG_FILE_MEMBERSHIP]= name of the current membership
  *
  * 	CHECK_ACTION_RESULT_LIMIT_REACHED:
  *
  * 		$arg0[CHECK_ACTION_LANG_FILE_LIMIT]		= limit on number of actions allowed for the profile
  * 		$arg0[CHECK_ACTION_LANG_FILE_PERIOD]	= period that the limit is set for (in hours, 0 if unlimited)
  *
  * 	CHECK_ACTION_RESULT_NOT_ALLOWED_BEFORE:
  *
  * 		$arg0[CHECK_ACTION_LANG_FILE_BEFORE]	= date/time since when the action is allowed
  *
  * 	CHECK_ACTION_RESULT_NOT_ALLOWED_AFTER:
  *
  * 		$arg0[CHECK_ACTION_LANG_FILE_AFTER]		= date/time since when the action is not allowed
  *
  * $aResult[CHECK_ACTION_PARAMETER] contains an additional parameter that can be considered
  * when performing the action (like the number of profiles to show in search result)
  */
 function checkAction($iProfileId, $iActionId, $bPerformAction = false)
 {
     $aResult = array();
     $aLangFileParams = array();
     $iProfileId = (int) $iProfileId;
     $iActionId = (int) $iActionId;
     $bPerformAction = $bPerformAction ? true : false;
     $aMembership = $this->getMemberMembershipInfo($iProfileId);
     // get current profile's membership information
     $aLangFileParams[CHECK_ACTION_LANG_FILE_MEMBERSHIP] = _t($aMembership['name']);
     $aLangFileParams[CHECK_ACTION_LANG_FILE_SITE_EMAIL] = getParam('site_email');
     $aAction = $this->oDb->getAction($aMembership['id'], $iActionId);
     if (!$aAction) {
         bx_trigger_error('Unknown action ID: ' . $iActionId, 2);
     }
     $aResult[CHECK_ACTION_PARAMETER] = $aAction['additional_param_value'];
     $aLangFileParams[CHECK_ACTION_LANG_FILE_ACTION] = !empty($aAction['title']) ? _t($aAction['title']) : $aAction['name'];
     /**
      * Action is not allowed for the current membership
      */
     if (is_null($aAction['id'])) {
         $sLangKey = CHECK_ACTION_MESSAGE_NOT_ALLOWED;
         if (isset($this->_aLevel2MessageMap[$aMembership['id']])) {
             $sLangKey = $this->_aLevel2MessageMap[$aMembership['id']];
         }
         $aResult[CHECK_ACTION_RESULT] = CHECK_ACTION_RESULT_NOT_ALLOWED;
         $aResult[CHECK_ACTION_MESSAGE] = _t_ext($sLangKey, $aLangFileParams);
         return $aResult;
     }
     /**
      * Check fixed period limitations if present (also for non-members)
      */
     if ($aAction['allowed_period_start'] && time() < $aAction['allowed_period_start']) {
         $aLangFileParams[CHECK_ACTION_LANG_FILE_BEFORE] = bx_time_js($aAction['allowed_period_start'], BX_FORMAT_DATE_TIME);
         $aResult[CHECK_ACTION_RESULT] = CHECK_ACTION_RESULT_NOT_ALLOWED_BEFORE;
         $aResult[CHECK_ACTION_MESSAGE] = _t_ext(CHECK_ACTION_MESSAGE_NOT_ALLOWED_BEFORE, $aLangFileParams);
         return $aResult;
     }
     if ($aAction['allowed_period_end'] && time() > $aAction['allowed_period_end']) {
         $aLangFileParams[CHECK_ACTION_LANG_FILE_AFTER] = bx_time_js($aAction['allowed_period_end'], BX_FORMAT_DATE_TIME);
         $aResult[CHECK_ACTION_RESULT] = CHECK_ACTION_RESULT_NOT_ALLOWED_AFTER;
         $aResult[CHECK_ACTION_MESSAGE] = _t_ext(CHECK_ACTION_MESSAGE_NOT_ALLOWED_AFTER, $aLangFileParams);
         return $aResult;
     }
     /**
      * if non-member, allow action without performing further checks
      */
     if ($aMembership['id'] == MEMBERSHIP_ID_NON_MEMBER) {
         $aResult[CHECK_ACTION_RESULT] = CHECK_ACTION_RESULT_ALLOWED;
         return $aResult;
     }
     /**
      * Check other limitations (for members only)
      */
     $iAllowedCnt = (int) $aAction['allowed_count'];
     ///< Number of allowed actions. Unlimited if not specified or 0
     $iPeriodLen = (int) $aAction['allowed_period_len'];
     ///< Period for AllowedCount in hours. If not specified, AllowedCount is treated as total number of actions permitted.
     if ($iAllowedCnt > 0) {
         $aActionTrack = $this->oDb->getActionTrack($iActionId, $iProfileId);
         $iActionsLeft = $bPerformAction ? $iAllowedCnt - 1 : $iAllowedCnt;
         $iValidSince = time();
         /**
          * Member is requesting/performing this action for the first time,
          * and there is no corresponding record in sys_acl_actions_track table.
          */
         if (!$aActionTrack) {
             $this->oDb->insertActionTarck($iActionId, $iProfileId, $iActionsLeft, $iValidSince);
             $aResult[CHECK_ACTION_RESULT] = CHECK_ACTION_RESULT_ALLOWED;
             return $aResult;
         }
         /**
          * Action has been requested/performed at least once at this point and there is a corresponding record in sys_acl_actions_track table
          *
          * Action record in sys_acl_actions_track table is out of date.
          */
         $iPeriodEnd = (int) $aActionTrack['valid_since'] + $iPeriodLen * 3600;
         //ValidSince is in seconds, PeriodLen is in hours
         if ($iPeriodLen > 0 && $iPeriodEnd < time()) {
             $this->oDb->updateActionTrack($iActionId, $iProfileId, $iActionsLeft, $iValidSince);
             $aResult[CHECK_ACTION_RESULT] = CHECK_ACTION_RESULT_ALLOWED;
             return $aResult;
         }
         $iActionsLeft = (int) $aActionTrack['actions_left'];
         ///< Action record is up to date
         /**
          * Action limit reached for now
          */
         if ($iActionsLeft <= 0) {
             $aLangFileParams[CHECK_ACTION_LANG_FILE_LIMIT] = $iAllowedCnt;
             $aLangFileParams[CHECK_ACTION_LANG_FILE_PERIOD] = $iPeriodLen;
             $aResult[CHECK_ACTION_RESULT] = CHECK_ACTION_RESULT_LIMIT_REACHED;
             $aResult[CHECK_ACTION_MESSAGE] = '<div style="width: 80%">' . _t_ext(CHECK_ACTION_MESSAGE_LIMIT_REACHED, $aLangFileParams) . ($iPeriodLen > 0 ? _t_ext(CHECK_ACTION_MESSAGE_MESSAGE_EVERY_PERIOD, $aLangFileParams) : '') . '.</div>';
             return $aResult;
         }
         if ($bPerformAction) {
             $iActionsLeft--;
             $this->oDb->updateActionTrack($iActionId, $iProfileId, $iActionsLeft);
         }
     }
     $aResult[CHECK_ACTION_RESULT] = CHECK_ACTION_RESULT_ALLOWED;
     return $aResult;
 }
/**
 * Checks if a given action is allowed for a given member and updates action information if the
 * action is performed.
 *
 * @param int $memberID			- ID of a member that is going to perform an action
 * @param int $actionID			- ID of the action itself
 * @param boolean $performAction	- if true, then action information is updated, i.e. action
 * 								  is 'performed'
 *
 * @return array(	CHECK_ACTION_RESULT => CHECK_ACTION_RESULT_ constant,
 * 					CHECK_ACTION_MESSAGE => CHECK_ACTION_MESSAGE_ constant,
 * 					CHECK_ACTION_PARAMETER => additional action parameter (string) )
 *
 *
 * NOTES:
 *
 * $result[CHECK_ACTION_MESSAGE] contains a message with detailed information about the result,
 * already processed by the language file
 *
 * if $result[CHECK_ACTION_RESULT] == CHECK_ACTION_RESULT_ALLOWED then this node contains
 * an empty string
 *
 * The error messages themselves are stored in the language file. Additional variables are
 * passed to the languages.inc.php function _t_ext() as an array and can be used there in the form of
 * {0}, {1}, {2} ...
 *
 * Additional variables passed to the lang. file on errors (can be used in error messages):
 *
 * 	For all errors:
 *
 * 		$arg0[CHECK_ACTION_LANG_FILE_ACTION]	= name of the action
 * 		$arg0[CHECK_ACTION_LANG_FILE_MEMBERSHIP]= name of the current membership
 *
 * 	CHECK_ACTION_RESULT_LIMIT_REACHED:
 *
 * 		$arg0[CHECK_ACTION_LANG_FILE_LIMIT]		= limit on number of actions allowed for the member
 * 		$arg0[CHECK_ACTION_LANG_FILE_PERIOD]	= period that the limit is set for (in hours, 0 if unlimited)
 *
 * 	CHECK_ACTION_RESULT_NOT_ALLOWED_BEFORE:
 *
 * 		$arg0[CHECK_ACTION_LANG_FILE_BEFORE]	= date/time since when the action is allowed
 *
 * 	CHECK_ACTION_RESULT_NOT_ALLOWED_AFTER:
 *
 * 		$arg0[CHECK_ACTION_LANG_FILE_AFTER]		= date/time since when the action is not allowed
 *
 * $result[CHECK_ACTION_PARAMETER] contains an additional parameter that can be considered
 * when performing the action (like the number of profiles to show in search result)
*/
function checkAction($memberID, $actionID, $performAction = false)
{
    global $site;
    //output array initialization
    $result = array();
    $arrLangFileParams = array();
    $dateFormat = "F j, Y, g:i a";
    //used when displaying error messages
    //input validation
    $memberID = (int) $memberID;
    $actionID = (int) $actionID;
    $performAction = $performAction ? true : false;
    //get current member's membership information
    $arrMembership = getMemberMembershipInfo($memberID);
    $arrLangFileParams[CHECK_ACTION_LANG_FILE_MEMBERSHIP] = $arrMembership['Name'];
    $arrLangFileParams[CHECK_ACTION_LANG_FILE_SITE_EMAIL] = $site['email'];
    //profile active check
    if ($arrMembership['ID'] != MEMBERSHIP_ID_NON_MEMBER) {
        $active = getProfileInfo($memberID);
        $active = $active['Status'] == 'Active';
        if (!$active) {
            $result[CHECK_ACTION_RESULT] = CHECK_ACTION_RESULT_NOT_ACTIVE;
            $result[CHECK_ACTION_MESSAGE] = _t_ext(CHECK_ACTION_MESSAGE_NOT_ACTIVE, $arrLangFileParams);
            return $result;
        }
    }
    //free mode check
    if (getParam("free_mode") == "on") {
        $result[CHECK_ACTION_RESULT] = CHECK_ACTION_RESULT_ALLOWED;
        return $result;
    }
    //get permissions for the current action
    $resMembershipAction = db_res("\r\n\t\tSELECT\tName,\r\n\t\t\t\tIDAction,\r\n\t\t\t\tAllowedCount,\r\n\t\t\t\tAllowedPeriodLen,\r\n\t\t\t\tUNIX_TIMESTAMP(AllowedPeriodStart) as AllowedPeriodStart,\r\n\t\t\t\tUNIX_TIMESTAMP(AllowedPeriodEnd) as AllowedPeriodEnd,\r\n\t\t\t\tAdditionalParamValue\r\n\t\tFROM\tMemActions\r\n\t\t\t\tLEFT JOIN MemLevelActions\r\n\t\t\t\tON\tMemLevelActions.IDAction = MemActions.ID\r\n\t\t\t\t\tAND MemLevelActions.IDLevel = {$arrMembership['ID']}\r\n\t\tWHERE\tMemActions.ID = {$actionID}");
    //no such action
    if (mysql_num_rows($resMembershipAction) < 1) {
        echo "<br /><b>checkAction()</b> fatal error. Unknown action ID: {$actionID}<br />";
        exit;
    }
    $arrAction = mysql_fetch_assoc($resMembershipAction);
    $result[CHECK_ACTION_PARAMETER] = $arrAction['AdditionalParamValue'];
    $arrLangFileParams[CHECK_ACTION_LANG_FILE_ACTION] = _t('_' . $arrAction['Name']);
    //action is not allowed for the current membership
    if (is_null($arrAction['IDAction'])) {
        $result[CHECK_ACTION_RESULT] = CHECK_ACTION_RESULT_NOT_ALLOWED;
        $result[CHECK_ACTION_MESSAGE] = _t_ext(CHECK_ACTION_MESSAGE_NOT_ALLOWED, $arrLangFileParams);
        return $result;
    }
    //Check fixed period limitations if present (also for non-members)
    if ($arrAction['AllowedPeriodStart'] && time() < $arrAction['AllowedPeriodStart']) {
        $arrLangFileParams[CHECK_ACTION_LANG_FILE_BEFORE] = date($dateFormat, $arrAction['AllowedPeriodStart']);
        $result[CHECK_ACTION_RESULT] = CHECK_ACTION_RESULT_NOT_ALLOWED_BEFORE;
        $result[CHECK_ACTION_MESSAGE] = _t_ext(CHECK_ACTION_MESSAGE_NOT_ALLOWED_BEFORE, $arrLangFileParams);
        return $result;
    }
    if ($arrAction['AllowedPeriodEnd'] && time() > $arrAction['AllowedPeriodEnd']) {
        $arrLangFileParams[CHECK_ACTION_LANG_FILE_AFTER] = date($dateFormat, $arrAction['AllowedPeriodEnd']);
        $result[CHECK_ACTION_RESULT] = CHECK_ACTION_RESULT_NOT_ALLOWED_AFTER;
        $result[CHECK_ACTION_MESSAGE] = _t_ext(CHECK_ACTION_MESSAGE_NOT_ALLOWED_AFTER, $arrLangFileParams);
        return $result;
    }
    //if non-member, allow action without performing further checks
    if ($arrMembership['ID'] == MEMBERSHIP_ID_NON_MEMBER) {
        $result[CHECK_ACTION_RESULT] = CHECK_ACTION_RESULT_ALLOWED;
        return $result;
    }
    //check other limitations (for members only)
    $allowedCnt = (int) $arrAction['AllowedCount'];
    //number of allowed actions
    //if not specified or 0, number of
    //actions is unlimited
    $periodLen = (int) $arrAction['AllowedPeriodLen'];
    //period for AllowedCount in hours
    //if not specified, AllowedCount is
    //treated as total number of actions
    //permitted
    //number of actions is limited
    if ($allowedCnt > 0) {
        //get current action info for the member
        $actionTrack = db_res("SELECT ActionsLeft,\r\n\t\t\t\t\t\t\t\t\t  UNIX_TIMESTAMP(ValidSince) as ValidSince\r\n\t\t\t\t\t\t\t   FROM MemActionsTrack\r\n\t\t\t\t\t\t\t   WHERE IDAction = {$actionID} AND IDMember = {$memberID}");
        $actionsLeft = $performAction ? $allowedCnt - 1 : $allowedCnt;
        $validSince = time();
        //member is requesting/performing this action for the first time,
        //and there is no corresponding record in MemActionsTrack table
        if (mysql_num_rows($actionTrack) <= 0) {
            //add action to MemActionsTrack table
            db_res("\r\n\t\t\t\tINSERT INTO MemActionsTrack (IDAction, IDMember, ActionsLeft, ValidSince)\r\n\t\t\t\tVALUES ({$actionID}, {$memberID}, {$actionsLeft}, FROM_UNIXTIME({$validSince}))");
            $result[CHECK_ACTION_RESULT] = CHECK_ACTION_RESULT_ALLOWED;
            return $result;
        }
        //action has been requested/performed at least once at this point
        //and there is a corresponding record in MemActionsTrack table
        $actionTrack = mysql_fetch_assoc($actionTrack);
        //action record in MemActionsTrack table is out of date
        $periodEnd = (int) $actionTrack['ValidSince'] + $periodLen * 3600;
        //ValidSince is in seconds, PeriodLen is in hours
        if ($periodLen > 0 && $periodEnd < time()) {
            db_res("\r\n\t\t\t\tUPDATE\tMemActionsTrack\r\n\t\t\t\tSET\t\tActionsLeft = {$actionsLeft}, ValidSince = FROM_UNIXTIME({$validSince})\r\n\t\t\t\tWHERE\tIDAction = {$actionID} AND IDMember = {$memberID}");
            $result[CHECK_ACTION_RESULT] = CHECK_ACTION_RESULT_ALLOWED;
            return $result;
        }
        //action record is up to date
        $actionsLeft = (int) $actionTrack['ActionsLeft'];
        //action limit reached for now
        if ($actionsLeft <= 0) {
            $arrLangFileParams[CHECK_ACTION_LANG_FILE_LIMIT] = $allowedCnt;
            $arrLangFileParams[CHECK_ACTION_LANG_FILE_PERIOD] = $periodLen;
            $result[CHECK_ACTION_RESULT] = CHECK_ACTION_RESULT_LIMIT_REACHED;
            $result[CHECK_ACTION_MESSAGE] = '<div style="width: 80%">' . _t_ext(CHECK_ACTION_MESSAGE_LIMIT_REACHED, $arrLangFileParams) . ($periodLen > 0 ? _t_ext(CHECK_ACTION_MESSAGE_MESSAGE_EVERY_PERIOD, $arrLangFileParams) : '') . '.</div>';
            return $result;
        }
        if ($performAction) {
            $actionsLeft--;
            db_res("\r\n\t\t\t\tUPDATE MemActionsTrack\r\n\t\t\t\tSET ActionsLeft = {$actionsLeft}\r\n\t\t\t\tWHERE IDAction = {$actionID} AND IDMember = {$memberID}");
        }
    }
    $result[CHECK_ACTION_RESULT] = CHECK_ACTION_RESULT_ALLOWED;
    return $result;
}