<?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    points
 */

/**
 * Hook class.
 */
class Hook_cns_warnings_points
{
    /**
     * Get details for this hook.
     *
     * @return ?array The details (null: hook disabled)
     */
    public function get_details() : ?array
    {
        if (!addon_installed('cns_warnings') || !addon_installed('points')) {
            return null;
        }

        return [
            'order' => 299,
        ];
    }

    /**
     * Generate punitive action text from a punitive action database row.
     *
     * @param  array $row The database row
     * @return string The punitive action text
     */
    public function generate_text(array $row) : string
    {
        if (!addon_installed('cns_warnings') || !addon_installed('points')) {
            return '';
        }

        require_lang('cns_warnings');

        switch ($row['p_action']) {
            case '_PUNITIVE_CHARGE_POINTS':
                return do_lang('_PUNITIVE_CHARGE_POINTS', integer_format(intval($row['p_param_a'])));

            default:
                return '';
        }
    }

    /**
     * Render form fields for the warnings screen.
     *
     * @param  Tempcode $add_text Tempcode to be included on the intro paragraph of the warnings screen (passed by reference)
     * @param  Tempcode $fields The fields to be rendered (passed by reference)
     * @param  Tempcode $hidden The hidden fields to be included (passed by reference)
     * @param  boolean $new Whether it is a new warning/punishment record
     * @param  LONG_TEXT $explanation The explanation for the warning/punishment record
     * @param  BINARY $is_warning Whether to make this a formal warning
     * @param  MEMBER $member_id The member the warning is for
     * @param  BINARY $spam_mode Whether this is a spam warning
     * @param  ?AUTO_LINK $post_id The ID of the forum post of which we clicked warn (null: we are not warning on a forum post)
     * @param  ?SHORT_TEXT $ip_address The IP address of the poster (null: we are not warning on a forum post)
     */
    public function get_form_fields(object &$add_text, object &$fields, object &$hidden, bool $new, string $explanation, int $is_warning, int $member_id, int $spam_mode, ?int $post_id, ?string $ip_address)
    {
        if (!addon_installed('cns_warnings') || !addon_installed('points')) {
            return;
        }

        if (!$new) {
            return;
        }

        if (has_privilege(get_member(), 'moderate_points')) {
            require_code('points');
            $num_points_currently = points_balance($member_id);
            $fields->attach(form_input_integer(do_lang_tempcode('CHARGED_POINTS'), do_lang_tempcode('DESCRIPTION_CHARGED_POINTS', escape_html(integer_format($num_points_currently, 0))), 'charged_points', 0, true));
        }
    }

    /**
     * Actualise punitive actions.
     * Note that this assumes action was applied through the warnings form, and that post parameters still exist.
     *
     * @param  array $punitive_messages Punitive action text to potentially be included in the PT automatically (passed by reference)
     * @param  AUTO_LINK $warning_id The ID of the warning that was created for this punitive action
     * @param  MEMBER $member_id The member this warning is being applied to
     * @param  SHORT_TEXT $username The username of the member this warning is being applied to
     * @param  SHORT_TEXT $explanation The defined explanation for this warning
     * @param  LONG_TEXT $message The message to be sent as a PT (passed by reference; you should generally use $punitive_text instead if you want to add PT text)
     */
    public function actualise_punitive_action(array &$punitive_messages, int $warning_id, int $member_id, string $username, string $explanation, string &$message)
    {
        if (!addon_installed('cns_warnings') || !addon_installed('points')) {
            return;
        }

        $charged_points = post_param_integer('charged_points', 0);

        // Charge points if we have the privilege and requested to charge > 0 points
        if (($charged_points > 0) && (has_privilege(get_member(), 'moderate_points'))) {
            require_code('points2');

            $punitive_action_id = $GLOBALS['FORUM_DB']->query_insert('f_warnings_punitive', [
                'p_warning_id' => $warning_id,
                'p_member_id' => $member_id,
                'p_ip_address' => '',
                'p_email_address' => '',
                'p_hook' => 'points',
                'p_action' => '_PUNITIVE_CHARGE_POINTS',
                'p_param_a' => strval($charged_points),
                'p_param_b' => '',
                'p_reversed' => 0,
            ], true);

            // Note we pass false for sending notifications, which mean they only get sent to staff. The member will be 'notified' in the private topic message they receive, if they receive one.
            points_debit_member($member_id, do_lang('WARNING_NUMBER', strval($warning_id)), $charged_points, 0, 1, null, 0, 'warning', 'add', strval($punitive_action_id), null, true, true);

            $punitive_messages[] = do_lang('PUNITIVE_CHARGE_POINTS', integer_format($charged_points), integer_format(points_balance($member_id)), null, null, false);
        }
    }

    /**
     * Actualiser to undo a certain type of punitive action.
     *
     * @param  array $punitive_action The database row for the punitive action being undone
     * @param  array $warning The database row for the warning associated with the punitive action being undone
     */
    public function undo_punitive_action(array $punitive_action, array $warning)
    {
        $error = new Tempcode();
        if (!addon_installed__messaged('cns_warnings', $error)) {
            warn_exit($error);
        }
        if (!addon_installed__messaged('points', $error)) {
            warn_exit($error);
        }
        if (get_forum_type() != 'cns') {
            warn_exit(do_lang_tempcode('INTERNAL_ERROR'));
        }

        require_code('points2');
        require_lang('points');

        $id = intval($punitive_action['id']);

        $row = $GLOBALS['SITE_DB']->query_select('points_ledger', ['id', 'sending_member'], ['t_type' => 'warning', 't_subtype' => 'add', 't_type_id' => strval($id)]);
        if (!array_key_exists(0, $row)) {
            warn_exit(do_lang_tempcode('MISSING_RESOURCE'));
        }
        $ledger = $row[0];

        points_transaction_reverse($ledger['id']);

        log_it('UNDO_CHARGE', strval($warning['id']), $GLOBALS['FORUM_DRIVER']->get_username($punitive_action['p_member_id']));
    }
}
