Seditio Source
Root |
./othercms/b2evolution_7.2.3/inc/messaging/_messaging.init.php
<?php
/**
 * This file is part of b2evolution - {@link http://b2evolution.net/}
 * See also {@link https://github.com/b2evolution/b2evolution}.
 *
 * @license GNU GPL v2 - {@link http://b2evolution.net/about/gnu-gpl-license}
 *
 * @copyright (c)2009-2016 by Francois Planque - {@link http://fplanque.com/}
 * Parts of this file are copyright (c)2009 by The Evo Factory - {@link http://www.evofactory.com/}.
 *
 * Released under GNU GPL License - {@link http://b2evolution.net/about/gnu-gpl-license}
 *
 * @package messaging
 */
if( !defined('EVO_CONFIG_LOADED') ) die( 'Please, do not access this page directly.' );

/**
 * Minimum PHP version required for messaging module to function properly
 */
$required_php_version[ 'messaging' ] = '5.6';

/**
 * Minimum MYSQL version required for messaging module to function properly
 */
$required_mysql_version[ 'messaging' ] = '5.1';

/**
 * Aliases for table names:
 *
 * (You should not need to change them.
 *  If you want to have multiple b2evo installations in a single database you should
 *  change {@link $tableprefix} in _basic_config.php)
 */
$db_config['aliases']['T_messaging__thread'] = $tableprefix.'messaging__thread';
$db_config['aliases']['T_messaging__message'] = $tableprefix.'messaging__message';
$db_config['aliases']['T_messaging__prerendering'] = $tableprefix.'messaging__prerendering';
$db_config['aliases']['T_messaging__threadstatus'] = $tableprefix.'messaging__threadstatus';
$db_config['aliases']['T_messaging__contact'] = $tableprefix.'messaging__contact';
$db_config['aliases']['T_messaging__contact_groups'] = $tableprefix.'messaging__contact_groups';
$db_config['aliases']['T_messaging__contact_groupusers'] = $tableprefix.'messaging__contact_groupusers';

/**
 * Controller mappings.
 *
 * For each controller name, we associate a controller file to be found in /inc/ .
 * The advantage of this indirection is that it is easy to reorganize the controllers into
 * subdirectories by modules. It is also easy to deactivate some controllers if you don't
 * want to provide this functionality on a given installation.
 *
 * Note: while the controller mappings might more or less follow the menu structure, we do not merge
 * the two tables since we could, at any time, decide to make a skin with a different menu structure.
 * The controllers however would most likely remain the same.
 *
 * @global array
 */
$ctrl_mappings['messages'] = 'messaging/messages.ctrl.php';
$ctrl_mappings['threads'] = 'messaging/threads.ctrl.php';
$ctrl_mappings['contacts'] = 'messaging/contacts.ctrl.php';
$ctrl_mappings['msgsettings'] = 'messaging/msg_settings.ctrl.php';
$ctrl_mappings['abuse'] = 'messaging/abuse.ctrl.php';



/**
 * Get the MessageCache
 *
 * @return MessageCache
 */
function & get_MessageCache()
{
    global
$MessageCache;

    if( ! isset(
$MessageCache ) )
    {    
// Cache doesn't exist yet:
       
load_class( 'messaging/model/_message.class.php', 'Message' );
       
$MessageCache = new DataObjectCache( 'Message', false, 'T_messaging__message', 'msg_', 'msg_ID' );
    }

    return
$MessageCache;
}


/**
 * Get the MessagePrerenderingCache
 *
 * @return MessagePrerenderingCache
 */
function & get_MessagePrerenderingCache()
{
    global
$MessagePrerenderingCache;

    if( ! isset(
$MessagePrerenderingCache ) )
    {
// Cache doesn't exist yet:
       
$MessagePrerenderingCache = array();
    }

    return
$MessagePrerenderingCache;
}


/**
 * Get the ThreadCache
 *
 * @return ThreadCache
 */
function & get_ThreadCache()
{
    global
$ThreadCache;

    if( ! isset(
$ThreadCache ) )
    {    
// Cache doesn't exist yet:
       
load_class( 'messaging/model/_thread.class.php', 'Thread' );
       
$ThreadCache = new DataObjectCache( 'Thread', false, 'T_messaging__thread', 'thrd_', 'thrd_ID', 'thrd_title' );
    }

    return
$ThreadCache;
}


/**
 * messaging_Module definition
 */
class messaging_Module extends Module
{
   
/**
     * Do the initializations. Called from in _main.inc.php.
     * This is typically where classes matching DB tables for this module are registered/loaded.
     *
     * Note: this should only load/register things that are going to be needed application wide,
     * for example: for constructing menus.
     * Anything that is needed only in a specific controller should be loaded only there.
     * Anything that is needed only in a specific view should be loaded only there.
     */
   
function init()
    {
       
$this->check_required_php_version( 'messaging' );

       
load_funcs( 'messaging/model/_messaging.funcs.php' );
    }


   
/**
     * Get default module permissions
     *
     * #param integer Group ID
     * @return array
     */
   
function get_default_group_permissions( $grp_ID )
    {
        switch(
$grp_ID )
        {
            case
1: // Administrators group ID equals 1
               
global $install_test_features;
               
$perm_messaging = ! empty( $install_test_features ) ? 'abuse' : 'delete';
               
$max_new_threads = ''; // empty = no limit
               
break;
            case
2: // Moderators group equals 2
           
case 3: // Editors group ID equals 3
               
$perm_messaging = 'write'; // Messaging permissions
               
$max_new_threads = '10'; // Maximum number of new threads per day
               
break;
            case
4: // Normal users group ID equals 4
               
$perm_messaging = 'write';
               
$max_new_threads = '5';
                break;
            case
5:        // Misbehaving/Suspect users (group ID 5) have permission by default:
               
$perm_messaging = 'write';
               
$max_new_threads = '1';
                break;
            case
6:  // Spammers/restricted Users
           
default: // Other groups
               
$perm_messaging = 'reply';
               
$max_new_threads = '1';
                break;
        }

       
// We can return as many default permissions as we want:
        // e.g. array ( permission_name => permission_value, ... , ... )
       
return $permissions = array( 'perm_messaging' => $perm_messaging, 'max_new_threads' => $max_new_threads );
    }


   
/**
     * Get available group permissions
     *
     * @return array
     */
   
function get_available_group_permissions()
    {
       
// 'label' is used in the group form as label for radio buttons group
        // 'user_func' is used to check user permission. This function should be defined in module initializer.
        // 'group_func' is used to check group permission. This function should be defined in module initializer.
        // 'perm_block' group form block where this permissions will be displayed. Now available, the following blocks: additional, system
        // 'options' is permission options
       
$permissions = array(
           
'perm_messaging' => array(
               
'label' => T_('Messages'),
               
'user_func'  => 'check_messaging_user_perm',
               
'group_func' => 'check_messaging_group_perm',
               
'perm_block' => 'additional',
               
'options'  => array(
                       
// format: array( radio_button_value, radio_button_label, radio_button_note )
                       
array( 'none', T_( 'No Access' ), '' ),
                        array(
'reply', T_( 'Read & Send messages to people in contacts list only (except for blocked contacts)' ), '' ),
                        array(
'write', T_( 'Read & Send messages to anyone (except for blocked contacts)' ), '' ),
                        array(
'delete', T_( 'Read, Send & Delete any messages (including for blocked contacts)' ), '' ),
                        array(
'abuse', T_( 'Abuse Management' ), '' )  ) ),
           
'max_new_threads' => array(
               
'label' => T_( 'Maximum number of new threads per day' ),
               
'group_func' => 'get_group_settings',
               
'perm_block' => 'additional',
               
'perm_type' => 'text_input',
               
'note' => T_( 'Leave empty for no limit' ),
               
'maxlength' => 5 ),
        );
       
// We can return as many permissions as we want.
        // In other words, one module can return many pluggable permissions.
       
return $permissions;
    }


   
/**
     * Check a permission for the user. ( see 'user_func' in get_available_group_permissions() function  )
     *
     * @param string Requested permission level
     * @param string Permission value
     * @param mixed Permission target (blog ID, array of cat IDs...)
     * @return boolean True on success (permission is granted), false if permission is not granted
     */
   
function check_messaging_user_perm( $permlevel, $permvalue, $permtarget )
    {
        global
$current_User;

        if(
$permtarget > 0 )
        {  
// Check user permission for current thread
           
$ThreadCache = & get_ThreadCache();
           
$Thread = & $ThreadCache->get_by_ID( $permtarget, false );

            if(
$Thread === false || ! $Thread->check_thread_recipient( $current_User->ID ) )
            {
                return
false;
            }
        }

        return
true;
    }


   
/**
     * Check a permission for the group. ( see 'group_func' in get_available_group_permissions() function )
     *
     * @param string Requested permission level
     * @param string Permission value
     * @param mixed Permission target (blog ID, array of cat IDs...)
     * @return boolean True on success (permission is granted), false if permission is not granted
     */
   
function check_messaging_group_perm( $permlevel, $permvalue, $permtarget )
    {
       
$perm = false;
        switch (
$permvalue )
        {
            case
'abuse':
               
// Abuse Management & Read, Send & Delete any messages (able to send messages even for blocked contacts)
               
if( $permlevel == 'abuse' )
                {
                   
$perm = true;
                    break;
                }
            case
'delete':
               
// Read, Send & Delete any messages (able to send messages even for blocked contacts)
               
if( $permlevel == 'delete' )
                {
// User can ask for delete perm...
                   
$perm = true;
                    break;
                }
            case
'write':
               
// Read & Send messages to anyone (except for blocked contacts)
               
if( $permlevel == 'write' )
                {
                   
$perm = true;
                    break;
                }
            case
'reply':
               
//  Read & Send messages to people in contacts list only (except for blocked contacts)
               
if( $permlevel == 'reply' )
                {
                   
$perm = true;
                    break;
                }
        }

        return
$perm;
    }


   
/**
     * Get pluggable group settings value
     */
   
function get_group_settings( $permname, $permvalue, $permtarget )
    {
        return
$permvalue;
    }


   
/**
     * Build the evobar menu
     */
   
function build_evobar_menu()
    {
        global
$DB;
        global
$topleft_Menu, $topright_Menu;
        global
$admin_url;

       
$left_entries = array();
       
$right_entries = array();

        if(
check_user_perm( 'perm_messaging', 'reply' ) )
        {
            if( ! empty(
$topleft_Menu->_menus['entries']['site']['entries'] ) )
            {
               
$left_entries['messaging'] = array(
                       
'text' => T_('Messages').'&hellip;',
                       
'href' => $admin_url.'?ctrl=threads',
                    );
            }

           
$messages_url = get_dispctrl_url( 'threads' );
           
$contacts_url = get_dispctrl_url( 'contacts' );

            if( ! empty(
$messages_url ) || ! empty( $contacts_url )  )
            {
               
$right_entries[] = array( 'separator' => true );
            }

            if( ! empty(
$messages_url ) )
            {
// Display this menu item only when url is available to current user
               
$right_entries['messages'] = array(
                       
'text' => T_('Messages'),
                       
'href' => $messages_url,
                       
'class' => 'evo_messages_link',
                    );
            }
            if( ! empty(
$contacts_url ) )
            {
// Display this menu item only when url is available to current user
               
$right_entries['contacts'] = array(
                       
'text' => T_('Contacts'),
                       
'href' => $contacts_url,
                       
'class' => 'evo_messages_link',
                    );
            }

           
// Count unread messages for current user
           
$unread_messages_count = get_unread_messages_count();
            if(
$unread_messages_count > 0 )
            {
               
$right_entries['messages']['text'] = T_('Messages').' <span class="badge badge-important">'.$unread_messages_count.'</span>';
            }
        }

       
$topleft_Menu->add_menu_entries( 'site', $left_entries );
       
$topright_Menu->insert_menu_entries_after( array( 'userprefs', 'name' ), $right_entries );
    }

   
/**
     * Builds the 3rd half of the menu. This is the one with the configuration features
     *
     * At some point this might be displayed differently than the 1st half.
     */
   
function build_menu_3()
    {
        global
$admin_url;

       
/**
         * @var AdminUI_general
         */
       
global $AdminUI;

        if( !
check_user_perm( 'admin', 'restricted' ) )
        {
            return;
        }

        if(
check_user_perm( 'perm_messaging', 'reply' ) )
        {
// Permission to view messaging:

            // Count unread messages for current user
           
$unread_messages_count = get_unread_messages_count();
            if(
$unread_messages_count > 0 )
            {
               
$messages_counter = ' <span class="badge badge-important">'.$unread_messages_count.'</span>';
            }
            else
            {
               
$messages_counter = '';
            }

           
$AdminUI->add_menu_entries( NULL, array(
                       
'messaging' => array(
                       
'text' => T_('Messages').$messages_counter,
                       
'title' => T_('Messages'),
                       
'href' => $admin_url.'?ctrl=threads',
                       
'entries' => get_messaging_sub_entries( true )
                    ),
                ),
'users' );
        }
    }


   
/**
     * Get the messaging module cron jobs
     *
     * @see Module::get_cron_jobs()
     */
   
function get_cron_jobs()
    {
        return array(
           
'send-unread-messages-reminders' => array(
               
'name'   => T_('Send reminders about unread messages'),
               
'help'   => '#',
               
'ctrl'   => 'cron/jobs/_unread_message_reminder.job.php',
               
'params' => NULL,
            )
        );
    }


   
/**
     * Handle messaging module htsrv actions
     */
   
function handle_htsrv_action()
    {
        global
$current_User, $Collection, $Blog, $Session, $Messages;

       
// Init objects we want to work on.
       
$action = param_action( true, true );
       
$disp = param( 'disp', '/^[a-z0-9\-_]+$/', 'threads' );

       
// Check that this action request is not a CSRF hacked request:
       
$Session->assert_received_crumb( 'messaging_'.$disp );

       
// Load classes
       
load_class( 'messaging/model/_thread.class.php', 'Thread' );
       
load_class( 'messaging/model/_message.class.php', 'Message' );

        if( !
is_logged_in() )
        {
// user must be logged in
           
debug_die( 'User must be logged in to proceed with messaging updates!' );
        }

       
// Check permission:
       
check_user_perm( 'perm_messaging', 'reply', true );

       
// set where to redirect
       
$redirect_to = param( 'redirect_to', 'url', NULL );
        if( empty(
$redirect_to ) )
        {
            if( isset(
$Blog ) )
            {
               
$redirect_to = url_add_param( $Blog->gen_baseurl(), 'disp='.$disp );
            }
            else
            {
               
$redirect_to = url_add_param( $baseurl, 'disp='.$disp );
            }
        }

        if( (
$disp != 'contacts' ) && ( $thrd_ID = param( 'thrd_ID', 'integer', '', true ) ) )
        {
// Load thread from cache:
           
$ThreadCache = & get_ThreadCache();
            if( (
$edited_Thread = & $ThreadCache->get_by_ID( $thrd_ID, false ) ) === false )
            {
// Thread doesn't exists with this ID
               
unset( $edited_Thread );
               
forget_param( 'thrd_ID' );
               
$Messages->add( T_('The private conversation you are trying to access does not exist any longer.'), 'error' );
               
$action = 'nil';
            }
        }

        switch(
$disp )
        {
           
// threads action
           
case 'threads':
                if(
$action != 'create' && $action != 'preview' )
                {
// Make sure we got a thrd_ID:
                   
param( 'thrd_ID', 'integer', true );
                }

                switch(
$action )
                {
                    case
'create': // create thread
                   
case 'preview': // preview message
                        // Stop a request from the blocked IP addresses or Domains
                       
antispam_block_request();

                       
// check if create new thread is allowed
                       
if( check_create_thread_limit() )
                        {
// max new threads limit reached, don't allow to create new thread
                           
debug_die( 'Invalid request, new conversation limit already reached!' );
                        }

                       
$creating_success = create_new_thread();
                        if( !
$creating_success || $action == 'preview' )
                        {
// unsuccessful new thread creation OR preview mode
                           
global $edited_Thread, $edited_Message, $thrd_recipients, $thrd_recipients_array;

                           
$redirect_to .= '&action=new';
                           
// save new message and thread params into the Session to not lose the content
                           
$unsaved_message_params = array();
                           
$unsaved_message_params[ 'action' ] = $action;
                           
$unsaved_message_params[ 'subject' ] = $edited_Thread->title;
                           
$unsaved_message_params[ 'message' ] = $edited_Message->text;
                           
$unsaved_message_params[ 'message_original' ] = $edited_Message->original_text;
                           
$unsaved_message_params[ 'renderers' ] = $edited_Message->get_renderers_validated();
                           
$unsaved_message_params[ 'thrdtype' ] = param( 'thrdtype', 'string', 'individual' );  // alternative: discussion
                           
$unsaved_message_params[ 'thrd_recipients' ] = $thrd_recipients;
                           
$unsaved_message_params[ 'thrd_recipients_array' ] = $thrd_recipients_array;
                           
$unsaved_message_params[ 'creating_success' ] = $creating_success;
                           
save_message_params_to_session( $unsaved_message_params );
                        }
                        break;

                    case
'delete': // delete thread
                        // Check permission:
                       
check_user_perm( 'perm_messaging', 'delete', true );

                       
$confirmed = param( 'confirmed', 'integer', 0 );
                        if(
$confirmed )
                        {
                           
$msg = sprintf( T_('Thread &laquo;%s&raquo; deleted.'), $edited_Thread->dget('title') );
                           
$edited_Thread->dbdelete();
                            unset(
$edited_Thread );
                           
forget_param( 'thrd_ID' );
                           
$Messages->add( $msg, 'success' );
                        }
                        else
                        {
                           
$delete_url = get_htsrv_url().'action.php?mname=messaging&thrd_ID='.$edited_Thread->ID.'&action=delete&confirmed=1&redirect_to='.rawurlencode( $redirect_to ).'&'.url_crumb( 'messaging_threads' );
                           
$ok_button = '<a href="'.$delete_url.'" class="btn btn-danger">'.T_( 'I am sure!' ).'</a>';
                           
$cancel_button = '<a href="'.$redirect_to.'" class="btn btn-default">CANCEL</a>';
                           
$msg = sprintf( T_( 'You are about to delete all messages in the conversation &laquo;%s&raquo;.' ), $edited_Thread->dget('title') );
                           
$msg .= '<br />'.T_( 'This CANNOT be undone!').'<br />'.T_( 'Are you sure?' ).'<br /><br />'.$ok_button."\t".$cancel_button;
                           
$Messages->add( $msg, 'error' );
                        }
                        break;

                    case
'leave': // user wants to leave the thread
                       
leave_thread( $edited_Thread->ID, $current_User->ID, false );

                       
$Messages->add( sprintf( T_( 'You have successfuly left the &laquo;%s&raquo; conversation!' ), $edited_Thread->get( 'title' ) ), 'success' );
                        break;

                    case
'close': // close the thread
                   
case 'close_and_block': // close the thread and block contact
                       
leave_thread( $edited_Thread->ID, $current_User->ID, true );

                       
// user has closed this conversation because there was only one other user involved
                       
$Messages->add( sprintf( T_( 'You have successfuly closed the &laquo;%s&raquo; conversation!' ), $edited_Thread->get( 'title' ) ), 'success' );
                        if(
$action == 'close_and_block' )
                        {
// user also wants to block contact with the other user involved in this thread
                           
$block_user_ID = param( 'block_ID', 'integer', true );
                           
$UserCache = & get_UserCache();
                           
$blocked_User = $UserCache->get_by_ID( $block_user_ID );

                           
set_contact_blocked( $block_user_ID, true );
                           
$Messages->add( sprintf( T_( '&laquo;%s&raquo; was blocked.' ), $blocked_User->get( 'login' ) ), 'success' );
                        }
                        break;
                }
                break;
// break from threads action switch

            // contacts action
           
case 'contacts':
               
$user_ID = param( 'user_ID', 'string', true );

                if( (
$action != 'block' ) && ( $action != 'unblock' ) )
                {
// only block or unblock is valid
                   
debug_die( "Invalid action param" );
                }
                if(
set_contact_blocked( $user_ID, ( ( $action == 'block' ) ? 1 : 0 ) ) )
                {
                    if(
$action == 'block' )
                    {
                       
$Messages->add( T_('You have blocked this user from contacting you.'), 'success' );
                    }
                    else
                    {
                       
$Messages->add( T_('You have unblocked this user so he can contact you again.'), 'success' );
                    }
                }
               
$redirect_to = str_replace( '&amp;', '&', $redirect_to );
                break;

           
// messages action
           
case 'messages':
                switch(
$action )
                {
                    case
'create': // create new message
                        // Stop a request from the blocked IP addresses or Domains
                       
antispam_block_request();

                       
create_new_message( $thrd_ID );
                        break;

                    case
'preview': // create new message
                        // Stop a request from the blocked IP addresses or Domains
                       
antispam_block_request();

                        global
$edited_Message;

                       
$creating_success = create_new_message( $thrd_ID, 'preview' );

                       
// save new message and thread params into the Session to not lose the content
                       
$unsaved_message_params = array();
                       
$unsaved_message_params[ 'action' ] = $action;
                       
$unsaved_message_params[ 'message' ] = $edited_Message->text;
                       
$unsaved_message_params[ 'message_original' ] = $edited_Message->original_text;
                       
$unsaved_message_params[ 'renderers' ] = $edited_Message->get_renderers_validated();
                       
$unsaved_message_params[ 'creating_success' ] = $creating_success;
                       
save_message_params_to_session( $unsaved_message_params );
                        break;

                    case
'delete': // delete message
                        // Check permission:
                       
check_user_perm( 'perm_messaging', 'delete', true );

                       
$msg_ID = param( 'msg_ID', 'integer', true );
                       
$MessageCache = & get_MessageCache();
                        if( (
$edited_Message = & $MessageCache->get_by_ID( $msg_ID, false )) === false )
                        {
                           
$Messages->add( sprintf( T_('Requested &laquo;%s&raquo; object does not exist any longer.'), T_('Message') ), 'error' );
                            break;
                        }

                       
$confirmed = param( 'confirmed', 'integer', 0 );
                        if(
$confirmed )
                        {
// delete message
                           
$edited_Message->dbdelete();
                            unset(
$edited_Message );
                           
$Messages->add( T_('Message deleted.'), 'success' );
                        }
                        else
                        {
                           
$delete_url = get_htsrv_url().'action.php?mname=messaging&disp=messages&thrd_ID='.$thrd_ID.'&msg_ID='.$msg_ID.'&action=delete&confirmed=1';
                            if( ! empty(
$Blog ) )
                            {
// Add blog ID to correctly redirect after deleting:
                               
$delete_url .= '&blog='.$Blog->ID;
                            }
                           
$delete_url = url_add_param( $delete_url, 'redirect_to='.rawurlencode( $redirect_to ), '&' ).'&'.url_crumb( 'messaging_messages' );
                           
$ok_button = '<a href="'.$delete_url.'" class="btn btn-danger">'.T_('I am sure!').'</a>';
                           
$cancel_button = '<a href="'.$redirect_to.'" class="btn btn-default">'.T_('CANCEL').'</a>';
                           
$msg = T_('You are about to delete this message. ').'<br /> '.T_('This CANNOT be undone!').'<br />'.T_( 'Are you sure?' ).'<br /><br />'.$ok_button."\t".$cancel_button;
                           
$Messages->add( $msg, 'error' );
                        }
                        break;
                }
                break;
        }

       
header_redirect( $redirect_to ); // Will save $Messages into Session
   
}


   
/**
     * Get contacts list params
     */
   
function get_contacts_list_params()
    {
        global
$module_contacts_list_params;

        if( !isset(
$module_contacts_list_params ) )
        {    
// Initialize this array first time
           
$module_contacts_list_params = array();
        }

       
$module_contacts_list_params['title_selected'] = T_('Send a message to all selected contacts');
       
$module_contacts_list_params['title_group'] = T_('Send a message to all %d contacts in the &laquo;%s&raquo; group');
       
$module_contacts_list_params['recipients_link'] = get_dispctrl_url( 'threads', 'action=new' );
    }
}

$messaging_Module = new messaging_Module();

?>