<?php /*

 Composr
 Copyright (c) ocProducts, 2004-2016

 See text/EN/licence.txt for full licencing 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  ocProducts Ltd
 * @package    core_cns
 */

/**
 * Make sure we are doing necessary join to be able to access the given field
 *
 * @param  object $db Database connection
 * @param  array $info Content type info
 * @param  ID_TEXT $context Context (unused)
 * @param  array $extra_join List of joins (passed as reference)
 * @param  array $extra_select List of selects (passed as reference)
 * @param  ID_TEXT $filter_key The field to get
 * @param  string $field_val The field value for this
 * @param  array $db_fields Database field data
 * @param  string $table_join_code What the database will join the table with
 * @return ?array A triple: Proper database field name to access with, The fields API table type (blank: no special table), The new filter value (null: error)
 * @ignore
 */
function _members_filtercode($db, $info, $context, &$extra_join, &$extra_select, $filter_key, $field_val, $db_fields, $table_join_code)
{
    // If it's trivial
    if (($filter_key == 'id') || (preg_match('#^m\_\w+$#', $filter_key) != 0)) {
        if (!array_key_exists($filter_key, $db_fields)) {
            return null;
        }
        return array($table_join_code . '.' . $filter_key, '', $field_val);
    }

    // Mostly CPFS...
    // --------------

    $join_sql = ' LEFT JOIN ' . $db->get_table_prefix() . 'f_member_custom_fields f ON f.mf_member_id=r.id';

    if (!in_array($join_sql, $extra_join)) {
        $extra_join[$filter_key] = $join_sql;
    }

    $new_filter_key = $filter_key;
    if (is_numeric($filter_key)) {
        // CPF by just ID
        $new_filter_key = 'field_' . $new_filter_key;
    } elseif ($filter_key == 'gm_group_id') {
        // Secondary usergroup membership

        $join_sql = ' LEFT JOIN ' . $db->get_table_prefix() . 'f_group_members gm ON gm.gm_member_id=r.id';

        if (!in_array($join_sql, $extra_join)) {
            $extra_join[$filter_key] = $join_sql;
        }

        return array($new_filter_key, '', $field_val);
    } elseif (preg_match('#^field\_\d+$#', $filter_key) == 0) { // If it's not already correct
        // CPF by title
        require_code('cns_members');
        $cpf_id = find_cpf_field_id($filter_key);
        if (is_null($cpf_id)) {
            return null;
        }
        $new_filter_key = 'field_' . strval($cpf_id);
    } else {
        // CPF like field_xxx
        $new_filter_key = $filter_key;
    }

    return array($new_filter_key, '', $field_val);
}

/**
 * Get a member display box. Some terminology refers to a member here as a 'poster', as this function is used in forum topics also.
 *
 * @param  mixed $poster_details Either a member ID or an array containing: ip_address, poster_num_warnings, poster, poster_posts, poster_points, poster_join_date_string, primary_group_name.
 * @param  boolean $preview Whether only to show 'preview' details
 * @param  ?array $hooks An array of hooks. (null: lookup)
 * @param  ?array $hook_objects An array of hook objects that allow us to collect additional mouse-over member information. (null: lookup)
 * @param  boolean $show_avatar Whether to show the avatar
 * @param  ?array $extra_fields Map of extra fields to show (null: none)
 * @param  boolean $give_context Whether to include context (i.e. say WHAT this is, not just show the actual content)
 * @param  ID_TEXT $guid Overridden GUID to send to templates (blank: none)
 * @return Tempcode The member box
 */
function render_member_box($poster_details, $preview = false, $hooks = null, $hook_objects = null, $show_avatar = true, $extra_fields = null, $give_context = true, $guid = '')
{
    if (is_null($poster_details)) { // Should never happen, but we need to be defensive
        return new Tempcode();
    }

    require_lang('cns');
    require_css('cns');

    // Have to build up $poster_details instead?
    if (!is_array($poster_details)) {
        if (addon_installed('points')) {
            require_code('points');
            $points = integer_format(total_points($poster_details));
        } else {
            $points = '';
        }
        require_code('cns_members');
        $primary_group = cns_get_member_primary_group($poster_details);
        if ($primary_group === null) {
            return new Tempcode();
        }
        require_code('cns_groups');
        $poster_details = array(
            'poster' => $poster_details,
            'poster_posts' => $GLOBALS['CNS_DRIVER']->get_member_row_field($poster_details, 'm_cache_num_posts'),
            'poster_join_date' => $GLOBALS['CNS_DRIVER']->get_member_row_field($poster_details, 'm_join_time'),
            'poster_join_date_string' => get_timezoned_date($GLOBALS['CNS_DRIVER']->get_member_row_field($poster_details, 'm_join_time'), false),
            'primary_group_name' => cns_get_group_name($primary_group),
        );
        $poster_details['custom_fields'] = cns_get_all_custom_fields_match_member(
            $poster_details['poster'], // member
            ((get_member() != $poster_details['poster']) && (!has_privilege(get_member(), 'view_any_profile_field'))) ? 1 : null, // public view
            ((get_member() == $poster_details['poster']) && (!has_privilege(get_member(), 'view_any_profile_field'))) ? 1 : null, // owner view
            null, // owner set
            0, // encrypted
            null, // required
            $preview ? null : 1, // show in posts
            $preview ? 1 : null // show in post previews
        );
        if ($preview) {
            $poster_details['custom_fields_full'] = cns_get_all_custom_fields_match_member(
                $poster_details['poster'], // member
                ((get_member() != $poster_details['poster']) && (!has_privilege(get_member(), 'view_any_profile_field'))) ? 1 : null, // public view
                ((get_member() == $poster_details['poster']) && (!has_privilege(get_member(), 'view_any_profile_field'))) ? 1 : null, // owner view
                null, // owner set
                0, // encrypted
                null, // required
                1, // show in posts
                0 // show in post previews
            );
        } else {
            $poster_details['custom_fields_full'] = $poster_details['custom_fields'];
        }
        if ((has_privilege(get_member(), 'see_warnings')) && (addon_installed('cns_warnings'))) {
            $num_warnings = $GLOBALS['CNS_DRIVER']->get_member_row_field($poster_details['poster'], 'm_cache_warnings');
            $poster_details['poster_num_warnings'] = $num_warnings;
        }
        if (has_privilege(get_member(), 'see_ip')) {
            $poster_details['ip_address'] = $GLOBALS['CNS_DRIVER']->get_member_row_field($poster_details['poster'], 'm_ip_address');
        }
    } else {
        $points = isset($poster_details['points']) ? integer_format($poster_details['points']) : '';
    }

    $member_id = $poster_details['poster'];

    if ($hooks === null) {
        // Poster detail hooks
        $hooks = find_all_hooks('modules', 'topicview');
        $hook_objects = array();
        foreach ($hooks as $hook => $hook_dir) {
            require_code('hooks/modules/topicview/' . filter_naughty_harsh($hook), false, $hook_dir == 'sources_custom');
            $object = object_factory('Hook_topicview_' . filter_naughty_harsh($hook), true);
            if ($object === null) {
                continue;
            }
            $hook_objects[$hook] = $object;
        }
    }

    $custom_fields = new Tempcode();
    foreach ($poster_details['custom_fields'] as $name => $value) {
        if (($value !== null) && ($value !== '')) {
            if (is_integer($name)) {
                $name = strval($name);
            }
            $custom_fields->attach(do_template('CNS_MEMBER_BOX_CUSTOM_FIELD', array('_GUID' => ($guid != '') ? $guid : '10b72cd1ec240c315e56bc8a0f3a92a1', 'MEMBER_ID' => strval($member_id), 'NAME' => $name, 'RAW' => $value['RAW'], 'VALUE' => is_object($value['RENDERED']) ? protect_from_escaping($value['RENDERED']) : $value['RENDERED'])));
        }
    }
    $custom_fields_full = new Tempcode();
    if (isset($poster_details['custom_fields_full'])) {
        foreach ($poster_details['custom_fields_full'] as $name => $value) {
            if (($value !== null) && ($value !== '')) {
                if (is_integer($name)) {
                    $name = strval($name);
                }
                $custom_fields_full->attach(do_template('CNS_MEMBER_BOX_CUSTOM_FIELD', array('_GUID' => ($guid != '') ? $guid : '20b72cd1ec240c315e56bc8a0f3a92a1', 'MEMBER_ID' => strval($member_id), 'NAME' => $name, 'RAW' => $value['RAW'], 'VALUE' => is_object($value['RENDERED']) ? protect_from_escaping($value['RENDERED']) : $value['RENDERED'])));
            }
        }
    }

    $ip_address = null;
    if (isset($poster_details['ip_address'])) {
        $ip_address = $poster_details['ip_address'];
    }

    $num_warnings = null;
    if ((isset($poster_details['poster_num_warnings'])) && (addon_installed('cns_warnings'))) {
        $num_warnings = integer_format($poster_details['poster_num_warnings']);
    }

    $galleries = null;
    if ((addon_installed('galleries')) && (get_option('show_gallery_counts') == '1')) {
        $gallery_cnt = $GLOBALS['SITE_DB']->query_value_if_there('SELECT COUNT(*) AS cnt FROM ' . $GLOBALS['SITE_DB']->get_table_prefix() . 'galleries WHERE name LIKE \'' . db_encode_like('member\_' . strval($member_id) . '\_%') . '\'');

        if ($gallery_cnt > 1) {
            require_lang('galleries');
            $galleries = integer_format($gallery_cnt);
        }
    }

    $dob = null;
    $age = null;
    $day = $GLOBALS['CNS_DRIVER']->get_member_row_field($member_id, 'm_dob_day');
    $month = $GLOBALS['CNS_DRIVER']->get_member_row_field($member_id, 'm_dob_month');
    $year = $GLOBALS['CNS_DRIVER']->get_member_row_field($member_id, 'm_dob_year');
    if (($day !== null) && ($month !== null) && ($year !== null)) {
        if ($GLOBALS['CNS_DRIVER']->get_member_row_field($member_id, 'm_reveal_age') == 1) {
            if (@strftime('%Y', @mktime(0, 0, 0, 1, 1, 1963)) != '1963') {
                $dob = strval($year) . '-' . str_pad(strval($month), 2, '0', STR_PAD_LEFT) . '-' . str_pad(strval($day), 2, '0', STR_PAD_LEFT);
            } else {
                $dob = get_timezoned_date(mktime(12, 0, 0, $month, $day, $year), false, false, true);
            }

            $age = intval(date('Y')) - $year;
            if ($month > intval(date('m'))) {
                $age--;
            }
            if (($month == intval(date('m'))) && ($day > intval(date('j')))) {
                $age--;
            }
        } else {
            $dob = cms_strftime(do_lang('date_no_year'), mktime(12, 0, 0, $month, $day));
        }
    }

    if ($extra_fields !== null) {
        foreach ($extra_fields as $key => $val) {
            if (is_integer($key)) {
                $key = strval($key);
            }

            $custom_fields->attach(do_template('CNS_MEMBER_BOX_CUSTOM_FIELD', array('_GUID' => ($guid != '') ? $guid : '530f049d3b3065df2d1b69270aa93490', 'MEMBER_ID' => strval($member_id), 'NAME' => $key, 'VALUE' => ($val))));
        }
    }

    foreach (array_keys($hooks) as $hook) {
        $hook_result = $hook_objects[$hook]->run($member_id);
        if ($hook_result !== null) {
            $custom_fields->attach($hook_result);
        }
    }

    $_usergroups = $GLOBALS['FORUM_DRIVER']->get_members_groups($member_id, true);
    $all_usergroups = $GLOBALS['FORUM_DRIVER']->get_usergroup_list(true, false, false, $_usergroups);
    $usergroups = array();
    foreach ($_usergroups as $u) {
        if (isset($all_usergroups[$u])) {
            $usergroups[] = $all_usergroups[$u];
        }
    }

    require_code('users2');
    return do_template('CNS_MEMBER_BOX', array(
        '_GUID' => ($guid != '') ? $guid : 'dfskfdsf9',
        'GIVE_CONTEXT' => $give_context,
        'MEMBER_ID' => strval($member_id),
        'POSTS' => integer_format($poster_details['poster_posts']),
        'POINTS' => $points,
        'JOIN_DATE_RAW' => strval($poster_details['poster_join_date']),
        'JOIN_DATE' => $poster_details['poster_join_date_string'],
        'PRIMARY_GROUP_NAME' => $poster_details['primary_group_name'],
        'OTHER_USERGROUPS' => $usergroups,
        'CUSTOM_FIELDS' => $custom_fields,
        'CUSTOM_FIELDS_FULL' => $custom_fields_full,
        'ONLINE' => member_is_online($member_id),
        'AVATAR_URL' => $show_avatar ? $GLOBALS['FORUM_DRIVER']->get_member_avatar_url($member_id) : '',
        'IP_ADDRESS' => $ip_address,
        'NUM_WARNINGS' => $num_warnings,
        'GALLERIES' => $galleries,
        'DATE_OF_BIRTH' => $dob,
        'AGE' => ($age === null) ? null : integer_format($age),
    ));
}

/**
 * Find if a certain member may be PTd by a certain member.
 *
 * @param  MEMBER $target Member to be PT'd
 * @param  ?MEMBER $member_id Member to PT. (null: current member)
 * @return boolean Whether the PT may be created
 */
function cns_may_whisper($target, $member_id = null)
{
    if (is_null($member_id)) {
        $member_id = get_member();
    }

    if (addon_installed('cns_forum')) {
        if (get_option('enable_pt_restrict') == '0') {
            return true;
        }
    }

    if ($target == $member_id) {
        return true;
    }

    if (has_privilege($member_id, 'pt_anyone')) {
        return true;
    }
    $pt_allow = $GLOBALS['CNS_DRIVER']->get_member_row_field($target, 'm_pt_allow');
    if ($pt_allow == '*') {
        return true;
    }

    global $MAY_WHISPER_CACHE;
    $key = serialize(array($target, $member_id));
    if (array_key_exists($key, $MAY_WHISPER_CACHE)) {
        return $MAY_WHISPER_CACHE[$key];
    }
    $MAY_WHISPER_CACHE = array();

    require_code('selectcode');
    $groups = $GLOBALS['FORUM_DRIVER']->get_members_groups($member_id);
    $answer = count(array_intersect(selectcode_to_idlist_using_memory($pt_allow, $GLOBALS['FORUM_DRIVER']->get_usergroup_list(false, false, false, null, $member_id)), $groups)) != 0;

    if ((!$answer) && (addon_installed('chat'))) {
        $rows = $GLOBALS['SITE_DB']->query_select('chat_friends', array('date_and_time'), array('member_likes' => $target, 'member_liked' => $member_id), '', 1);
        if (count($rows) != 0) {
            $answer = true;
        }
    }

    $MAY_WHISPER_CACHE[$key] = $answer;
    return $answer;
}
