<?php /*

 Composr
 Copyright (c) Christopher Graham, 2004-2024

 See docs/LICENSE.md for full licensing information.


 NOTE TO PROGRAMMERS:
   Do not edit this file. If you need to make changes, save your changed file to the appropriate *_custom folder
   **** If you ignore this advice, then your website upgrades (e.g. for bug fixes) will likely kill your changes ****

*/

/**
 * @license    http://opensource.org/licenses/cpal_1.0 Common Public Attribution License
 * @copyright  Christopher Graham
 * @package    core
 */

/**
 * Find whether some content is validated.
 *
 * @param  ID_TEXT $content_type Content type
 * @param  ID_TEXT $content_id Content ID
 * @return boolean Whether it is validated
 */
function content_validated(string $content_type, string $content_id) : bool
{
    if (!addon_installed('validation')) {
        return true;
    }

    require_code('content');
    list(, , $cma_info, $content_row,) = content_get_details($content_type, $content_id);
    if ($content_row === null) {
        return false;
    }
    return ($content_row[$cma_info['validated_field']] == 1);
}

/**
 * Send a "your content has been validated" notification out to the submitter of some content. Only call if this is true ;).
 *
 * @param  ID_TEXT $content_type Content type
 * @param  ID_TEXT $content_id Content ID
 * @param  integer $points_credited If points were not credited until after validation, specify how many points were credited (<=0: no mention of points will be included in this notification)
 */
function send_content_validated_notification(string $content_type, string $content_id, int $points_credited = 0)
{
    if (!addon_installed('validation')) {
        warn_exit(do_lang_tempcode('INTERNAL_ERROR', escape_html('577079bcc5ed5050b9ddcc9cf497ab22')));
    }

    require_code('content');
    list($content_title, $submitter_id, , , , $content_url_safe) = content_get_details($content_type, $content_id);

    if ($content_url_safe !== null) {
        require_code('notifications');
        require_lang('validation');
        $subject = do_lang('CONTENT_VALIDATED_NOTIFICATION_MAIL_SUBJECT', $content_title, get_site_name());
        $mail = do_notification_lang('CONTENT_VALIDATED_NOTIFICATION_MAIL', comcode_escape(get_site_name()), comcode_escape($content_title), [$content_url_safe->evaluate()]);
        if (addon_installed('points') && ($points_credited > 0)) {
            $mail .= do_notification_lang('CONTENT_VALIDATED_NOTIFICATION_MAIL_SUP_POINTS', comcode_escape(integer_format($points_credited, 0)));
        }
        dispatch_notification('content_validated', null, $subject, $mail, [$submitter_id]);
    }
}

/**
 * Send (by e-mail) a validation request for a submitted item to the admin.
 *
 * @param  ID_TEXT $type The validation request will say one of this type has been submitted. By convention it is the language string codename of what was done, e.g. ADD_DOWNLOAD
 * @param  ID_TEXT $table The table saved into
 * @param  boolean $non_integer_id Whether the ID field is not an integer
 * @param  ID_TEXT $id The validation request will say this ID has been submitted
 * @param  Tempcode $url The validation request will link to this URL
 * @param  ?MEMBER $member_id Member doing the submitting (null: current member)
 */
function send_validation_request(string $type, string $table, bool $non_integer_id, string $id, object $url, ?int $member_id = null)
{
    if (!addon_installed('validation')) {
        warn_exit(do_lang_tempcode('INTERNAL_ERROR', escape_html('f3723d966e8b5889afbcf6495191f248')));
    }

    require_code('content');
    require_code('notifications');
    require_lang('validation');

    $content_type = convert_cms_type_codes('table', $table, 'content_type');
    $cma_ob = get_content_object($content_type);
    if (!is_object($cma_ob)) {
        warn_exit(do_lang_tempcode('INTERNAL_ERROR', escape_html('a37d9eec627f5924939c5788a5d2ce1a')));
    }

    $row = $cma_ob->get_row($non_integer_id ? $id : strval($id));
    $title = $cma_ob->get_title($row);
    $id_string = $cma_ob->get_id_string($row);
    $content_type_label = $cma_ob->get_content_type_label($row);

    if ($member_id === null) {
        $member_id = get_member();
    }

    $_type = do_lang($type, null, null, null, null, false);
    if ($_type !== null) {
        $type = $_type;
    }

    $comcode = do_notification_template('VALIDATION_REQUEST_MAIL', [
        '_GUID' => '1885be371b2ff7810287715ef2f7b948',
        'USERNAME' => $GLOBALS['FORUM_DRIVER']->get_username($member_id),
        'CONTENT_TYPE_LABEL' => $content_type_label,
        'TITLE' => $title,
        'TYPE' => $type,
        'ID' => $id_string,
        'URL' => $url,
    ], get_site_default_lang(), false, null, '.txt', 'text');

    $subject = do_lang('NOT_VALIDATED_TITLE', $title, '', '', get_site_default_lang());
    $message = $comcode->evaluate(get_site_default_lang());
    dispatch_notification('needs_validation', null, $subject, $message, null, $member_id, ['use_real_from' => true]);
}

/**
 * Credit points to a member for submitting something, then returns the HTML page to say so.
 *
 * @param  ID_TEXT $type One of this type has been submitted. By convention it is the language string codename of what was done, e.g. ADD_DOWNLOAD
 * @param  ID_TEXT $content_type The content type submitted
 * @param  ID_TEXT $content_id The content ID that was submitted
 * @param  ?MEMBER $member_id The member to give the points to (null: give to current member)
 * @return ?string A message about the member being given these submit points (null: no message)
 */
function give_submit_points(string $type, string $content_type, string $content_id, ?int $member_id = null) : ?string
{
    if ($member_id === null) {
        $member_id = get_member();
    }
    if ((!is_guest($member_id)) && (addon_installed('points'))) {
        // FUDGE
        if ($type == 'ADD_NEWS_BLOG') {
            $type = 'ADD_NEWS';
        }

        $points = get_option('points_' . $type, true);
        if ($points === null || intval($points) <= 0) {
            return null;
        }

        require_code('points');
        $already_awarded = $GLOBALS['SITE_DB']->query_select_value_if_there('points_ledger', 'id', ['status' => LEDGER_STATUS_NORMAL, 'receiving_member' => $member_id, 't_type' => $content_type, 't_subtype' => 'add', 't_type_id' => strval($content_id)]);
        if ($already_awarded === null) {
            require_code('content');
            require_code('points2');

            // Get our reason
            list($title) = content_get_details($content_type, $content_id);
            $lang_string = do_lang('ACTIVITY_' . $type, $title, null, null, null, false);
            if ($lang_string === null) {
                $lang_string = do_lang($type, null, null, null, null, false);
            }
            if ($lang_string === null) {
                $lang_string = $type;
            }

            // Credit points
            points_credit_member($member_id, $lang_string, intval($points), 0, true, 0, $content_type, 'add', strval($content_id));
            return do_lang('SUBMIT_AWARD', integer_format(intval($points), 0));
        }
    }
    return null;
}

/**
 * Find a member from their IP address. Unlike plain $GLOBALS['FORUM_DRIVER']->probe_ip, it has the benefit of looking in the actionlogs and stats tables also.
 *
 * @param  IP $ip The IP address to probe
 * @return array The member IDs found
 */
function wrap_probe_ip(string $ip) : array
{
    if (strpos($ip, '*') !== false) {
        $a = $GLOBALS['SITE_DB']->query('SELECT DISTINCT member_id AS id FROM ' . get_table_prefix() . 'actionlogs WHERE ip LIKE \'' . db_encode_like(str_replace('*', '%', $ip)) . '\'');
    } else {
        $a = $GLOBALS['SITE_DB']->query_select('actionlogs', ['DISTINCT member_id AS id'], ['ip' => $ip]);
    }

    if (addon_installed('stats')) {
        $b = $GLOBALS['SITE_DB']->query_select('stats', ['DISTINCT member_id AS id'], ['ip' => $ip]);
    } else {
        $b = [];
    }

    $c = $GLOBALS['FORUM_DRIVER']->probe_ip($ip);

    $guest_id = $GLOBALS['FORUM_DRIVER']->get_guest_id();

    $member_ids = [];
    foreach (array_merge($a, $b, $c) as $x) {
        if ($x['id'] != $guest_id) {
            $member_ids[] = $x['id'];
        }
    }
    return array_unique($member_ids);
}

/**
 * Ban the specified IP address.
 *
 * @param  IP $ip The IP address to ban
 * @param  LONG_TEXT $descrip Explanation for ban
 */
function wrap_add_ip_ban(string $ip, string $descrip = '')
{
    $ban = trim($ip);
    if (($ban != '') && (!compare_ip_address($ban, get_ip_address()))) {
        require_code('failure');
        add_ip_ban($ban, $descrip, null, true, true); // Forced as it is usually manually triggered

        log_it('IP_BANNED', $ip);
    } elseif (compare_ip_address($ban, get_ip_address())) {
        if (addon_installed('securitylogging')) {
            require_lang('submitban');
            attach_message(do_lang_tempcode('AVOIDING_BANNING_SELF'), 'warn');
        }
    }
}

/**
 * Unban the specified IP address.
 *
 * @param  IP $ip The IP address to unban
 */
function wrap_remove_ip_ban(string $ip)
{
    require_code('failure');

    $unban = trim($ip);
    remove_ip_ban($unban);

    log_it('IP_UNBANNED', $ip);
}
