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

/**
 * Standard code module initialisation function.
 *
 * @ignore
 */
function init__cns_posts()
{
    global $SIGNATURES_CACHE;
    $SIGNATURES_CACHE = array();
}

/**
 * Find whether a member may post in a certain topic.
 *
 * @param  ?AUTO_LINK $forum_id The forum ID of the forum the topic is in (null: private topics).
 * @param  AUTO_LINK $topic_id The topic ID is in.
 * @param  ?MEMBER $last_member_id The last poster in the topic (null: do not check for double posting).
 * @param  boolean $closed Whether this topic is closed.
 * @param  ?MEMBER $member_id The member (null: current member).
 * @param  boolean $will_be_private_post Whether this post will be private.
 * @return boolean The answer.
 */
function cns_may_post_in_topic($forum_id, $topic_id, $last_member_id = null, $closed = false, $member_id = null, $will_be_private_post = false)
{
    if (is_null($member_id)) {
        $member_id = get_member();
    }

    if (!has_actual_page_access($member_id, 'topics')) {
        return false;
    }

    require_code('cns_forums');
    if (($closed) && (!cns_may_moderate_forum($forum_id, $member_id))) {
        return false;
    }

    $sql = 'SELECT id FROM ' . $GLOBALS['FORUM_DB']->get_table_prefix() . 'f_warnings WHERE (p_silence_from_topic=' . strval($topic_id);
    if ($forum_id !== null) {
        $sql .= ' OR p_silence_from_forum=' . strval($forum_id);
    }
    $sql .= ') AND w_member_id=' . strval($member_id);
    $test = $GLOBALS['FORUM_DB']->query_value_if_there($sql, false, true);
    if ($test !== null) {
        return false;
    }

    if (!cns_may_access_topic($topic_id, $member_id)) {
        return false;
    }

    if ($forum_id === null) {
        // No extra checks for private topics...

        return true;
    }

    // Extra checks for regular topics...

    if (!has_privilege($member_id, 'submit_lowrange_content', 'topics', array('forums', $forum_id, 'topics', $topic_id))) {
        return false;
    }

    if (($last_member_id !== null) && (!has_privilege($member_id, 'double_post'))) {
        if (($last_member_id == $member_id) && (!$will_be_private_post)) {
            return false;
        }
    }

    return true;
}

/**
 * Find whether a member may edit the detailed post.
 *
 * @param  AUTO_LINK $post_id The post ID.
 * @param  ?TIME $post_time The time of the post (null: lookup).
 * @param  ?MEMBER $resource_owner The owner of the post (null: lookup).
 * @param  ?AUTO_LINK $forum_id The forum the post is in (null: is a Private Topic, unless $post_time is null in which case we look this up too).
 * @param  ?MEMBER $member_id The member (null: current member).
 * @param  ?boolean $topic_is_closed Whether the topic the post is in is closed (null: don't consider this, maybe we're not considering any one specific case, unless $post_time is null in which case we look this up to).
 * @param  ?string $reason The reason for the topic being closed is put here (null: no interesting reason).
 * @return boolean The answer.
 */
function cns_may_edit_post_by($post_id, $post_time, $resource_owner, $forum_id, $member_id = null, $topic_is_closed = null, &$reason = null)
{
    if (is_null($member_id)) {
        $member_id = get_member();
    }

    $reason = null;

    if (is_null($post_time)) {
        $posts = $GLOBALS['FORUM_DB']->query_select('f_posts p JOIN ' . $GLOBALS['FORUM_DB']->get_table_prefix() . 'f_topics t ON t.id=p.p_topic_id', array('p_time', 'p_poster', 'p_cache_forum_id', 't_is_open'), array('id' => $post_id), '', 1);
        if (!array_key_exists(0, $posts)) {
            $reason = do_lang('INTERNAL_ERROR');
            return false;
        }
        $post_time = $posts[0]['p_time'];
        $resource_owner = $posts[0]['p_poster'];
        $forum_id = $posts[0]['p_cache_forum_id'];
        $topic_is_closed = ($posts[0]['t_is_open'] == 0);
    }

    if (is_null($forum_id)) {
        if (!has_privilege($member_id, 'moderate_private_topic')) {
            if (($resource_owner != $member_id) || (!has_privilege($member_id, 'delete_private_topic_posts'))) {
                return false;
            }
        }
    } else {
        $ticket_forum = get_option('ticket_forum_name', true);
        $comments_forum = get_option('comments_forum_name', true);
        if ((is_null($ticket_forum)) || (($forum_id != $GLOBALS['FORUM_DRIVER']->forum_id_from_name($ticket_forum)) && ($forum_id != $GLOBALS['FORUM_DRIVER']->forum_id_from_name($comments_forum)))) {
            if (!has_category_access($member_id, 'forums', strval($forum_id))) {
                return false;
            }
        }
    }

    if ($topic_is_closed === true) {
        require_code('cns_forums');
        if (!cns_may_moderate_forum($forum_id, $member_id)) {
            return false;
        }
    }

    if (!is_null($forum_id) || !has_privilege($member_id, 'moderate_private_topic')) {
        if (!has_edit_permission('low', $member_id, $resource_owner, 'topics', array('forums', $forum_id))) {
            return false;
        }
    }

    if (((time() - $post_time) > intval(get_option('edit_time_limit')) * 60) && (!has_privilege($member_id, 'exceed_post_edit_time_limit'))) {
        require_lang('cns');
        $reason = do_lang('EXCEEDED_TIME_LIMIT', escape_html(display_time_period(intval(get_option('edit_time_limit')) * 60)));
        return false;
    }

    return true;
}

/**
 * Find whether a member may delete the detailed post.
 *
 * @param  AUTO_LINK $post_id The post ID.
 * @param  ?TIME $post_time The time of the post (null: lookup).
 * @param  ?MEMBER $resource_owner The owner of the post (null: lookup).
 * @param  ?AUTO_LINK $forum_id The forum the post is in (null: is a Private Topic, unless $post_time is null in which case we look this up too).
 * @param  ?MEMBER $member_id The member (null: current member).
 * @param  ?boolean $topic_is_closed Whether the topic the post is in is closed (null: don't consider this, maybe we're not considering any one specific case, unless $post_time is null in which case we look this up to).
 * @param  ?string $reason The reason for the topic being closed is put here (null: no interesting reason).
 * @return boolean The answer.
 */
function cns_may_delete_post_by($post_id, $post_time, $resource_owner, $forum_id, $member_id = null, $topic_is_closed = null, &$reason = null)
{
    if (is_null($member_id)) {
        $member_id = get_member();
    }

    $reason = null;

    if (is_null($post_time)) {
        $posts = $GLOBALS['FORUM_DB']->query_select('f_posts p JOIN ' . $GLOBALS['FORUM_DB']->get_table_prefix() . 'f_topics t ON t.id=p.p_topic_id', array('p_time', 'p_poster', 'p_cache_forum_id', 't_is_open'), array('p.id' => $post_id), '', 1);
        if (!array_key_exists(0, $posts)) {
            $reason = do_lang('INTERNAL_ERROR');
            return false;
        }
        $post_time = $posts[0]['p_time'];
        $resource_owner = $posts[0]['p_poster'];
        $forum_id = $posts[0]['p_cache_forum_id'];
        $topic_is_closed = ($posts[0]['t_is_open'] == 0);
    }

    if (is_null($forum_id)) {
        if (!has_privilege($member_id, 'moderate_private_topic')) {
            if (($resource_owner != $member_id) || (!has_privilege($member_id, 'delete_private_topic_posts'))) {
                return false;
            }
        }
    } else {
        $ticket_forum = get_option('ticket_forum_name', true);
        $comments_forum = get_option('comments_forum_name', true);
        if ((is_null($ticket_forum)) || (($forum_id != $GLOBALS['FORUM_DRIVER']->forum_id_from_name($ticket_forum)) && ($forum_id != $GLOBALS['FORUM_DRIVER']->forum_id_from_name($comments_forum)))) {
            if (!has_category_access($member_id, 'forums', strval($forum_id))) {
                return false;
            }
        }
    }

    if (!is_null($forum_id) || !has_privilege($member_id, 'moderate_private_topic')) {
        if (!has_delete_permission('low', $member_id, $resource_owner, 'topics', array('forums', $forum_id))) {
            return false;
        }
    }

    if (((time() - $post_time) > intval(get_option('delete_time_limit')) * 60) && (!has_privilege($member_id, 'exceed_post_delete_time_limit'))) {
        require_lang('cns');
        $reason = do_lang('EXCEEDED_TIME_LIMIT', escape_html(display_time_period(intval(get_option('delete_time_limit')) * 60)));
        return false;
    }

    return true;
}

/**
 * Try and make a spacer post look nicer on Conversr than it automatically would.
 *
 * @param  ID_TEXT $linked_type Content type.
 * @param  ID_TEXT $linked_id Content ID.
 * @return array A pair: better description (may be null), better post (may be null).
 */
function cns_display_spacer_post($linked_type, $linked_id)
{
    $new_description = mixed();
    $new_post = mixed();

    require_code('content');
    $linked_type = convert_composr_type_codes('feedback_type_code', $linked_type, 'content_type');
    if ($linked_type != '') {
        require_code('content');
        $cma_ob = get_content_object($linked_type);
        if ($cma_ob !== null) {
            $cma_info = $cma_ob->info();
            if ($cma_info !== null) {
                $linked_rows = $GLOBALS['SITE_DB']->query_select($cma_info['table'], array('*'), get_content_where_for_str_id($linked_id, $cma_info), '', 1);
                if (array_key_exists(0, $linked_rows)) {
                    $new_post = $cma_ob->run($linked_rows[0], '_SEARCH', true, true);
                }
                $new_description = do_lang('THIS_IS_COMMENT_TOPIC', get_site_name());
            }
        }
    }

    return array($new_description, $new_post);
}
