Seditio Source
Root |
./othercms/b2evolution_7.2.3/inc/collections/model/_blog.funcs.php
<?php
/**
 * This file implements Blog handling functions.
 *
 * This file is part of the evoCore framework - {@link http://evocore.net/}
 * See also {@link https://github.com/b2evolution/b2evolution}.
 *
 * @license GNU GPL v2 - {@link http://b2evolution.net/about/gnu-gpl-license}
 *
 * @copyright (c)2003-2020 by Francois Planque - {@link http://fplanque.com/}
 * Parts of this file are copyright (c)2004-2006 by Daniel HAHLER - {@link http://thequod.de/contact}.
 *
 * @package evocore
 */
if( !defined('EVO_MAIN_INIT') ) die( 'Please, do not access this page directly.' );


/**
 * Check if permission is always enabled
 *
 * @param object the db row
 * @param string the prefix of the db row: 'bloguser_' or 'bloggroup_'
 * @param string permission name
 * @param string Collection owner user ID
 * @return boolean
 */
function is_always_coll_perm_enabled( $row, $prefix, $perm, $coll_owner_user_ID )
{
    if(
$prefix == 'bloguser_' && $perm != 'perm_admin' && $coll_owner_user_ID == $row->user_ID )
    {    
// Collection owner has almost all permissions by default (One exception is "admin" perm to edit advanced/administrative coll properties):
       
return true;
    }

   
// Check if permission is always enabled by group setting:
   
if( ! empty( $row->user_ID ) )
    {    
// User perm:
       
$UserCache = & get_UserCache();
        if(
$User = & $UserCache->get_by_ID( $row->user_ID, false, false ) )
        {    
// Get user group:
           
$perm_Group = & $User->get_Group();
        }
    }
    elseif( ! empty(
$row->grp_ID ) )
    {    
// Group perm:
       
$GroupCache = & get_GroupCache();
       
$perm_Group = & $GroupCache->get_by_ID( $row->grp_ID, false, false );
    }

    if( ! empty(
$perm_Group ) )
    {    
// Check global group setting permission:
       
$group_perm_blogs = $perm_Group->get( 'perm_blogs' );
        if(
$group_perm_blogs == 'editall' )
        {    
// If the group has a global permission to edit ALL collections:
           
return true;
        }
        elseif(
$perm == 'ismember' && $group_perm_blogs == 'viewall' )
        {    
// If the group has a global permission to view or edit ALL collections:
           
return true;
        }
    }

    return
false;
}


/**
 * Update the advanced user/group permissions for edited blog
 *
 * @param integer Blog ID or Group ID
 * @param string 'user', 'group' or 'coll'
 */
function blog_update_perms( $object_ID, $context = 'user' )
{
    global
$DB;

   
// Get affected user/group IDs:
   
$IDs = param( $context.'_IDs', '/^[0-9]+(,[0-9]+)*$/', '' );
   
$ID_array = explode( ',', $IDs );

    switch(
$context )
    {
        case
'user':
           
$table = 'T_coll_user_perms';
           
$prefix = 'bloguser_';
           
$ID_field_main = 'bloguser_blog_ID';
           
$ID_field_edit = 'bloguser_user_ID';
           
$blog = $object_ID;
           
$coll_IDs = array( $blog );
            break;

        case
'coll':
           
$table = 'T_coll_group_perms';
           
$prefix = 'bloggroup_';
           
$ID_field_main = 'bloggroup_group_ID';
           
$ID_field_edit = 'bloggroup_blog_ID';
           
$group_ID = $object_ID;
           
$coll_IDs = $ID_array;
            break;

        case
'group':
        default:
           
$table = 'T_coll_group_perms';
           
$prefix = 'bloggroup_';
           
$ID_field_main = 'bloggroup_blog_ID';
           
$ID_field_edit = 'bloggroup_group_ID';
           
$blog = $object_ID;
           
$coll_IDs = array( $blog );
            break;
    }

    foreach(
$coll_IDs as $coll_ID )
    {
       
// Can the current user touch advanced admin permissions?
       
if( ! check_user_perm( 'blog_admin', 'edit', false, $coll_ID ) )
        {
// We have no permission to touch advanced admins!

            // Get the users/groups which are advanced admins
           
$admins_ID_array = $DB->get_col( "SELECT {$ID_field_edit}
                                                                                    FROM
$table
                                                                                 WHERE
{$ID_field_edit} IN (".implode( ',',$ID_array ).")
                                                                                                AND
{$ID_field_main} = $object_ID
                                                                                                AND
{$prefix}perm_admin <> 0" );

           
// Take the admins out of the list:
           
$ID_array = array_diff( $ID_array, $admins_ID_array );
        }
    }

    if( empty(
$ID_array ) )
    {
        return;
    }

   
$BlogCache = & get_BlogCache();
   
$BlogCache->load_list( $coll_IDs );

   
// Delete old perms for the edited collection/group:
   
$DB->query( "DELETE FROM $table
                                WHERE
{$ID_field_edit} IN (".implode( ',',$ID_array ).")
                                            AND
{$ID_field_main} = ".$object_ID );

   
$inserted_values = array();
    foreach(
$ID_array as $loop_ID )
    {    
// Check new permissions per each user or group or collection:

        // Get collection/object ID depedning on request:
       
$coll_ID = ( $context == 'coll' ? $loop_ID : $blog );
       
$main_object_ID = ( $context == 'coll' ? $group_ID : $blog );

       
// Use checkboxes
       
$perm_post = array();

       
$ismember = param( 'blog_ismember_'.$loop_ID, 'integer', 0 );
       
$can_be_assignee = param( 'blog_can_be_assignee_'.$loop_ID, 'integer', 0 );
       
$workflow_status = param( 'blog_workflow_status_'.$loop_ID, 'integer', 0 );
       
$workflow_user = param( 'blog_workflow_user_'.$loop_ID, 'integer', 0 );
       
$workflow_priority = param( 'blog_workflow_priority_'.$loop_ID, 'integer', 0 );

       
$perm_item_propose = param( 'blog_perm_item_propose_'.$loop_ID, 'integer', 0 );

       
$perm_published = param( 'blog_perm_published_'.$loop_ID, 'string', '' );
        if( !empty(
$perm_published) ) $perm_post[] = 'published';

       
$perm_community = param( 'blog_perm_community_'.$loop_ID, 'string', '' );
        if( !empty(
$perm_community) ) $perm_post[] = 'community';

       
$perm_protected = param( 'blog_perm_protected_'.$loop_ID, 'string', '' );
        if( !empty(
$perm_protected) ) $perm_post[] = 'protected';

       
$perm_private = param( 'blog_perm_private_'.$loop_ID, 'string', '' );
        if( !empty(
$perm_private) ) $perm_post[] = 'private';

       
$perm_review = param( 'blog_perm_review_'.$loop_ID, 'string', '' );
        if( !empty(
$perm_review) ) $perm_post[] = 'review';

       
$perm_draft = param( 'blog_perm_draft_'.$loop_ID, 'string', '' );
        if( !empty(
$perm_draft) ) $perm_post[] = 'draft';

       
$perm_deprecated = param( 'blog_perm_deprecated_'.$loop_ID, 'string', '' );
        if( !empty(
$perm_deprecated) ) $perm_post[] = 'deprecated';

       
$perm_redirected = param( 'blog_perm_redirected_'.$loop_ID, 'string', '' );
        if( !empty(
$perm_redirected) ) $perm_post[] = 'redirected';

       
$perm_item_type = param( 'blog_perm_item_type_'.$loop_ID, 'string', 'standard' );
       
$perm_edit = param( 'blog_perm_edit_'.$loop_ID, 'string', 'no' );

       
$perm_delpost = param( 'blog_perm_delpost_'.$loop_ID, 'integer', 0 );
       
$perm_edit_ts = param( 'blog_perm_edit_ts_'.$loop_ID, 'integer', 0 );

       
$perm_delcmts = param( 'blog_perm_delcmts_'.$loop_ID, 'integer', 0 );
       
$perm_recycle_owncmts = param( 'blog_perm_recycle_owncmts_'.$loop_ID, 'integer', 0 );
       
$perm_vote_spam_comments = param( 'blog_perm_vote_spam_cmts_'.$loop_ID, 'integer', 0 );
       
$perm_cmtstatuses = 0;
       
$perm_cmtstatuses += param( 'blog_perm_published_cmt_'.$loop_ID, 'integer', 0 ) ? get_status_permvalue( 'published' ) : 0;
       
$perm_cmtstatuses += param( 'blog_perm_community_cmt_'.$loop_ID, 'integer', 0 ) ? get_status_permvalue( 'community' ) : 0;
       
$perm_cmtstatuses += param( 'blog_perm_protected_cmt_'.$loop_ID, 'integer', 0 ) ? get_status_permvalue( 'protected' ) : 0;
       
$perm_cmtstatuses += param( 'blog_perm_private_cmt_'.$loop_ID, 'integer', 0 ) ? get_status_permvalue( 'private' ) : 0;
       
$perm_cmtstatuses += param( 'blog_perm_review_cmt_'.$loop_ID, 'integer', 0 ) ? get_status_permvalue( 'review' ) : 0;
       
$perm_cmtstatuses += param( 'blog_perm_draft_cmt_'.$loop_ID, 'integer', 0 ) ? get_status_permvalue( 'draft' ) : 0;
       
$perm_cmtstatuses += param( 'blog_perm_deprecated_cmt_'.$loop_ID, 'integer', 0 ) ? get_status_permvalue( 'deprecated' ) : 0;
       
$perm_edit_cmt = param( 'blog_perm_edit_cmt_'.$loop_ID, 'string', 'no' );

       
$perm_meta_comments = param( 'blog_perm_meta_comment_'.$loop_ID, 'integer', 0 );
       
$perm_cats = param( 'blog_perm_cats_'.$loop_ID, 'integer', 0 );
       
$perm_properties = param( 'blog_perm_properties_'.$loop_ID, 'integer', 0 );

        if(
check_user_perm( 'blog_admin', 'edit', false, $coll_ID ) )
        {
// We have permission to give advanced admins perm!
           
$perm_admin = param( 'blog_perm_admin_'.$loop_ID, 'integer', 0 );
        }
        else
        {
           
$perm_admin = 0;
        }

       
$perm_media_upload = param( 'blog_perm_media_upload_'.$loop_ID, 'integer', 0 );
       
$perm_media_browse = param( 'blog_perm_media_browse_'.$loop_ID, 'integer', 0 );
       
$perm_media_change = param( 'blog_perm_media_change_'.$loop_ID, 'integer', 0 );

       
$perm_analytics = param( 'blog_perm_analytics_'.$loop_ID, 'integer', 0 );

       
// Update those permissions in DB:

        // Update permissions per user or group or collection if at least on is selected:
       
$update_permissions = ( $ismember || $can_be_assignee || $workflow_status || $workflow_user || $workflow_priority ||
           
$perm_item_propose || count($perm_post) || $perm_delpost || $perm_edit_ts || $perm_delcmts || $perm_recycle_owncmts || $perm_vote_spam_comments || $perm_cmtstatuses ||
           
$perm_meta_comments || $perm_cats || $perm_properties || $perm_admin || $perm_media_upload || $perm_media_browse || $perm_media_change || $perm_analytics );
        if( !
$update_permissions &&
            (
$perm_Blog = & $BlogCache->get_by_ID( $coll_ID, false, false ) ) )
        {    
// When all permissions are disabled(not checked),
            // do additional check for users or groups which are always members of the Collection:
           
$null_row = ( $context == 'user'
               
? array( 'user_ID' => $loop_ID )
                : array(
'grp_ID'  => ( $context == 'coll' ? $group_ID : $loop_ID ) ) );
           
$update_permissions = is_always_coll_perm_enabled( (object)$null_row, $prefix, 'can_be_assignee', $perm_Blog->get( 'owner_user_ID' ) );
        }

        if(
$update_permissions )
        {    
// Initialize value to update permissions:
           
$ismember = 1;    // Must have this permission

            // insert new perms:
           
$inserted_values[] = " ( $main_object_ID, $loop_ID, $ismember, $can_be_assignee, $workflow_status, $workflow_user, $workflow_priority, $perm_item_propose, ".$DB->quote( implode( ',',$perm_post ) ).",
                                                                "
.$DB->quote( $perm_item_type ).", ".$DB->quote( $perm_edit ).",
                                                               
$perm_delpost, $perm_edit_ts, $perm_delcmts, $perm_recycle_owncmts, $perm_vote_spam_comments, $perm_cmtstatuses,
                                                                "
.$DB->quote( $perm_edit_cmt ).",
                                                               
$perm_meta_comments, $perm_cats, $perm_properties, $perm_admin, $perm_media_upload,
                                                               
$perm_media_browse, $perm_media_change, $perm_analytics )";
        }
    }

   
// Proceed with insertions:
   
if( count( $inserted_values ) )
    {
       
$DB->query( "INSERT INTO $table( {$ID_field_main}, {$ID_field_edit}, {$prefix}ismember, {$prefix}can_be_assignee, {$prefix}workflow_status, {$prefix}workflow_user, {$prefix}workflow_priority,
                                           
{$prefix}perm_item_propose, {$prefix}perm_poststatuses, {$prefix}perm_item_type, {$prefix}perm_edit, {$prefix}perm_delpost, {$prefix}perm_edit_ts,
                                           
{$prefix}perm_delcmts, {$prefix}perm_recycle_owncmts, {$prefix}perm_vote_spam_cmts, {$prefix}perm_cmtstatuses, {$prefix}perm_edit_cmt,
                                           
{$prefix}perm_meta_comment, {$prefix}perm_cats, {$prefix}perm_properties, {$prefix}perm_admin,
                                           
{$prefix}perm_media_upload, {$prefix}perm_media_browse, {$prefix}perm_media_change, {$prefix}perm_analytics )
                                    VALUES "
.implode( ',', $inserted_values ) );
    }

   
// Unassign users that no longer can be assignees from the items of the collection:
   
$DB->query( 'UPDATE T_items__item
            SET post_assigned_user_ID = NULL
        WHERE post_assigned_user_ID IS NOT NULL
          AND post_main_cat_ID IN
          (
            SELECT cat_ID
              FROM T_categories
             WHERE cat_blog_ID IN ( '
.$DB->quote( $coll_IDs ).' )
          )
          AND post_assigned_user_ID NOT IN
          (
            SELECT user_ID
              FROM T_users
             INNER JOIN T_groups ON user_grp_ID = grp_ID
             WHERE grp_perm_blogs = "editall"
          )
          AND post_assigned_user_ID NOT IN
          (
            SELECT blog_owner_user_ID
              FROM T_blogs
             WHERE blog_ID IN ( '
.$DB->quote( $coll_IDs ).' )
          )
          AND post_assigned_user_ID NOT IN
          (
            SELECT bloguser_user_ID
              FROM T_coll_user_perms
             WHERE bloguser_can_be_assignee = 1
               AND bloguser_blog_ID IN ( '
.$DB->quote( $coll_IDs ).' )
          )
          AND post_assigned_user_ID NOT IN
          (
            SELECT user_ID
              FROM T_users INNER JOIN T_coll_group_perms ON user_grp_ID = bloggroup_group_ID
             WHERE bloggroup_can_be_assignee = 1
               AND bloggroup_blog_ID IN ( '
.$DB->quote( $coll_IDs ).' )
          )
          AND post_assigned_user_ID NOT IN
          (
            SELECT sug_user_ID
              FROM T_users__secondary_user_groups
             INNER JOIN T_coll_group_perms ON sug_grp_ID = bloggroup_group_ID
             WHERE bloggroup_can_be_assignee = 1
               AND bloggroup_blog_ID IN ( '
.$DB->quote( $coll_IDs ).' )
          )'
);

    if(
$DB->rows_affected > 0 )
    {
        global
$Messages;
       
$Messages->add( sprintf( '%d tasks have lost their assignee due to new permissions (this may include fixes to older inconsistencies in the DB).', $DB->rows_affected ), 'warning' );
    }

   
// BLOCK CACHE INVALIDATION:
   
foreach( $coll_IDs as $coll_ID )
    {
       
BlockCache::invalidate_key( 'set_coll_ID', $coll_ID ); // Settings have changed
   
}
   
BlockCache::invalidate_key( 'set_coll_ID', 'any' ); // Settings of a have changed (for widgets tracking a change on ANY blog)

    // cont_coll_ID  // Content has not changed
}


/**
 * Check permissions on a given blog (by ID) and autoselect an appropriate blog
 * if necessary.
 *
 * For use in admin
 *
 * NOTE: we no longer try to set $Blog inside of the function because later global use cannot be safely guaranteed in PHP4.
 *
 * @param string Permission name that must be given to the {@link $current_User} object.
 * @param string Permission level that must be given to the {@link $current_User} object.
 * @return integer new selected blog
 */
function autoselect_blog( $permname, $permlevel = 'any' )
{
    global
$blog;

 
/**
     * @var User
     */
   
global $current_User;

   
$autoselected_blog = $blog;

    if(
$autoselected_blog )
    {
// a blog is already selected
       
if( ! check_user_perm( $permname, $permlevel, false, $autoselected_blog ) )
        {
// invalid blog
             // echo 'current blog was invalid';
           
$autoselected_blog = 0;
        }
    }

    if( !
$autoselected_blog )
    {
// No blog is selected so far (or selection was invalid)...
        // Let's try to find another one:

    /**
         * @var BlogCache
         */
       
$BlogCache = & get_BlogCache();

       
// Get first suitable blog
       
$blog_array = $BlogCache->load_user_blogs( $permname, $permlevel, $current_User->ID, 'ID', 'ASC', 1 );
        if( !empty(
$blog_array) )
        {
           
$autoselected_blog = $blog_array[0];
        }
    }

    return
$autoselected_blog;
}


/**
 * Check that we have received a valid blog param
 *
 * For use in admin
 */
function valid_blog_requested()
{
    global
$Collection, $Blog, $Messages;
    if( empty(
$Blog ) )
    {
// The requested blog does not exist, Try to get other available blog for the current User
       
$blog_ID = get_working_blog();
        if(
$blog_ID )
        {
           
$BlogCache = & get_BlogCache();
           
$Collection = $Blog = $BlogCache->get_by_ID( $blog_ID, false, false );
        }
    }

    if( empty(
$Blog ) )
    {
// The requested blog does not exist
       
$Messages->add( T_('The requested blog does not exist (any more?)'), 'error' );
        return
false;
    }
    return
true;
}


/**
 * Get working blog
 *
 * For use in backoffice
 *
 * @return integer|FALSE Blog ID or FALSE when no available blog to view by current User
 */
function get_working_blog()
{
    global
$blog, $UserSettings;

    if( !
is_logged_in() )
    {
// User must be logged in to view the blogs
       
return false;
    }

    if( ! empty(
$blog ) )
    {
// Use a blog from GET request
       
$blog_ID = intval( $blog );
        if(
$blog_ID > 0 && check_user_perm( 'blog_ismember', 'view', false, $blog_ID ) )
        {
// Allow to use this blog only when current user has an access to view it
           
return $blog_ID;
        }
    }

   
$BlogCache = & get_BlogCache();

   
// Try to use the blog which is selected by current user last time
   
$blog_ID = intval( $UserSettings->get( 'selected_blog' ) );
   
// Check if it really exists in DB
   
$selected_Blog = & $BlogCache->get_by_ID( $blog_ID, false, false );
    if(
$selected_Blog && check_user_perm( 'blog_ismember', 'view', false, $selected_Blog->ID ) )
    {
// Allow to use this blog only when current user is a member of it
       
return $blog_ID;
    }

   
// Use first blog from DB which current user can views
   
if( $blog_array = $BlogCache->load_user_blogs( 'blog_ismember', 'view', NULL, '', '', 1 ) )
    {
        foreach(
$blog_array as $blog_ID )
        {
            return
$blog_ID;
        }
    }

    return
false;
}


/**
 * Set working blog to a new value and memorize it in user settings if needed.
 *
 * For use in backoffice
 *
 * @return boolean $blog changed?
 */
function set_working_blog( $new_blog_ID )
{
    global
$blog, $UserSettings;

    if( !
is_logged_in() )
    {    
// User must be logged in to set working collection:
       
return false;
    }

    if(
$new_blog_ID != (int)$UserSettings->get('selected_blog') )
    {
// Save the new default blog.
        // fp> Test case 1: dashboard without a blog param should go to last selected blog
        // fp> Test case 2: uploading to the default blog may actually upload into another root (sev)
       
$UserSettings->set( 'selected_blog', $blog );
       
$UserSettings->dbupdate();
    }

    if(
$new_blog_ID == $blog )
    {
        return
false;
    }

   
$blog = $new_blog_ID;

    return
true;
}


/**
 * Get collection kinds
 * (might be extended by plugins)
 *
 * @param string Blog type
 * @return array|string
 */
function get_collection_kinds( $kind = NULL )
{
    global
$Plugins;

   
$kinds = array(
       
'minisite' => array(
               
'name' => T_('Mini-Site'),
               
'class' => 'btn-primary',
               
'desc' => T_('Use this to build a <b>small site</b> consisting of a home page and only a few additional pages.'),
               
'note' => T_('Use this if you want to start with a relatively simple "page builder".')
                                .
'<br />'.T_('If your site grows, you can always switch this to a "Home / Main" collection later.'),
            ),
       
'main' => array(
               
'name' => T_('Home / Main'),
               
'class' => 'btn-primary',
               
'desc' => T_('Use this as a site homepage to build a <b>large site</b> consisting of a home page <b>plus</b> several sections (where each section is a separate collection).'),
               
'note' => T_('By default, this home collection will aggregate the contents of all your other collections.')
                                .
'<br />'.T_('This collection can also be used to display all the cross-collection site features such as registration, login, user profiles, private messaging, etc.'),
            ),
       
'std' => array(
               
'name' => T_('Blog'), // NOTE: this is a REAL usage of the word 'Blog'. Do NOT change to 'collection'.
               
'class' => 'btn-info',
               
'desc' => T_('A collection of Posts, optimized to present <b>articles or news</b>, sorted primarily by date.'),
               
'note' => T_('Use this is you are going to publish fresh content on a regular basis.')
                                .
'<br />'.T_('Can be used as a section of a larger site.'),
            ),
       
'manual' => array(
               
'name' => T_('Manual'),
               
'class' => 'btn-info',
               
'desc' => T_('A collection of Pages, optimized to present <b>reference material</b> organized into chapters, sub-chapters, etc.'),
               
'note' => T_('Use this if you want to publish an online manual, a reference section, a book or a guide.')
                                .
'<br />'.T_('Can be used as a section of a larger site.').' '.T_('Should be used with a "manual" skin.'),
            ),
       
'photo' => array(
               
'name' => T_('Gallery'),
               
'class' => 'btn-info',
               
'desc' => T_('A collection of Albums, optimized to present <b>photos</b> grouped into small <b>albums</b>.'),
               
'note' => T_('Use this if you want to publish several images at a time, without much text.')
                                .
'<br />'.T_('Can be used as a section of a larger site.').' '.T_('This should be used with a "gallery" skin.'),
            ),
       
'forum' => array(
               
'name' => T_('Forum'),
               
'class' => 'btn-info',
               
'desc' => T_('A collection of Topics (and replies), optimized to be used as an <b>interactive discussion forum</b>.'),
               
'note' => T_('Users will be able to post new topics and replies from the front-office.')
                                .
'<br />'.T_('Can be used as a section of a larger site.').' '.T_('This should be used with a "forums" skin.'),
            ),
       
'group' => array(
               
'name' => T_('Tracker'),
               
'class' => 'btn-info',
               
'desc' => T_('A collection of Issues, optimized for <b>issue tracking</b> or <b>collaborative editing</b> between multiple users.'),
               
'note' => T_('Look for the workflow properties on the post editing form.')
                                .
'<br />'.T_('Can be used as a section of a larger site.').' '.T_('Should be used with a "tracker" skin. May also be used only in back-office.'),
            ),
        );

   
// Define blog kinds, their names and description.
   
$plugin_kinds = $Plugins->trigger_collect( 'GetCollectionKinds', array('kinds' => & $kinds) );

    foreach(
$plugin_kinds as $l_kinds )
    {
       
$kinds = array_merge( $l_kinds, $kinds );
    }

    if(
is_null( $kind ) )
    {
// Return kinds array
       
return $kinds;
    }

    if(
array_key_exists( $kind, $kinds ) && !empty($kinds[$kind]['name']) )
    {
        return
$kinds[$kind]['name'];
    }
    else
    {    
// Use default collection kind
       
return $kinds['std']['name'];
    }
}


/**
 * Enable/Disable the given cache
 *
 * @param string cache key name, 'general_cache_enabled', blogs 'cache_enabled'
 * @param boolean status to set
 * @param integer the id of the blog, if we want to set a blog's cache. Let it NULL to set general caching.
 * @param boolean true to save db changes, false if db update will be called outside from this function
 */
function set_cache_enabled( $cache_key, $new_status, $coll_ID = NULL, $save_setting = true )
{
   
load_class( '_core/model/_pagecache.class.php', 'PageCache' );
    global
$Settings;

    if( empty(
$coll_ID ) )
    {
// general cache
       
$Collection = $Blog = NULL;
       
$old_cache_status = $Settings->get( $cache_key );
    }
    else
    {
// blog page cache
       
$BlogCache = & get_BlogCache();
       
$Collection = $Blog = $BlogCache->get_by_ID( $coll_ID );
       
$old_cache_status = $Blog->get_setting( $cache_key );
    }

   
$PageCache = new PageCache( $Blog );
    if(
$old_cache_status == false && $new_status == true )
    {
// Caching has been turned ON:
       
if( $PageCache->cache_create( false ) )
        {
// corresponding cache folder was created
           
if( empty( $coll_ID ) )
            {
// general cache
               
$result = array( 'success', T_( 'General caching has been enabled.' ) );
            }
            else
            {
// blog page cache
               
$result = array( 'success', T_( 'Page caching has been enabled.' ) );
            }
        }
        else
        {
// error creating cache folder
           
if( empty( $coll_ID ) )
            {
// general cache
               
$result = array( 'error', T_( 'General caching could not be enabled. Check /cache/ folder file permissions.' ) );
            }
            else
            {
// blog page cache
               
$result = array( 'error', T_( 'Page caching could not be enabled. Check /cache/ folder file permissions.' ) );
            }
           
$new_status = false;
        }
    }
    elseif(
$old_cache_status == true && $new_status == false )
    {
// Caching has been turned OFF:
       
$PageCache->cache_delete();
        if( empty(
$coll_ID ) )
        {
// general cache
           
$result = array( 'note',  T_( 'General caching has been disabled. Cache contents have been purged.' ) );
        }
        else
        {
// blog page cache
           
$result = array( 'note',  T_( 'Page caching has been disabled. Cache contents have been purged.' ) );
        }
    }
    else
    {
// nothing was changed
        // check if ajax_form_enabled has correct state after b2evo upgrade
       
if( ( $Blog != NULL ) && ( $new_status ) && ( !$Blog->get_setting( 'ajax_form_enabled' ) ) )
        {
// if page cache is enabled, ajax form must be enabled to
           
$Blog->set_setting( 'ajax_form_enabled', true );
           
$Blog->dbupdate();
        }
        return
NULL;
    }

   
// set db changes
   
if( $Blog == NULL )
    {
       
$Settings->set( 'general_cache_enabled', $new_status );
        if(
$save_setting )
        {
// save
           
$Settings->dbupdate();
        }
    }
    else
    {
       
$Blog->set_setting( $cache_key, $new_status );
        if( (
$cache_key == 'cache_enabled' ) && $new_status )
        {
// if page cache is enabled, ajax form must be enabled to
           
$Blog->set_setting( 'ajax_form_enabled', true );
        }
        if(
$save_setting )
        {
// save
           
$Blog->dbupdate();
        }
    }
    return
$result;
}


/**
 * Identify requested collection & initialize global $blog variable to the requested collection
 * This is when we go through index.php (NOT through stub file).
 *
 * @param boolean try to identify a TinySlug before trying to identify a collection
 * @param boolean if the domain does not match a collection, try to process as a TinyURL and redirect before fallback to default collection
 * @return boolean true if $blog was initialized successful, false otherwise
 */
function init_requested_coll_or_process_tinyurl( $process_tinyslug_first = true, $process_unknown_domain_as_tinyurl = true )
{
    global
$blog, $ReqHost, $ReqURL, $sanitized_ReqPath, $baseurl, $pagenow;
    global
$Settings;
    global
$Debuglog;
    global
$resolve_extra_path, $slug_extra_term;

    if( !empty(
$blog ) )
    {    
// $blog was already initialized (maybe through a stub file)
        // Don't do any extra processing. This also means you cannot do TinyURLs through a blog stub file, which is ok.
       
return true;
    }

   
// Set some defaults in case we cannot get those from the URL:
   
$last_part = '';
   
$slug_extra_term = '';


    if( ! isset(
$resolve_extra_path ) )
    {    
// Resolve extra path by default:
       
$resolve_extra_path = true;
    }

    if(
$resolve_extra_path )
    {
       
/*
         * Now we will start to decode the URL extra path
         *
         * Possible urls:
         *
         * Decoding should try to work like this:
         *
         * baseurl/blog-urlname/junk/.../junk/post-slug     -> points to a single post (no ending slash)
         * baseurl/blog-urlname/junk/.../junk/aA1           -> points to a single post with TinySlug (special format)
         * baseurl/blog-urlname/junk/.../junk/p142          -> points to a single post
         * baseurl/blog-urlname/2006/                       -> points to a yearly archive because of ending slash + 4 digits
         * baseurl/blog-urlname/2006/12/                    -> points to a monthly archive
         * baseurl/blog-urlname/2006/12/31/                 -> points to a daily archive
         * baseurl/blog-urlname/2006/w53/                   -> points to a weekly archive
         * baseurl/blog-urlname/junk/.../junk/chap-urlname/ -> points to a single chapter/category (because of ending slash)
         *                                                                     Note: category names cannot be named like this [a-z][0-9]+
         *
         * All the above can also exist with a PHP file inserted, like this:
         * baseurl/index.php/blog-urlname/junk/.../junk/post-slug  
         * baseurl/stubfile.php/blog-urlname/junk/.../junk/post-slug  
         *
         * All the above can also exist with a specific collection domain for direct selection of collection:
         * specific-coll-domain/junk/.../junk/post-title    -> points to a single post (no ending slash)
         * baseurl/blog-urlname/junk/.../junk/p142          -> points to a single post
         *
         * And we can also have Tiny URLs:
         * anydomain/aA1                                    -> points to a single post with TinySlug (special format) AND should be processed with special "TinySlug processing" (301 + params)
         * anydomain/post-slug                              -> points to a single post with short format URL AND should be processed with special "TinySlug processing" (301 + params)
         *
         * So the GENERAL case is:
         * domain/first-part/.../.../.../last-part
         * domain/first-part/.../.../.../last-part/
         * The FIRST and LAST part may have special meanings, so we need to extract them and STORE them for use in multiple places.
         */
       
$Debuglog->add( 'Extra path info found! path_string='.$sanitized_ReqPath, 'url_decode_part_1' );
       
// echo "path=[$sanitized_ReqPath]<br />";

        // Slice the path:
       
$path_elements = preg_split( '~/~', $sanitized_ReqPath, 20, PREG_SPLIT_NO_EMPTY );
       
// pre_dump( '', $path_elements, $pagenow );

        // PREVENT index.php or blog1.php etc from being considered as a slug later on.
       
if( isset( $path_elements[0] ) && $path_elements[0] == $pagenow )
        {
// Ignore element that is the current PHP file name (ideally this URL will later be redirected to a canonical URL without any .php file in the URL)
           
array_shift( $path_elements );
           
$Debuglog->add( 'Ignoring *.php in extra path info' , 'url_decode_part_1' );
        }

       
// Do we still have extra path info to decode?
       
if( count( $path_elements ) )
        {

           
// this is the LAST path element!
           
$last_part = $path_elements[count( $path_elements )-1];

            if(
strpos( $last_part, ' ' ) !== false )
            {    
// Extract extra term form slug with space as separator:
               
$last_part = explode( ' ', $last_part, 2 );
                if( isset(
$last_part[1] ) )
                {    
// Set extra term from part of slug after first space:
                   
$slug_extra_term = $last_part[1];
                }
               
// Use only part before first space, because slug cannot has a space:
               
$last_part = $last_part[0];
            }
        }
    }


    if(
$process_tinyslug_first && ! empty( $last_part ) && $Settings->get( 'redirect_tinyurl' ) )
    {    
// We should redirect from Tiny URLs to canonical URLs:
       
load_funcs( 'slugs/model/_slug.funcs.php' );
        if(
is_tiny_slug( $last_part ) )
        {    
// The last part of the current URL looks like Tiny URL:
           
$Debuglog->add( '$last_part has correct TinySlug format: '.$last_part, 'url_decode_part_1' );
            if( (
$ItemCache = & get_ItemCache() ) &&
                (
$Item = & $ItemCache->get_by_urltitle( $last_part, false, false ) ) && // Item is found by the requested Tiny URL
               
( $SlugCache = & get_SlugCache() ) &&
                (
$item_Slug = & $SlugCache->get_by_ID( $Item->get( 'tiny_slug_ID' ), false, false ) ) ) // Tiny Slug is found in DB)
           
{    // If we have a tiny-slug and we find a matching Item:
               
$Debuglog->add( 'Found Item for that slug: #'.$Item->ID.' ('.$Item->get( 'title' ).')', 'url_decode_part_1' );

               
// Redirect from tiny URL to canonical URL of the detected Item:
               
$Item->tinyurl_redirect( $last_part, $slug_extra_term );
               
// Exit here.
           
}
        }
    }


   
$Debuglog->add( 'Trying to identify collection by extra path...', 'url_decode_part_1' );

   
// No collection requested by URL param, let's try to match something in the URL:
    // Note: we try to find a matching collection URL BEFORE falling back to considering a tinyURL:
   
$BlogCache = & get_BlogCache();

   
// fp>yb: What is this for? Make protocol lowercase?
   
$baseurl_regex = preg_replace( '/^https?(.*)/i', 'https?$1', preg_quote( $baseurl, '#' ) );

    if(
preg_match( '#^'.$baseurl_regex.'(index.php/)?([^/]+)#', $ReqHost.$sanitized_ReqPath, $matches ) )
    {
// We have an URL that is of the form `http://domain.com/slug` or `http://domain.com/index.php/slug` (NOTE: may still contain `slug.php`)
       
$Debuglog->add( 'Found a potential URL collection name: '.$matches[2].' (in: '.$ReqHost.$sanitized_ReqPath.')', 'url_decode_part_1' );
        if(
strpos( $matches[2], '.' ) !== false )
        {    
// There is an extension (like .php) in the collection name, ignore...
           
$Debuglog->add( 'Ignoring because it contains a dot.', 'url_decode_part_1' );
        }
        elseif( (
$Collection = $Blog = & $BlogCache->get_by_urlname( $matches[2], false ) ) !== false ) /* SQL request '=' */
       
{ // We found a matching Collection by collection Slug:
           
$blog = $Blog->ID;
           
$Debuglog->add( 'Found matching collection: '.$blog, 'url_decode_part_1' );
            return
true;
        }
        else
        {
           
$Debuglog->add( 'No match.', 'url_decode_part_1' );
        }
    }


   
// No collection identified by URL name, let's try to match the absolute URL:
    // Remove optional index.php:
   
if( preg_match( '#^(.+?)index.php#', $ReqHost.$sanitized_ReqPath, $matches ) )
    {
// Remove everything starting at `index.php...`:
       
$ReqAbsUrl = $matches[1];
    }
    else
    {    
// Match on the whole URL (we'll try to find the base URL at the beginning)
       
$ReqAbsUrl = $ReqHost.$sanitized_ReqPath;
    }

   
$Debuglog->add( 'Trying to identify collection by looking up Absolute url: '.$ReqAbsUrl, 'url_decode_part_1' );
   
// SQL request 'LIKE':
   
if( ( $Collection = $Blog = & $BlogCache->get_by_url( $ReqAbsUrl, false ) ) !== false )
    {
// We found a matching collection:
       
$blog = $Blog->ID;
       
$Debuglog->add( 'Found matching collection: '.$blog, 'url_decode_part_1' );
        return
true;
    }


   
// No collection identified by absolute URL, try searching URL aliases:
   
$Debuglog->add( 'Trying to identify collection by looking up URL aliases...', 'url_decode_part_1' );
   
$alias = NULL;
    if( (
$Collection = $Blog = & $BlogCache->get_by_url_alias( $ReqAbsUrl, $alias, false ) ) !== false )
    {
// We found a matching collection:
       
$Debuglog->add( 'Found matching collection: '.$blog. 'using alias '.$alias, 'url_decode_part_1' );
       
// Find tail from the currently requested alias URL:
       
$same_protocol_alias = url_same_protocol( $alias, $ReqAbsUrl );
       
$tail_Path = str_replace( $same_protocol_alias, '', $ReqURL );
        if(
substr( $tail_Path, 0, 1 ) != '/' )
        {
// Tail must start with '/'
           
$tail_Path = '/'.$tail_Path;
        }
       
// Redirect from alias collection URL to real collection URL:
       
$redirect_to = url_add_tail( $Blog->gen_blogurl(), $tail_Path );
        if(
$Blog->get_setting( 'http_protocol' ) == 'allow_both' )
        {    
// Allow any protocol of the current alias URL:
// fp> DO we really want to redirect immediately here (in case there is extra path?)
// yb> Here we always need a redirect from alias collection URL to real collection URL.
           
$redirect_to = url_same_protocol( $redirect_to, $ReqAbsUrl );
        }
       
// Else redirect to real collection URL only with protocol that is used by default for the collection base URL:
       
header_redirect( $redirect_to, 301 );
    }


   
// No collection identified by Absolute URL or URL alias...
    // Check for ?blog=123 param now:
   
$Debuglog->add( 'Checking for explicit "blog" param', 'url_decode_part_1' );
   
$blog = param( 'blog', 'integer', '', true );

    if( !empty(
$blog) )
    {
// a specific collection has been requested in the URL:
       
return true;
    }


   
// Check if the default collection uses the current domain as baseurl:
    // (because we do NOT want to process as tinyURL in that case, that would prevent loading pages like http://domain.com/about )
   
$default_blog_ID = $Settings->get( 'default_blog_ID' );
   
$default_Collection = & $BlogCache->get_by_ID( $default_blog_ID, false, false );
    if(
$default_Collection !== NULL )
    {
// There is a default collection:
       
$default_Collection_baseurl = $default_Collection->gen_baseurl();
       
$Debuglog->add( 'The default collection lives on: '.$default_Collection_baseurl, 'url_decode_part_1' );
        if(
is_same_url( $default_Collection_baseurl, $ReqHost.'/' ) )
        {    
           
$Debuglog->add( 'Match! We will consider that we are requesting a page of the default collection: '.$default_blog_ID, 'url_decode_part_1' );
           
$blog = $default_blog_ID;
           
$Collection = $default_Collection;
            return
true;
        }
    }

   
// No collection identified, we MUST now consider the domain as being a TinyURL domain:
   
if( $process_unknown_domain_as_tinyurl && ! empty( $last_part ) && $Settings->get( 'redirect_tinyurl' ) )
    {
       
// Check if the URL matches a tinyurl scheme `https?://x.y.z.domain.tld/slug` without extra folders or params:
       
if( preg_match( '#^https?://[a-z0-9\-_.]+\.[a-z]+/[a-z0-9\-_\+\s%]+$#i', $ReqAbsUrl ) )
        {
           
$Debuglog->add( 'URL has correct TinyURL format: '.$ReqAbsUrl, 'url_decode_part_1' );

            if( (
$ItemCache = & get_ItemCache() ) &&
                (
$Item = & $ItemCache->get_by_urltitle( $last_part, false, false ) ) )
            {    
// If we find a matching Item by slug:
               
$Debuglog->add( 'Found Item for that slug: #'.$Item->ID.' ('.$Item->get( 'title' ).')', 'url_decode_part_1' );

               
// Redirect from tiny URL to canonical URL of the detected Item:
               
$Item->tinyurl_redirect( $last_part, $slug_extra_term );
               
// Exit here.
           
}
        }
    }


   
// Still no collection matches and no TinyURL identified, use default Collection:
   
if( $default_Collection !== NULL )
    {
// We found a matching blog:
       
$blog = $default_blog_ID;
       
$Collection = $default_Collection;
       
$Debuglog->add( 'Falling back to default collection: '.$blog, 'url_decode_part_1' );
        return
true;
    }

   
// No collection has been selected (we'll probably display the default.php page):
   
$Debuglog->add( 'We cannot use any specific collection.', 'url_decode_part_1' );
   
$blog = NULL;
    return
false;
}


/**
 * Activate the blog locale and the corresponding charset
 *
 * @param integer the blog Id
 */
function activate_blog_locale( $blog )
{
    global
$current_charset;

    if( empty(
$blog ) || ( $blog <= 0 ) )
    {
// $blog is not a valid blog ID
       
return;
    }

   
$BlogCache = & get_BlogCache();
   
$Collection = $Blog = $BlogCache->get_by_ID( $blog, false, false );
    if( !empty(
$Blog ) )
    {
// Activate the blog locale
       
locale_activate( $Blog->get('locale') );

       
// Re-Init charset handling, in case current_charset has changed:
       
init_charsets( $current_charset );
    };
}


/**
 * Initialize blog enabled widgets. It will call every enabled widget request_required_files() function.
 *
 * @param integer blog ID
 */
function init_blog_widgets( $blog_id )
{
   
/**
     * @var EnabledWidgetCache
     */
   
$EnabledWidgetCache = & get_EnabledWidgetCache();
   
$container_Widget_array = & $EnabledWidgetCache->get_by_coll_ID( $blog_id );

    if( !empty(
$container_Widget_array) )
    {
        foreach(
$container_Widget_array as $container=>$Widget_array )
        {
            foreach(
$Widget_array as $ComponentWidget )
            {    
// Let the Widget initialize itself:
               
$ComponentWidget->request_required_files();
            }
        }
    }
}


/**
 * Check if user is activated and status allow to display the requested form ($disp).
 * Do nothing if status is activated or can't be activated or display is not allowed, add error message to activate the account otherwise.
 * asimo>TODO: We may find a better name and a better place for this function ( maybe user.funcs.php )
 *
 * @param string the requested view name
 */
function check_allow_disp( $disp )
{
    global
$Collection, $Blog, $Messages;

    if( !
check_user_status( 'can_be_validated' ) )
    {
// we don't have the case when user is logged in and the account is not active
       
return;
    }

   
$messages_content = $Messages->get_string( '', '', '', 'raw' );
    if( (
strstr( $messages_content, 'disp=activateinfo' ) !== false ) || ( strstr( $messages_content, 'action=req_activate_email' ) !== false ) )
    {
// If there is already a message to display activateinfo link, then don't add this message again
       
return;
    }

    switch(
$disp )
    {
        case
'activateinfo':
           
// don't display activate account error notification in activate info page
           
return;
            break;
// already exited before this
       
case 'contacts':
            if( !
check_user_status( 'can_view_contacts' ) )
            {
// contacts view display is not allowed
               
return;
            }
            break;
        case
'edit':
            if( !
check_user_status( 'can_edit_post' ) )
            {
// edit post is not allowed
               
return;
            }
            break;
        case
'messages':
            if( !
check_user_status( 'can_view_messages' ) )
            {
// messages view display is not allowed
               
return;
            }
            break;
        case
'msgform':
            if( !
check_user_status( 'can_view_msgform' ) )
            {
// msgform display is not allowed
               
return;
            }
            break;
        case
'threads':
            if( !
check_user_status( 'can_view_threads' ) )
            {
// threads view display is not allowed
               
return;
            }
            break;
        case
'user':
           
$user_ID = param( 'user_ID', 'integer', '', true );
            if( !
check_user_status( 'can_view_user', $user_ID ) )
            {
// user profile display is not allowed
               
return;
            }
            break;
        case
'users':
            if( !
check_user_status( 'can_view_users' ) )
            {
// not active user can't see users list
               
return;
            }
            break;
        case
'register_finish':
           
// don't display activate account error notification on register finish form:
           
return;
        default:
            break;
    }

   
// User is allowed to see the requested view, but show an account activation error message
   
$activateinfo_link = 'href="'.get_activate_info_url( NULL, '&amp;' ).'"';
   
$Messages->add( sprintf( T_( 'IMPORTANT: your account is not active yet! Activate your account now by clicking on the activation link in the email we sent you. <a %s>More info &raquo;</a>' ), $activateinfo_link ) );
}


/**
 * Get the highest public status and action button label of a new post or comment in the given blog what the current User may create.
 * We assume here that the User should be able to create a post/comment with at least the lowest level status.
 *
 * @param string 'post' or 'comment'
 * @param integer blog ID
 * @param boolean set false to get only the status without the action button label
 * @param string Restrict max collection allowed status by this. Used for example to restrict a comment status with its post status
 * @param object Permission object: Item or Comment
 * @return mixed string status if with_label is false, array( status, label ) if with_label is true
 */
function get_highest_publish_status( $type, $blog, $with_label = true, $restrict_max_allowed_status = '', $perm_target = NULL )
{
    global
$current_User;

    if( (
$type != 'post' ) && ( $type != 'comment' ) )
    {
// $type is invalid
       
debug_die( 'Invalid type parameter!' );
    }

    if(
$restrict_max_allowed_status == 'redirected' && $type == 'comment' )
    {    
// Comment cannot have a status "redirected", force this to "deprecated":
       
$restrict_max_allowed_status = 'deprecated';
    }

   
$BlogCache = & get_BlogCache();
   
$requested_Blog = $BlogCache->get_by_ID( $blog );
   
$default_status = ( $type == 'post' ) ? $requested_Blog->get_setting( 'default_post_status' ) : $requested_Blog->get_setting( 'new_feedback_status' );

    if(
$type == 'post' && $perm_target !== NULL && $perm_target->get_type_setting( 'usage' ) == 'content-block' )
    {    
// Item type usage is Content Block:
        // Set max allowed visibility status to "Public":
       
$max_allowed_status = 'published';
    }
    elseif(
$requested_Blog->get_setting( 'allow_access' ) == 'members' )
    {    
// The collection is restricted for members or only for owner:
       
if( ! $requested_Blog->get( 'advanced_perms' ) )
        {    
// If advanced permissions are NOT enabled then only owner has an access for the collection
            // Set max allowed visibility status to "Private":
           
$max_allowed_status = 'private';
        }
        else
        {    
// Otherwise all members of this collection have an access for the collection
            // Set max allowed visibility status to "Members":
           
$max_allowed_status = 'protected';
        }
    }
    elseif(
$requested_Blog->get_setting( 'allow_access' ) == 'users' )
    {    
// The collection is restricted for logged-in users only:
        // Set max allowed visibility status to "Community":
       
$max_allowed_status = 'community';
    }
    else
    {    
// The collection has no restriction for visibility statuses
        // Set max allowed visibility status to "Public":
       
$max_allowed_status = 'published';
    }

    if( empty(
$current_User ) || ( ( !$requested_Blog->get( 'advanced_perms' ) ) && ( !$current_User->check_perm_blog_global( $blog, 'editall' ) ) ) )
    {    
// current User is not set or collection advanced perms are not enabled and user has no global perms on the given blog, set status to the default status
       
$curr_status = $default_status;
        if(
$max_allowed_status != 'published' )
        {    
// If max allowed status is not "published" then we should check what status we can return here instead of default:
           
$statuses = get_visibility_statuses();
            foreach(
$statuses as $status_key => $status_title )
            {
                if(
$curr_status == $status_key || $max_allowed_status == $status_key || $status_key == $restrict_max_allowed_status )
                {    
// Allow to use this status because only this is max allowed for the requested collection:
                    // Use min of max allowed statuses:
                   
$allowed_curr_status = $status_key;
                }
            }
           
// Force default status to max allowed:
           
$curr_status = ( empty( $allowed_curr_status ) ? '' : $allowed_curr_status );
        }
        return (
$with_label ? array( $curr_status, '' ) : $curr_status );
    }

   
$indexed_statuses = array_reverse( get_visibility_statuses( 'ordered-index' ) );
   
$result = false;
   
// Set this flag to know if we should not allow $max_allowed_status and find next status with lower level:
   
$restricted_status_is_allowed = empty( $restrict_max_allowed_status );
   
// Set this flag to false in order to find first allowed status below:
   
$status_is_allowed = false;
    foreach(
$indexed_statuses as $curr_status => $status_index )
    {
        if(
$curr_status == $restrict_max_allowed_status )
        {    
// Set this var to TRUE to make all next statuses below are allowed because it is a max allowed status:
           
$restricted_status_is_allowed = true;
        }
        if(
$curr_status == $max_allowed_status )
        {    
// This is first allowed status, then all next statuses are also allowed:
           
$status_is_allowed = true;
        }
        if(
$restricted_status_is_allowed && $status_is_allowed && check_user_perm( 'blog_'.$type.'!'.$curr_status, 'create', false, $blog ) )
        {    
// The highest available publish status has been found:
           
$result = $curr_status;
            break;
        }
    }

    if( !
$result )
    {    
// There are no available public status:
       
if( check_user_perm( 'blog_'.$type.'!private', 'create', false, $blog ) )
        {    
// Check private status:
           
$result = 'private';
        }
        else
        {    
// None of the statuses were allowed above the 'draft' status, so we return the lowest level status:
           
$result = 'draft';
        }
    }

    if(
$with_label )
    {    
// Get label for status updating action:
       
if( $result == 'private' )
        {    
// Set special label for private status because it is not defined in get_visibility_statuses( 'ordered-array' ):
           
$result_label = T_('Make private!');
        }
        else
        {    
// Get label by status key:
           
$ordered_statuses = get_visibility_statuses( 'ordered-array' );
            foreach(
$ordered_statuses as $index => $ordered_status )
            {
                if(
$ordered_status[0] == $result )
                {
                   
$result_label = $ordered_status[1];
                    break;
                }
            }
        }
        return array(
$result, empty( $result_label ) ? '' : $result_label );
    }

   
// Return only the highest available visibility status without label:
   
return $result;
}


/**
 * Retrieves all tags from published posts
 *
 * @param mixed id of the collection or array of collection ids. Set to NULL to use current blog or '*' to use all collections
 * @param integer maximum number of returned tags
 * @param string a comma separated list of tags to ignore/exclude
 * @param bool true to skip tags from pages, intro posts and sidebar stuff
 * @return array of tags
 */
function get_tags( $blog_ids, $limit = 0, $filter_list = NULL, $skip_intro_posts = false, $post_statuses = array( 'published' ), $get_cat_blog_ID = false )
{
    global
$DB, $localtimenow;

   
$BlogCache = & get_BlogCache();

    if(
is_null( $blog_ids ) )
    {
        global
$blog;
       
$blog_ids = $blog;
    }

    if(
$blog_ids == '*' )
    {
// All collections
       
$where_cat_clause = '1';
    }
    elseif(
is_array( $blog_ids ) )
    {
// Get quoted ID list
       
$where_cat_clause = 'cat_blog_ID IN ( '.$DB->quote( $blog_ids ).' )';
    }
    else
    {
// Get list of relevant/ aggregated collections
       
$Blog = & $BlogCache->get_by_ID( $blog_ids );
       
$where_cat_clause = trim( $Blog->get_sql_where_aggregate_coll_IDs( 'cat_blog_ID' ) );

        if(
$Blog->get_setting( 'aggregate_coll_IDs' ) == '*' )
        {
           
$blog_ids = '*';
        }
    }

   
// Build query to get the tags:
   
$tags_SQL = new SQL( 'Get tags' );

    if(
$blog_ids != '*' || $get_cat_blog_ID )
    {
       
$tags_SQL->SELECT( 'tag_name, COUNT( DISTINCT itag_itm_ID ) AS tag_count, tag_ID, cat_blog_ID' );
    }
    else
    {
       
$tags_SQL->SELECT( 'tag_name, COUNT( DISTINCT itag_itm_ID ) AS tag_count, tag_ID' );
    }

   
$tags_SQL->FROM( 'T_items__tag' );
   
$tags_SQL->FROM_add( 'INNER JOIN T_items__itemtag ON itag_tag_ID = tag_ID' );
   
$tags_SQL->FROM_add( 'INNER JOIN T_items__item ON itag_itm_ID = post_ID' );

    if(
$blog_ids != '*' || $get_cat_blog_ID )
    {
       
$tags_SQL->FROM_add( 'INNER JOIN T_postcats ON itag_itm_ID = postcat_post_ID' );
       
$tags_SQL->FROM_add( 'INNER JOIN T_categories ON postcat_cat_ID = cat_ID' );
    }

    if(
$skip_intro_posts )
    {
       
$tags_SQL->FROM_add( 'LEFT JOIN T_items__type ON post_ityp_ID = ityp_ID' );
    }

   
$tags_SQL->WHERE( $where_cat_clause );
   
$tags_SQL->WHERE_and( 'post_status IN ("'.implode( '", "', $post_statuses ).'")' );
   
$tags_SQL->WHERE_and( 'post_datestart < '.$DB->quote( remove_seconds( $localtimenow ) ) );

    if(
$skip_intro_posts )
    {    
// Skip "Intro", "Page" and other special posts:
       
$tags_SQL->WHERE_and( 'post_ityp_ID IS NULL OR ityp_usage = "post"' );
    }

    if( ! empty(
$filter_list ) )
    {
// Filter tags
       
$tags_SQL->WHERE_and( 'tag_name NOT IN ( '.$DB->quote( explode( ', ', $filter_list ) ).' )' );
    }

   
$tags_SQL->GROUP_BY( 'tag_name' );

   
$tags_SQL->ORDER_BY( 'tag_count DESC' );

    if( ! empty(
$limit ) )
    {
// Limit
       
$tags_SQL->LIMIT( $limit );
    }

    return
$DB->get_results( $tags_SQL );
}


/**
 * Get a list of those statuses which can be displayed in the front office
 *
 * @param integer blog ID
 * @param string get setting for 'post' or 'comment'
 * @return array front office statuses in the given blog
 */
function get_inskin_statuses( $blog_ID, $type )
{
    if( empty(
$blog_ID ) )
    {
// When blog is not set return the default value
       
return array( 'published', 'community', 'protected', 'private', 'review' );
    }

   
$BlogCache = & get_BlogCache();
   
$Collection = $Blog = $BlogCache->get_by_ID( $blog_ID );
   
$inskin_statuses = trim( $Blog->get_setting( ( $type == 'comment' ) ? 'comment_inskin_statuses' : 'post_inskin_statuses' ) );

    return empty(
$inskin_statuses ) ? array() : explode( ',', $inskin_statuses );
}


/**
 * Get post/comment inskin statuses option list
 *
 * @param string type = 'post' or 'comment'
 * @return array checklist options
 */
function get_inskin_statuses_options( & $edited_Blog, $type )
{
   
$checklist_options = array();
    if(
$type != 'post' && $type != 'comment' )
    {
        return
$checklist_options;
    }

   
// Get all available statuses except 'deprecated', 'trash' and 'redirected'
   
$statuses = get_visibility_statuses( '', array( 'deprecated', 'trash', 'redirected' ) );
   
$status_icons = get_visibility_statuses( 'icons', array( 'deprecated', 'trash', 'redirected' ) );

   
// Get current selected visibility statuses:
   
$inskin_statuses = $edited_Blog->get_setting( $type.'_inskin_statuses' );

   
// Get max allowed visibility status:
   
$max_allowed_status = get_highest_publish_status( $type, $edited_Blog->ID, false );

   
$status_is_hidden = true;
    foreach(
$statuses as $status => $status_text )
    {    
// Add a checklist option for each possible front office post/comment status:
       
if( $max_allowed_status == $status )
        {    
// This is max allowed status, Then display all next statuses with
           
$status_is_hidden = false;
        }

       
$checklist_options[] = array(
               
$type.'_inskin_'.$status, // Field name of checkbox
               
1, // Field value
               
$status_icons[ $status ].' '.$status_text, // Text
               
( strpos( $inskin_statuses, $status ) !== false ), // Checked?
               
'', // Disabled?
               
'', // Note
               
'', // Class
               
$status_is_hidden, // Hidden field instead of checkbox?
               
array(
                   
'data-toggle' => 'tooltip',
                   
'data-placement' => 'top',
                   
'title' => get_status_tooltip_title( $status ) )
            );
    }

    return
$checklist_options;
}


/**
 * Callback for array_map in get_visibility_status()
 */
function _get_visibility_statuses_callback( $val )
{
    return
implode( " ", $val );
}


/**
 * Get available post statuses
 *
 * @param string Statuses format, defaults to translated statuses
 * @param array Statuses to exclude. Unused 'trash' status excluded by default
 * @param array Check if current user has a permission for each status
 * @param integer Blog ID
 * @return array of statuses
 */
function get_visibility_statuses( $format = '', $exclude = array('trash'), $check_perms = false, $blog_ID = NULL )
{
    switch(
$format )
    {
        case
'notes-array':
        case
'notes-string':
        case
'radio-options':
           
// Array notes for visibility_select()
           
$r = array(
                   
'published'  => array( T_('Public'),     '('.T_('Everyone').')' ),
                   
'community'  => array( T_('Community'),  '('.T_('Logged in users only').')' ),
                   
'protected'  => array( T_('Members'),    '('.T_('Blog members only').')' ),
                   
'review'     => array( T_('Review'),     '('.T_('Moderators only (+You)').')' ),
                   
'private'    => array( T_('Private'),    '('.T_('You only').')' ),
                   
'draft'      => array( T_('Draft'),      '('.T_('You only (+backoffice users)').')' ),
                   
'deprecated' => array( T_('Deprecated'), '('.T_('Not published!').')' ),
                   
'redirected' => array( T_('Redirected'), '(301)' ),
                   
'trash'      => array( T_('Recycled'),   '' )
                );

            if(
$format == 'notes-string' )
            {    
// String notes
               
$r = array_map( '_get_visibility_statuses_callback', $r );
            }
            break;

        case
'moderation-titles':
           
$change_status = T_('Change status to').': ';
           
$visible_by = ' ('.T_('Visible by').': ';
           
$r = array(
                   
'published'  => $change_status.T_('Public').$visible_by.T_('Everyone').')',
                   
'community'  => $change_status.T_('Community').$visible_by.T_('Logged in users only').')',
                   
'protected'  => $change_status.T_('Members').$visible_by.T_('Blog members only').')',
                   
'review'     => $change_status.T_('Review').$visible_by.T_('Moderators only (+You)').')',
                   
'private'    => $change_status.T_('Private').$visible_by.T_('You only').')',
                   
'draft'      => $change_status.T_('Draft').$visible_by.T_('You only (+backoffice users)').')',
                   
'deprecated' => $change_status.T_('Deprecated').' ('.T_('Not published!').')',
                   
'redirected' => '',
                   
'trash'      => ''
               
);
            break;

        case
'legend-titles':
           
$r = array(
                   
'published' => T_('Visible by anyone'),
                   
'community' => T_('Visible by logged-in users only'),
                   
'protected' => T_('Visible by members only'),
                   
'review'    => T_('Waiting for moderator review'),
                   
'private'   => T_('Visible by you only'),
                   
'draft'     => T_('Unfinished post'),
                );
            break;

        case
'button-titles':
           
$r = array(
                   
'published'  => NT_('Save as Public!'),
                   
'community'  => NT_('Save for Community!'),
                   
'protected'  => NT_('Save for Members!'),
                   
'review'     => NT_('Save for Review!'),
                   
'private'    => NT_('Save as Private!'),
                   
'draft'      => NT_('Save as Draft!'),
                   
'deprecated' => NT_('Save as Deprecated!'),
                   
'redirected' => NT_('Save as Redirected!'),
                );
            break;

        case
'tooltip-titles':
           
$r = array(
                   
'published'  => T_('This is visible by everyone.'),
                   
'community'  => T_('This is visible by logged-in users only.'),
                   
'protected'  => T_('This is visible by members only.'),
                   
'review'     => T_('This is waiting for review and is visible by moderators only.'),
                   
'private'    => T_('This is visible only by the owner/author of the post and collection administrators.'),
                   
'draft'      => is_admin_page() ? T_('This is a draft.') : T_('This is a draft and is visible only by the owner/author of the post and collection administrators.'),
                   
'deprecated' => T_('This is deprecated and visible in the Back-Office only.'),
                   
'redirected' => T_('This will redirect to another page when accessed from the Front-Office.'),
                   
'trash'      => T_('This is a recycled.'),
                );
            break;

        case
'ordered-array': // indexed array, ordered from the lowest to the highest public level
           
$r = array(
               
0 => array( 'deprecated', '', T_('Deprecate').'!', 'grey' ),
               
1 => array( 'review', T_('Open to moderators!'), T_('Restrict to moderators!'), 'magenta' ),
               
2 => array( 'protected', T_('Open to members!'), T_('Restrict to members!'), 'orange' ),
               
3 => array( 'community', T_('Open to community!'), T_('Restrict to community!'), 'blue' ),
               
4 => array( 'published', T_('Make public!'), '', 'green' )
            );
            return
$r;

        case
'ordered-index': // gives each status index in the statuses ordered array
           
$r = array(
               
'trash'      => 0,
               
'redirected' => 0,
               
'deprecated' => 0,
               
'draft'      => 0,
               
'private'    => 0,
               
'review'     => 1,
               
'protected'  => 2,
               
'community'  => 3,
               
'published'  => 4,
            );
            break;

        case
'moderation': // these statuses may need moderation
           
$r = array( 'community', 'protected', 'review', 'private', 'draft' );
            return
$r;

        case
'icons': // colored icons
           
$r = array (
                   
'published'  => '<span class="fa fa-circle status_color_published"></span>',
                   
'community'  => '<span class="fa fa-circle status_color_community"></span>',
                   
'protected'  => '<span class="fa fa-circle status_color_protected"></span>',
                   
'review'     => '<span class="fa fa-circle status_color_review"></span>',
                   
'private'    => '<span class="fa fa-circle status_color_private"></span>',
                   
'draft'      => '<span class="fa fa-circle status_color_draft"></span>',
                   
'deprecated' => '<span class="fa fa-circle status_color_deprecated"></span>',
                   
'redirected' => '<span class="fa fa-circle status_color_redirected"></span>',
                );
            break;

        case
'raw':
        default:
           
$r = array (
                   
'published'  => NT_('Public'),
                   
'community'  => NT_('Community'),
                   
'protected'  => NT_('Members'),
                   
'review'     => NT_('Review'),
                   
'private'    => NT_('Private'),
                   
'draft'      => NT_('Draft'),
                   
'deprecated' => NT_('Deprecated'),
                   
'redirected' => NT_('Redirected'),
                   
'trash'      => NT_('Recycled'),
                );

            if(
$format != 'keys' && $format != 'raw' )
            {    
// Translate statuses (default format)
               
$r = array_map( 'T_', $r );
            }
    }

    if( !empty(
$exclude) )
    {
       
// PHP 5.1 array_diff_key( $r, $exclude );
       
foreach( $exclude as $ex )
        {
            if( isset(
$r[$ex]) )
            {
                unset(
$r[$ex]);
            }
        }
    }

    if(
$check_perms && ! is_null( $blog_ID ) )
    {
// Check what status is available for current user
       
foreach( $r as $status_key => $status_title )
        {
            if( !
check_user_perm( 'blog_post!'.$status_key, 'create', false, $blog_ID ) )
            {
// Unset this status from list because current user has no perms to use this status
               
unset( $r[ $status_key ] );
            }
        }
    }

    if(
$format == 'keys' )
    {
// Return status keys for 'visibility_array'
       
$r = array_keys( $r );
    }

    if(
$format == 'radio-options' )
    {
// Return options for radio buttons
       
$radio_options = array();
        foreach(
$r as $status => $labels )
        {
           
$radio_options[] = array( $status, $labels[0].' <span class="notes">'.$labels[1].'</span>' );
        }
        return
$radio_options;
    }

    return
$r;
}


/**
 * Compare two visibility status in the point of public level
 *
 * @param string first_status
 * @param string second_status
 * @return integer
 *   0 if the two statuses have the same public level
 *   1 if the first status has higher public level
 *   -1 if it first status has lower public level
 */
function compare_visibility_status( $first_status, $second_status )
{
   
$status_index = get_visibility_statuses( 'ordered-index', array() );
    if( !isset(
$status_index[$first_status] ) || !isset( $status_index[$second_status] ) )
    {
// At least one of the given statuses doesn't exist
       
debug_die( 'Invalid status given to compare!' );
    }

   
$first_status_index = $status_index[$first_status];
   
$second_status_index = $status_index[$second_status];
    if(
$first_status_index == $second_status_index )
    {
// The two status public level is equal, but note this doesn't mean that the two status must be same!
       
return 0;
    }

    return (
$first_status_index > $second_status_index ) ? 1 : -1;
}


/**
 * Get restricted visibility statuses for the current User in the given blog
 *
 * @param integer blog ID
 * @param string permission prefix: 'blog_post!' or 'blog_comment!'
 * @param string permlevel: 'view'/'edit' depending on where we would like to use it
 * @param string|array Statuses; Don't restrict these statuses by max allowed status, for example, if it is already used for the post/comment
 * @param string Restrict max collection allowed status by this. Used for example to restrict a comment status with its post status
 * @param object Permission object: Item or Comment
 * @return array of restricted statuses
 */
function get_restricted_statuses( $blog_ID, $prefix, $permlevel = 'view', $allow_statuses = '', $restrict_max_allowed_status = '', $perm_target = NULL )
{
   
$result = array();

   
// Get max allowed visibility status:
   
$max_allowed_status = get_highest_publish_status( ( $prefix == 'blog_post!' ? 'post' : 'comment' ), $blog_ID, false, $restrict_max_allowed_status );

    if( !
is_array( $allow_statuses ) )
    {    
// Convert string to array:
       
$allow_statuses = array( $allow_statuses );
    }

    if(
$prefix == 'blog_post!' && $perm_target !== NULL && $perm_target->get_type_setting( 'usage' ) == 'content-block' )
    {    
// Always allow "Public" status for Content Block:
       
$allow_statuses[] = 'published';
    }

   
// This statuses are allowed to view/edit only for those users who may create post/comment with these statuses
   
$restricted = array( 'published', 'community', 'protected', 'review', 'private', 'draft', 'deprecated' );
   
$status_is_allowed = false;
    foreach(
$restricted as $status )
    {
        if(
$status == $max_allowed_status )
        {    
// Set this var to TRUE to make all next statuses below are allowed because it is a max allowed status:
           
$status_is_allowed = true;
        }
        if(
in_array( $status, array( 'published', 'community', 'protected' ) ) )
        {    
// Keep these statuses in array only to set $status_is_allowed in order to know when we can start allow the statuses:
           
continue;
        }
        if( ( !
in_array( $status, $allow_statuses ) && ! $status_is_allowed ) || ! check_user_perm( $prefix.$status, 'create', false, $blog_ID ) )
        {    
// This status is not allowed
           
$result[] = $status;
        }
    }

   
// 'redirected' status is allowed to view/edit only in case of posts, and only if user has permission
   
if( $prefix == 'blog_comment!' ||
        (
$prefix == 'blog_post!' && ! check_user_perm( $prefix.'redirected', 'create', false, $blog_ID ) ) )
    {
// not allowed
       
$result[] = 'redirected';
    }

   
// 'trash' status is allowed only in case of comments, and only if user has a permission to delete a comment from the given collection
   
if( $prefix == 'blog_comment!' && ! ( ! empty( $perm_target ) && check_user_perm( 'comment!CURSTATUS', 'delete', false, $perm_target ) ) )
    {
// not allowed
       
$result[] = 'trash';
    }

   
// The other statuses are always allowed to view in backoffice
   
if( $permlevel != 'view' )
    {
// in case of other then 'view' action we must check the permissions
       
$restricted = array( 'published', 'community', 'protected' );
       
$status_is_allowed = false;
        foreach(
$restricted as $status )
        {
            if(
$status == $max_allowed_status )
            {    
// Set this var to TRUE to make all next statuses below are allowed because it is a max allowed status:
               
$status_is_allowed = true;
            }
            if( ( !
in_array( $status, $allow_statuses ) && ! $status_is_allowed ) ||
                !
check_user_perm( $prefix.$status, 'create', false, $blog_ID ) )
            {    
// This status is not allowed
               
$result[] = $status;
            }
        }
    }

    return
$result;
}


function
get_status_tooltip_title( $status )
{
   
$visibility_statuses = get_visibility_statuses( 'tooltip-titles', array() );

    if( isset(
$visibility_statuses[$status] ) )
    {
        return
$visibility_statuses[$status];
    }
    else
    {
       
debug_die( 'Invalid status value' );
    }
}

/**
 * Check if item/comment can be displayed with status for current user on front-office
 *
 * @param string Status
 * @param string Type: 'item', 'comment'
 * @param integer Blog ID
 * @param integer Creator user ID
 * @return boolean
 */
function can_be_displayed_with_status( $status, $type, $blog_ID, $creator_user_ID )
{
   
// Get statuses which are visible on front-office:
   
$show_statuses = get_inskin_statuses( $blog_ID, $type );

    if( !
in_array( $status, $show_statuses ) )
    {    
// This Item has a status which cannot be displayed on front-office:
       
return false;
    }

    global
$current_User;

   
$permname = ( $type == 'item' ? 'blog_post!' : 'blog_comment!' ).$status;

    switch(
$status )
    {
        case
'published':
           
// Published items/comments are always allowed:
           
$allowed = true;
            break;

        case
'community':
           
// It is always allowed for logged in users:
           
$allowed = is_logged_in( false );
            break;

        case
'protected':
           
// It is always allowed for members:
           
$allowed = check_user_perm( 'blog_ismember', 1, false, $blog_ID, false );
            break;

        case
'private':
           
// It is allowed for users who has global 'editall' permission:
           
$allowed = check_user_perm( 'blogs', 'editall', false, NULL, false );
            if( !
$allowed && check_user_perm( $permname, 'create', false, $blog_ID, false ) )
            {    
// Own private items/comments are allowed if user can create private items/comments:
               
$allowed = ( $current_User->ID == $creator_user_ID );
            }
            break;

        case
'review':
           
// It is allowed for users who have at least 'lt' items/comments edit permission :
           
$allowed = check_user_perm( $permname, 'moderate', false, $blog_ID, false );
            if( !
$allowed && check_user_perm( $permname, 'create', false, $blog_ID, false ) )
            {    
// Own items/comments with 'review' status are allowed if user can create items/comments with 'review' status
               
$allowed = ( $current_User->ID == $creator_user_ID );
            }
            break;

        case
'draft':
           
// In front-office only authors may see their own draft items/comments, but only if the have permission to create draft items/comments:
           
$allowed = ( check_user_perm( $permname, 'create', false, $blog_ID, false )
                &&
$current_User->ID == $creator_user_ID );
            break;

        default:
           
// Decide the unknown item/comment statuses as not visible for front-office:
           
$allowed = false;
    }

    return
$allowed;
}


/**
 * Get Blog object from general setting
 *
 * @param string Setting name: 'default_blog_ID', 'info_blog_ID', 'login_blog_ID', 'msg_blog_ID'
 * @param object|NULL Current collection, Used for additional checking
 * @param boolean true if function $BlogCache->get_by_ID() should die on error
 * @param boolean true if function $BlogCache->get_by_ID() should die on empty/null
 * @param boolean true to get first detected collection from DB when requested collection is not defined
 * @return object|NULL|false
 */
function & get_setting_Blog( $setting_name, $current_Blog = NULL, $halt_on_error = false, $halt_on_empty = false, $get_first = false )
{
    global
$Settings;

   
$setting_Blog = false;

    if( ! isset(
$Settings ) )
    {
        return
$setting_Blog;
    }

   
$blog_ID = intval( $Settings->get( $setting_name ) );
    if(
$blog_ID > 0 )
    {
// Check if blog really exists in DB
       
$BlogCache = & get_BlogCache();
       
$setting_Blog = & $BlogCache->get_by_ID( $blog_ID, $halt_on_error, $halt_on_empty );
    }

    if(
$get_first && empty( $setting_Blog ) )
    {    
// Try to get first collection from DB:
       
$BlogCache = & get_BlogCache();
       
$setting_Blog = & $BlogCache->get_first();
    }

    if(
$setting_name == 'login_blog_ID' &&
       
$current_Blog !== NULL &&
       
$current_Blog->get( 'access_type' ) == 'absolute' &&
        ! empty(
$setting_Blog ) &&
        !
url_check_same_domain( $current_Blog->gen_baseurl(), $setting_Blog->gen_baseurl() ) )
    {    
// Don't allow to use main login collection if current collection has a DIFFERENT external domain:
       
$setting_Blog = NULL;
    }

    return
$setting_Blog;
}


/**
 * Display collection favorite icon
 *
 * @param integer Blog ID
 */
function get_coll_fav_icon( $blog_ID, $params = array() )
{
    global
$admin_url;

   
$params = array_merge( array(
           
'title' => '',
           
'class' => '',
        ),
$params );

   
$BlogCache = & get_BlogCache();
   
$edited_Blog = $BlogCache->get_by_ID( $blog_ID );
   
$is_favorite = $edited_Blog->favorite() > 0;
    if(
$is_favorite )
    {
       
$icon = 'star_on';
       
$action = 'disable_setting';
       
$title = T_('The collection is a favorite');
    }
    else
    {
       
$icon = 'star_off';
       
$action = 'enable_setting';
       
$title = T_('The collection is not a favorite');
    }

    return
'<a class="evo_post_fav_btn" href="'.$admin_url.'?ctrl=coll_settings'
           
.'&amp;tab=general'
           
.'&amp;action='.$action
           
.'&amp;setting=fav'
           
.'&amp;blog='.$blog_ID
           
.'&amp;'.url_crumb('collection').'" '
           
.'data-coll="'.$edited_Blog->urlname.'" '
           
.'data-favorite="'.( $edited_Blog->favorite() ? '0' : '1' ).'">'
           
.get_icon( $icon, 'imgtag', $params )
            .
'</a>';
}


/**
 * Get blog order field
 *
 * @param object Blog
 * @param string What return: 'field', 'dir'
 * @param string Separator
 * @return string
 */
function get_blog_order( $Blog = NULL, $return = 'field', $separator = ',' )
{
   
$result = '';

    switch(
$return )
    {
        case
'field':
           
// Get field for ORDERBY sql clause
           
if( empty( $Blog ) )
            {
// Get default value if blog is not defined
               
$result = 'datestart';
            }
            else
            {
               
$result = $Blog->get_setting( 'orderby' );
                if(
$Blog->get_setting( 'orderby_1' ) != '' )
                {
// Append second order field
                   
$result .= $separator.$Blog->get_setting( 'orderby_1' );
                    if(
$Blog->get_setting( 'orderby_2' ) != '' )
                    {
// Append third order field
                       
$result .= $separator.$Blog->get_setting( 'orderby_2' );
                    }
                }
            }
            break;

        case
'dir':
           
// Get direction(ASC|DESC) for ORDERBY sql clause
           
if( empty( $Blog ) )
            {
// Get default value if blog is not defined
               
$result = 'DESC';
            }
            else
            {
               
$result = $Blog->get_setting( 'orderdir' );
                if(
$Blog->get_setting( 'orderby_1' ) != '' && $Blog->get_setting( 'orderdir_1' ) != '' )
                {
// Append second order direction
                   
$result .= $separator.$Blog->get_setting( 'orderdir_1' );
                    if(
$Blog->get_setting( 'orderby_2' ) != '' && $Blog->get_setting( 'orderdir_2' ) != '' )
                    {
// Append third order direction
                       
$result .= $separator.$Blog->get_setting( 'orderdir_2' );
                    }
                }
            }
            break;
    }

    return
$result;
}


/**
 * Get posts order by options for the order by select list
 *
 * @param integer|NULL Collection ID to get only enabled item types for the collection, NULL to get all item types
 * @param string the value which should be selected by default
 * @param boolean set tru to allow 'none' option, false otherwise
 * @return string HTML code of <option>s for <select>
 */
function get_post_orderby_options( $coll_ID = NULL, $selected_value, $allow_none = false )
{
   
// Get available sort options:
   
$available_sort_options = get_available_sort_options( $coll_ID, $allow_none, true );
   
// Get general order list options from sub array:
   
$general_orderby_list = $available_sort_options['general'];

   
// Build $option_list
   
$option_list = Form::get_select_options_string( $general_orderby_list, $selected_value, false, false );
    if( ! empty(
$available_sort_options['custom'] ) )
    {
// There are custom fields order by options
       
$option_list .= '<optgroup label="'.T_('Custom fields').'">';
       
$option_list .= Form::get_select_options_string( $available_sort_options['custom'], $selected_value, false, false );
       
$option_list .= '</optgroup>';
    }

    return
$option_list;
}


/**
 * Get JavaScript to enable/disable fields to order post fields
 * (used on ?ctrl=coll_settings&tab=features and for "Universal Item list" widget settings form)
 *
 * @param string "Order by" field name
 * @param string "Order direction" field name
 * @return string JavaScript
 */
function get_post_orderby_js( $field_order_by, $field_order_dir )
{
    return
'jQuery( document ).ready( function() { disable_selected_orderby_options(); } );
jQuery( "select[id^='
.$field_order_by.']" ).change( function() { disable_selected_orderby_options(); } );
function disable_selected_orderby_options()
{
    // Disable/Enable second additional order field if the first was changed:
    jQuery( "#'
.$field_order_by.'_2, #'.$field_order_dir.'_2" ).prop( "disabled", jQuery( "#'.$field_order_by.'_1" ).val() == "" );

    // Redisable options after some order field was changed:
    jQuery( "select[id^='
.$field_order_by.'] option" ).prop( "disabled", false );
    jQuery( "select[id^='
.$field_order_by.']" ).each( function()
    {
        var selected = jQuery( this ).val();
        if( selected != "" )
        {
            jQuery( "select[id^='
.$field_order_by.'][id!=" + jQuery( this ).attr( "id" ) + "]" ).each( function()
            {
                jQuery( this ).find( "option[value=" + selected + "]" ).prop( "disabled", true );
            } );
        }
    } );
}'
;
}


/**
 * Display blogs results table
 *
 * @param array Params
 */
function blogs_user_results_block( $params = array() )
{
   
// Make sure we are not missing any param:
   
$params = array_merge( array(
           
'edited_User'          => NULL,
           
'results_param_prefix' => 'actv_blog_',
           
'results_title'        => T_('Collections owned by the User'),
           
'results_no_text'      => T_('User does not own any blogs'),
           
'action'               => '',
        ),
$params );

    if( !
check_user_perm( 'users', 'moderate' ) || ! check_user_perm( 'blogs', 'view' ) )
    {    
// Check minimum permission:
       
return;
    }

   
$edited_User = $params['edited_User'];
    if( !
$edited_User )
    {    
// No defined User, probably the function is calling from AJAX request
       
$user_ID = param( 'user_ID', 'integer', 0 );
        if( empty(
$user_ID ) )
        {    
// Bad request, Exit here
           
return;
        }
       
$UserCache = & get_UserCache();
        if( (
$edited_User = & $UserCache->get_by_ID( $user_ID, false ) ) === false )
        {    
// Bad request, Exit here
           
return;
        }
    }

    global
$DB, $AdminUI;

   
param( 'user_tab', 'string', '', true );
   
param( 'user_ID', 'integer', 0, true );

   
$SQL = new SQL();
   
$SQL->SELECT( '*, cset_value AS collection_logo_file_ID' );
   
$SQL->FROM( 'T_blogs' );
   
$SQL->FROM_add( 'LEFT JOIN T_coll_settings ON blog_ID = cset_coll_ID AND cset_name = "collection_logo_file_ID"' );
   
$SQL->WHERE( 'blog_owner_user_ID = '.$DB->quote( $edited_User->ID ) );

   
// Create result set:
   
$blogs_Results = new Results( $SQL->get(), $params['results_param_prefix'] );
   
$blogs_Results->Cache = & get_BlogCache();
   
$blogs_Results->title = $params['results_title'];
   
$blogs_Results->no_results_text = $params['results_no_text'];

   
// Get a count of the blogs which current user can delete
   
$deleted_blogs_count = count( $edited_User->get_deleted_blogs() );
    if(
$params['action'] != 'view' && $blogs_Results->get_total_rows() > 0 && $deleted_blogs_count > 0 )
    {    
// Display action icon to delete all records if at least one record exists & user can delete at least one blog
       
$blogs_Results->global_icon( sprintf( T_('Delete all blogs owned by %s'), $edited_User->login ), 'delete', '?ctrl=user&amp;user_tab=activity&amp;action=delete_all_blogs&amp;user_ID='.$edited_User->ID.'&amp;'.url_crumb('user'), ' '.T_('Delete all'), 3, 4 );
    }

   
// Initialize Results object
   
blogs_results( $blogs_Results, array(
           
'display_type'    => false,
           
'display_owner'   => false,
           
'display_plist'   => false,
           
'display_order'   => false,
           
'display_caching' => false,
           
'display_fav'     => false,
        ) );

    if(
is_ajax_content() )
    {    
// init results param by template name
       
if( !isset( $params[ 'skin_type' ] ) || ! isset( $params[ 'skin_name' ] ) )
        {
           
debug_die( 'Invalid ajax results request!' );
        }
       
$blogs_Results->init_params_by_skin( $params[ 'skin_type' ], $params[ 'skin_name' ] );
    }

   
$results_params = $AdminUI->get_template( 'Results' );
   
$display_params = array(
       
'before' => str_replace( '>', ' style="margin-top:25px" id="owned_blogs_result">', $results_params['before'] ),
    );
   
$blogs_Results->display( $display_params );

    if( !
is_ajax_content() )
    {    
// Create this hidden div to get a function name for AJAX request
       
echo '<div id="'.$params['results_param_prefix'].'ajax_callback" style="display:none">'.__FUNCTION__.'</div>';
    }
}


/**
 * Callback to add filters on top of the result set
 *
 * @param Form
 */
function callback_filter_collectionlist( & $Form )
{
    global
$cf_name, $cf_owner, $cf_type;

   
$UserCache = & get_UserCache();
   
$owner_User = & $UserCache->get_by_login( $cf_owner );

   
$Form->text_input( 'cf_name', $cf_name, 40, T_('Name') );
   
$Form->username( 'cf_owner', $owner_User, T_('Owner') );

   
$kinds = get_collection_kinds();
   
$collection_types = array();
    foreach(
$kinds as $kind => $value )
    {
       
$collection_types[$kind] = $value['name'];
    }
   
$collection_types = array_merge( array(    '' => T_('All') ), $collection_types );
   
$Form->select_input_array( 'cf_type', $cf_type, $collection_types, T_('Type') );
}


/**
 * Display all blogs results table
 *
 * @param array Params
 */
function blogs_all_results_block( $params = array() )
{
    global
$admin_url, $DB, $Session;
    global
$cf_name, $cf_owner, $cf_type;

   
// Make sure we are not missing any param:
   
$params = array_merge( array(
           
'results_param_prefix' => 'blog_',
           
'results_title'        => check_user_perm( 'blog_admin', 'view', false ) ? T_('List of Collections configured on this system').get_manual_link('site-collection-list') : T_('Your Collections'),
           
'results_no_text'      => T_('Create your first collection now').': '
                   
.'<a href="'.$admin_url.'?ctrl=collections&amp;action=new" class="btn btn-primary btn-sm" title="'.T_('New Collection').'..."><span class="fa fa-plus-square"></span> '.T_('New Collection').'...</a>',
           
'results_no_perm_text' => ( check_user_perm( 'blogs', 'create' )
                ?
T_('Create your first collection now').': '.action_icon( T_('New Collection').'...', 'new', $admin_url.'?ctrl=collections&amp;action=new', T_('New Collection').'...', 3, 4, array( 'class' => 'action_icon btn btn-primary', 'style' => 'margin:-10px 0 -7px 0' ) )
                :
T_('Sorry, you have no permission to edit/view any collection\'s properties.') ),
           
'grouped'              => true,
        ),
$params );

    if( !
is_logged_in() )
    {
// Only logged in users can access to this function
       
return;
    }

    global
$current_User;

   
$cf_name = param( 'cf_name', 'string', NULL, true );
   
$cf_owner = param( 'cf_owner', 'string', NULL, true );
   
$cf_type = param( 'cf_type', 'string', NULL, true );

   
$collection_filters = $Session->get( 'collection_filters' );

    if( empty(
$collection_filters ) )
    {
       
$collection_filters = array();
    }
    if(
$cf_name === NULL )
    {
// Get a param value from Session
       
$cf_name = empty( $collection_filters['name'] ) ? '' : $collection_filters['name'];
    }
    else
    {
// Save new value to Session
       
$collection_filters['name'] = $cf_name;
    }
    if(
$cf_owner === NULL )
    {
// Get a param value from Session
       
$cf_owner = empty( $collection_filters['owner'] ) ? '' : $collection_filters['owner'];
    }
    else
    {
// Save new value to Session
       
$collection_filters['owner'] = $cf_owner;
    }
    if(
$cf_type === NULL )
    {
// Get a param value from Session
       
$cf_type = empty( $collection_filters['type'] ) ? '' : $collection_filters['type'];
    }
    else
    {
// Save new value to Session
       
$collection_filters['type'] = $cf_type;
    }

    foreach(
$collection_filters as $cf => $collection_filter )
    {
        if( empty(
$collection_filter ) )
        {    
// Remove empty filter:
           
unset( $collection_filters[ $cf ] );
        }
    }

   
// Save new filters
   
$Session->set( 'collection_filters', $collection_filters );
   
$Session->dbsave();

    if(
is_ajax_content() )
    {
       
$order_action = param( 'order_action', 'string' );
       
$new_value = intval( param( 'new_value', 'string', 0 ) );
       
$order_data = param( 'order_data', 'string' );

        if(
$order_action == 'update' )
        {    
// Update collection order to new value:
           
$order_obj_ID = intval( str_replace( 'order-blog-', '', $order_data ) );
            if(
$order_obj_ID > 0 )
            {    
// Update collection order if ID is valid integer:
               
$BlogCache = & get_BlogCache();
                if(
$updated_Blog = & $BlogCache->get_by_ID( $order_obj_ID, false ) )
                {
                    if(
check_user_perm( 'blog_properties', 'edit', false, $updated_Blog->ID ) )
                    {    
// If current user can edit the collection:
                       
$updated_Blog->set( 'order', $new_value );
                       
$updated_Blog->dbupdate();
                       
$BlogCache->clear();
                    }
                }
            }
        }
        elseif(
$order_action == 'update_section' )
        {    
// Update section order to new value:
           
$order_obj_ID = intval( str_replace( 'order-section-', '', $order_data ) );
            if(
$order_obj_ID > 0 )
            {    
// Update collection order if ID is valid integer:
               
$SectionCache = & get_SectionCache();
                if(
$updated_Section = & $SectionCache->get_by_ID( $order_obj_ID, false ) )
                {
                    if(
check_user_perm( 'section', 'edit', false, $order_obj_ID ) )
                    {    
// If current user can edit the requested section:
                       
$updated_Section->set( 'order', $new_value );
                       
$updated_Section->dbupdate();
                    }
                }
            }
        }
    }

   
$SQL = new SQL();
   
$SQL->SELECT( 'DISTINCT blog_ID, T_blogs.*, user_login, IF( cufv_user_id IS NULL, 0, 1 ) AS blog_favorite, cset_value AS collection_logo_file_ID' );
    if(
$params['grouped'] )
    {    
// Get collections with groups:
       
$SQL->SELECT_add( ', sec_ID, sec_name, sec_order, sec_owner_user_ID' );
       
$SQL->FROM( 'T_section' );
       
$SQL->FROM_add( 'LEFT JOIN T_blogs ON sec_ID = blog_sec_ID' );
       
$SQL->FROM_add( 'LEFT JOIN T_users ON blog_owner_user_ID = user_ID' );
       
$SQL->GROUP_BY( 'blog_ID, sec_ID' );
       
$SQL->ORDER_BY( 'sec_order, sec_name' );
    }
    else
    {    
// Get collections without groups:
       
$SQL->FROM( 'T_blogs' );
       
$SQL->FROM_add( 'INNER JOIN T_users ON blog_owner_user_ID = user_ID' );
    }
   
$SQL->FROM_add( 'LEFT JOIN T_coll_user_favs ON ( cufv_blog_ID = blog_ID AND cufv_user_ID = '.$current_User->ID.' )' );
   
$SQL->FROM_add( 'LEFT JOIN T_coll_settings ON blog_ID = cset_coll_ID AND cset_name = "collection_logo_file_ID"' );

    if( !
check_user_perm( 'blogs', 'view' ) )
    {
// We do not have perm to view all blogs... we need to restrict to those we're a member of:
       
$SQL->FROM_add( 'LEFT JOIN T_coll_user_perms ON ( blog_advanced_perms <> 0 AND blog_ID = bloguser_blog_ID'
           
. ' AND bloguser_user_ID = ' . $current_User->ID . ' )' );
       
$SQL->FROM_add( ' LEFT JOIN T_coll_group_perms ON ( blog_advanced_perms <> 0 AND blog_ID = bloggroup_blog_ID'
           
. ' AND ( bloggroup_group_ID = ' . $current_User->grp_ID
           
. '       OR bloggroup_group_ID IN ( SELECT sug_grp_ID FROM T_users__secondary_user_groups WHERE sug_user_ID = '.$current_User->ID.' ) ) )' );
       
$section_where_sql = '';
       
$collection_where_sql = 'blog_owner_user_ID = '.$current_User->ID
           
.' OR bloguser_ismember <> 0'
           
.' OR bloggroup_ismember <> 0';
        if(
$params['grouped'] )
        {    
// Get default section of the current user group:
           
global $DB;
           
// Get all collections from sections where current user is owner:
           
$section_where_sql .= 'sec_owner_user_ID = '.$current_User->ID.' OR ';
           
// Get collections(if current user is owner or member of these collections) from sections where current user can create new collection:
           
$user_Group = & $current_User->get_Group();
           
$perm_allowed_sections = trim( $user_Group->get_setting( 'perm_allowed_sections' ) );
            if( ! empty(
$perm_allowed_sections ) )
            {    
// If at least one section is specified to be allowed for new collections:
               
$section_where_sql .= '( sec_ID IN ( '.$DB->quote( explode( ',', $perm_allowed_sections ) ).' ) '
                   
.'AND ( '.$collection_where_sql.' ) ) OR ';
            }
        }
       
$SQL->WHERE( $section_where_sql.$collection_where_sql );

       
$no_results = $params['results_no_perm_text'];
    }
    else
    {
       
$no_results = $params['results_no_text'];
    }

    if( ! empty(
$cf_name ) )
    {
// Filter by name
       
$SQL->WHERE_and( '( blog_name LIKE '.$DB->quote('%'.$cf_name.'%').' OR blog_shortname LIKE '.$DB->quote('%'.$cf_name.'%').' OR blog_urlname LIKE '.$DB->quote('%'.$cf_name.'%').' )' );
    }

    if( ! empty(
$cf_owner ) )
    {
       
$SQL->WHERE_and( 'user_login = '.$DB->quote( $cf_owner ) );
    }

    if( ! empty(
$cf_type ) )
    {
// Filter by collection type
       
$SQL->WHERE_and( 'blog_type = '.$DB->quote( $cf_type ) );
    }

   
// Create result set:
   
$blogs_Results = new Results( $SQL->get(), $params['results_param_prefix'], '----------A' );
   
$blogs_Results->Cache = & get_BlogCache();
   
$blogs_Results->title = $params['results_title'];
   
$blogs_Results->no_results_text = $no_results;

   
$blogs_Results->filter_area = array(
       
'callback' => 'callback_filter_collectionlist',
       
'is_filtered' => ! empty( $collection_filters ),
       
'url_ignore' => 'results_blog_page',
    );
   
$blogs_Results->register_filter_preset( 'all', T_('All'), '?ctrl=collections&amp;cf_type=&amp;cf_name=&amp;cf_owner=' );

    global
$admin_url;
    if(
check_user_perm( 'section', 'edit' ) )
    {    
// Display a button to create new section only if Current user has a permission for this action:
       
$blogs_Results->global_icon( T_('New Section').'...', 'new', url_add_param( $admin_url, 'ctrl=collections&amp;action=new_section' ), T_('New Section').'...', 3, 4, array( 'class' => 'action_icon btn-primary' ) );
    }
    if(
check_user_perm( 'blogs', 'create' ) )
    {    
// Display a button to create new collection only if Current user has a permission to create this in default section:
       
$blogs_Results->global_icon( T_('New Collection').'...', 'new', url_add_param( $admin_url, 'ctrl=collections&amp;action=new' ), T_('New Collection').'...', 3, 4, array( 'class' => 'action_icon btn-primary' ) );
    }

   
// Initialize Results object
   
blogs_results( $blogs_Results, $params );

    if(
is_ajax_content() )
    {
// init results param by template name
       
if( !isset( $params[ 'skin_type' ] ) || ! isset( $params[ 'skin_name' ] ) )
        {
           
debug_die( 'Invalid ajax results request!' );
        }
       
$blogs_Results->init_params_by_skin( $params[ 'skin_type' ], $params[ 'skin_name' ] );
    }

   
$blogs_Results->display( NULL, 'session' );

    if( !
is_ajax_content() )
    {
// Create this hidden div to get a function name for AJAX request
       
echo '<div id="'.$params['results_param_prefix'].'ajax_callback" style="display:none">'.__FUNCTION__.'</div>';
    }
}


/**
 * Display models to start new collections results table
 *
 * @param array Params
 */
function blogs_model_results_block( $params = array() )
{
    global
$admin_url, $DB;

   
// Make sure we are not missing any param:
   
$params = array_merge( array(
           
'results_param_prefix' => 'template_',
           
'results_title'        => T_('Models you can use to start your own collections').get_manual_link( 'site-template-list' ),
           
'results_no_text'      => T_('No model available'),
        ),
$params );

    if( !
check_user_perm( 'blogs', 'create' ) )
    {    
// Only logged in users which can create new collections can access this function
       
return;
    }

   
// Check if at least one collection exists in DB:
   
load_funcs( 'dashboard/model/_dashboard.funcs.php' );
    if(
get_table_count( 'T_blogs' ) == 0 )
    {    
// Don't display this panel if no collections:
       
return;
    }

   
$is_coll_admin = check_user_perm( 'blog_admin', 'editAll' );

    if(
is_ajax_content() )
    {
       
$order_action = param( 'order_action', 'string' );

        if(
$order_action == 'update' )
        {
// Update an order to new value
           
$new_value = ( int ) param( 'new_value', 'string', 0 );
           
$order_data = param( 'order_data', 'string' );
           
$order_obj_ID = ( int ) str_replace( 'order-blog-', '', $order_data );
            if(
$order_obj_ID > 0 )
            {
// Update blog order
               
$BlogCache = & get_BlogCache();
                if(
$updated_Blog = & $BlogCache->get_by_ID( $order_obj_ID, false ) )
                {
                    if(
check_user_perm( 'blog_properties', 'edit', false, $updated_Blog->ID ) )
                    {
// Check permission to edit this Blog
                       
$updated_Blog->set( 'order', $new_value );
                       
$updated_Blog->dbupdate();
                       
$BlogCache->clear();
                    }
                }
            }
        }
    }

   
$no_results = $params['results_no_text'];

   
$SQL = new SQL();
   
$SQL->SELECT( 'DISTINCT blog_ID, T_blogs.*, user_login' );
   
$SQL->FROM( 'T_blogs INNER JOIN T_users ON blog_owner_user_ID = user_ID' );
   
$SQL->FROM_add( 'INNER JOIN T_coll_settings ON blog_ID = cset_coll_ID' );
   
$SQL->WHERE( 'cset_name = "allow_duplicate" AND cset_value = 1' );

   
// Create result set:
   
$blogs_Results = new Results( $SQL->get(), $params['results_param_prefix'] );
   
$blogs_Results->Cache = & get_BlogCache();
   
$blogs_Results->title = $params['results_title'];
   
$blogs_Results->no_results_text = $no_results;

    if(
check_user_perm( 'blogs', 'create' ) )
    {
        global
$admin_url;
       
//$blogs_Results->global_icon( T_('New Collection').'...', 'new', url_add_param( $admin_url, 'ctrl=collections&amp;action=new' ), T_('New Collection').'...', 3, 4, array( 'class' => 'action_icon btn-primary' ) );
   
}

   
// Initialize Results object
   
blogs_results( $blogs_Results, array(
       
'display_fav' => false,
       
'display_logo' => false,
       
'display_url' => $is_coll_admin,
       
'display_locale' => $is_coll_admin,
       
'display_plist' => false,
       
'display_order' => $is_coll_admin,
       
'display_caching' => false,
       
'display_actions' => false,
       
'display_model_actions' => true
   
) );

    if(
is_ajax_content() )
    {
// init results param by template name
       
if( !isset( $params[ 'skin_type' ] ) || ! isset( $params[ 'skin_name' ] ) )
        {
           
debug_die( 'Invalid ajax results request!' );
        }
       
$blogs_Results->init_params_by_skin( $params[ 'skin_type' ], $params[ 'skin_name' ] );
    }

   
$blogs_Results->display( NULL, 'session' );

    if( !
is_ajax_content() )
    {
// Create this hidden div to get a function name for AJAX request
       
echo '<div id="'.$params['results_param_prefix'].'ajax_callback" style="display:none">'.__FUNCTION__.'</div>';
    }
}


/**
 * Initialize Results object for blogs list
 *
 * @param object Results
 * @param array Params
 */
function blogs_results( & $blogs_Results, $params = array() )
{
   
// Make sure we are not missing any param:
   
$params = array_merge( array(
           
'display_id'       => true,
           
'display_name'     => true,
           
'display_type'     => true,
           
'display_fullname' => true,
           
'display_owner'    => true,
           
'display_url'      => true,
           
'display_locale'   => true,
           
'display_plist'    => true,
           
'display_fav'      => true,
           
'display_logo'     => true,
           
'display_order'    => true,
           
'display_caching'  => true,
           
'display_actions'  => true,
           
'display_model_actions' => false,
           
'grouped'          => false,
        ),
$params );

   
$cols_num = 0;

    if(
$params['display_id'] )
    {    
// Display ID column:
       
$blogs_Results->cols[] = array(
               
'th' => T_('ID'),
               
'order' => 'blog_ID',
               
'th_class' => 'shrinkwrap',
               
'td_class' => 'shrinkwrap',
               
'td' => '$blog_ID$',
            );
       
$cols_num++;
    }

    if(
$params['display_fav'] )
    {    
// Display Favorite column:
       
$blogs_Results->cols[] = array(
               
'th' => T_('Fav'),
               
'th_title' => T_('Favorite'),
               
'order' => 'blog_favorite',
               
'th_class' => 'shrinkwrap',
               
'td_class' => 'shrinkwrap',
               
'td' => '%blog_row_setting( #blog_ID#, "fav", #blog_favorite# )%',
            );
       
$cols_num++;
    }

    if(
$params['display_logo'] )
    {    
// Display collection logo:
       
$blogs_Results->cols[] = array(
               
'th' => T_('Image'),
               
'th_title' => T_('Image'),
               
'th_class' => 'shrinkwrap',
               
'td_class' => 'shrinkwrap',
               
'td' => '%blog_row_setting( #blog_ID#, "logo", #collection_logo_file_ID# )%',
            );
       
$cols_num++;
    }

    if(
$params['display_name'] )
    {    
// Display Name column:
       
$blogs_Results->cols[] = array(
               
'th' => T_('Name'),
               
'order' => 'blog_shortname',
               
'td' => '<strong>%blog_row_name( #blog_shortname#, #blog_ID# )%</strong>',
            );
       
$cols_num++;
    }

    if(
$params['display_type'] )
    {    
// Display Type column:
       
$blogs_Results->cols[] = array(
               
'th' => T_('Type'),
               
'order' => 'blog_type',
               
'td' => '%blog_row_type( #blog_type#, #blog_ID# )%',
               
'th_class' => 'shrinkwrap',
               
'td_class' => 'shrinkwrap',
            );
       
$cols_num++;
    }

    if(
$params['display_fullname'] )
    {    
// Display Full Name column:
       
$blogs_Results->cols[] = array(
               
'th' => T_('Full Name'),
               
'order' => 'blog_name',
               
'td' => '%blog_row_fullname( #blog_name#, #blog_ID# )%',
            );
       
$cols_num++;
    }

    if(
$params['grouped'] )
    {    
// Display group rows:
       
$blogs_Results->group_by = 'sec_ID';
       
$blogs_Results->ID_col = 'blog_ID';

       
$blogs_Results->grp_cols[] = array(
               
'td_colspan' => $cols_num,
               
'td' => '%blog_row_group_name( #sec_ID#, #sec_name# )%',
            );
    }

    if(
$params['display_owner'] )
    {    
// Display Owner column:
       
$blogs_Results->cols[] = array(
               
'th' => T_('Owner'),
               
'order' => 'user_login',
               
'td' => '%get_user_identity_link( #user_login# )%',
            );
       
$cols_num++;
        if(
$params['grouped'] )
        {    
// Group owner:
           
$blogs_Results->grp_cols[] = array(
                   
'td' => '%get_user_identity_link( "", #sec_owner_user_ID# )%',
                );
           
$cols_num = 0;
        }
    }

    if(
$params['display_url'] )
    {    
// Display Blog URL column:
       
$blogs_Results->cols[] = array(
               
'th' => T_('Blog URL'),
               
'td' => '<a href="@get(\'url\')@">@get(\'url\')@</a>',
            );
       
$cols_num++;
    }

    if(
$params['display_locale'] )
    {    
// Display Locale column:
       
$blogs_Results->cols[] = array(
               
'th' => T_('Locale'),
               
'order' => 'blog_locale',
               
'th_class' => 'shrinkwrap',
               
'td_class' => 'shrinkwrap',
               
'td' => '%blog_row_locale( #blog_locale#, #blog_ID# )%',
            );
       
$cols_num++;
    }

    if(
$params['display_plist'] )
    {    
// Display Listed column:
       
$blogs_Results->cols[] = array(
               
'th' => T_('Listed'),
               
'th_title' => T_('Public List'),
               
'order' => 'blog_in_bloglist',
               
'th_class' => 'shrinkwrap',
               
'td_class' => 'shrinkwrap',
               
'td' => '%blog_row_listed( #blog_in_bloglist#, #blog_ID# )%',
            );
       
$cols_num++;
    }

    if(
$params['display_order'] )
    {    
// Display Order column:
       
$blogs_Results->cols[] = array(
               
'th' => T_('Order'),
               
'order' => 'blog_order',
               
'th_class' => 'shrinkwrap',
               
'td_class' => 'shrinkwrap',
               
'td' => '%blog_row_order( #blog_ID#, #blog_order# )%',
            );
       
$cols_num++;
        if(
$params['grouped'] )
        {    
// Group order:
           
$blogs_Results->grp_cols[] = array(
                   
'td_colspan' => $cols_num - 1,
                   
'td' => ''
               
);
           
$blogs_Results->grp_cols[] = array(
                   
'td_class' => 'shrinkwrap',
                   
'td' => '%blog_row_group_order( #sec_ID#, #sec_order# )%',
                );
           
$cols_num = 0;
        }
    }

    if(
$params['display_caching'] )
    {    
// Display Order column:
       
$blogs_Results->cols[] = array(
               
'th' => T_('Caching'),
               
'th_class' => 'shrinkwrap',
               
'td_class' => 'shrinkwrap',
               
'td' => '%blog_row_caching( {Obj} )%',
            );
       
$cols_num++;
    }

    if(
$params['display_actions'] )
    {    
// Display Actions column:
       
$blogs_Results->cols[] = array(
               
'th' => T_('Actions'),
               
'th_class' => 'shrinkwrap',
               
'td_class' => 'shrinkwrap',
               
'td' => '%blog_row_actions( {Obj}, #blog_sec_ID# )%',
            );
        if(
$params['grouped'] )
        {    
// Group actions:
           
$blogs_Results->grp_cols[] = array(
                   
'td_colspan' => $cols_num,
                   
'td' => ''
               
);
           
$blogs_Results->grp_cols[] = array(
                   
'td_class' => 'nowrap',
                   
'td' => '%blog_row_group_actions( {row} )%',
                );
        }
    }

    if(
$params['display_model_actions'] )
    {
       
$blogs_Results->cols[] = array(
               
'th' => T_('Actions'),
               
'th_class' => 'shrinkwrap',
               
'td_class' => 'shrinkwrap left',
               
'td' => '%model_row_actions( {Obj} )%',
            );
    }
}


/**
 * Helper functions to display Blogs results.
 * New ( not display helper ) functions must be created above blogs_results function
 */


/**
 * Get a name of section with link to edit form
 *
 * @param integer Section ID
 * @param string Section name
 * @return string Section name with link to edit form if user has a permission
 */
function blog_row_group_name( $sec_ID, $sec_name )
{
    global
$admin_url;

    if(
check_user_perm( 'section', 'view', false, $sec_ID ) )
    {    
// If user can view the section:
       
$sec_name = '<a href="'.$admin_url.'?ctrl=collections&amp;action=edit_section&amp;sec_ID='.$sec_ID.'">'.$sec_name.'</a>';
    }

    return
'<b>'.$sec_name.'</b>';
}

/**
 * Get a blog name with link to edit
 *
 * @param string Blog name
 * @param integer Blog ID
 * @return string Link
 */
function blog_row_name( $coll_name, $coll_ID )
{
    global
$ctrl, $admin_url;
    if(
$ctrl == 'dashboard' && check_user_perm( 'blog_ismember', 'view', false, $coll_ID ) )
    {
// Dashboard
       
$edit_url = $admin_url.'?ctrl=coll_settings&amp;tab=dashboard&amp;blog='.$coll_ID;
       
$r = '<a href="'.$edit_url.'">';
       
$r .= $coll_name;
       
$r .= '</a>';
    }
    elseif(
check_user_perm( 'blog_properties', 'edit', false, $coll_ID ) )
    {
// Blog setting & can edit
       
$edit_url = $admin_url.'?ctrl=coll_settings&amp;blog='.$coll_ID;
       
$r = '<a href="'.$edit_url.'" title="'.T_('Edit properties...').'">';
       
$r .= $coll_name;
       
$r .= '</a>';
    }
    else
    {
       
$r = $coll_name;
    }
    return
$r;
}


/**
 * Get a blog full name with link to edit
 *
 * @param string Blog full name
 * @param integer Blog ID
 * @return string Link
 */
function blog_row_fullname( $coll_fullname, $coll_ID )
{
    global
$admin_url;

   
$coll_fullname = strmaxlen( $coll_fullname, 40, NULL, 'raw' );

    if(
check_user_perm( 'blog_properties', 'edit', false, $coll_ID ) )
    {
// Blog setting & can edit
       
$edit_url = $admin_url.'?ctrl=coll_settings&amp;tab=general&amp;blog='.$coll_ID;
       
$r = '<a href="'.$edit_url.'" title="'.T_('Edit properties...').'">';
       
$r .= $coll_fullname;
       
$r .= '</a>';
    }
    else
    {
       
$r = $coll_fullname;
    }

    return
$r;
}


/**
 * Get a blog type with link to edit
 *
 * @param string Blog type
 * @param integer Blog ID
 * @return string Link
 */
function blog_row_type( $coll_type, $coll_ID )
{
    global
$admin_url, $Settings;

   
$type_titles = array(
           
'minisite' => T_('Mini-Site'),
           
'main'     => T_('Main'),
           
'std'      => T_('Blog'),
           
'photo'    => T_('Gallery'),
           
'group'    => T_('Collab'),
           
'forum'    => T_('Forum'),
           
'manual'   => T_('Manual'),
        );

   
$type_title = isset( $type_titles[ $coll_type ] ) ? $type_titles[ $coll_type ] : $coll_type;

    if(
check_user_perm( 'blog_properties', 'edit', false, $coll_ID ) )
    {
// Blog setting & can edit
       
$edit_url = $admin_url.'?ctrl=coll_settings&tab=general&action=type&blog='.$coll_ID;
       
$r = '<a href="'.$edit_url.'" title="'.T_('Edit properties...').'">';
       
$r .= $type_title;
       
$r .= '</a>';
    }
    else
    {
       
$r = $type_title;
    }

   
// Display the icons depending on how blog is used as default
   
$r .= ' ';
    if(
$coll_ID == $Settings->get( 'default_blog_ID' ) )
    {
// This blog is default
       
$r .= action_icon( T_('Default collection to display'), 'coll_default', $admin_url.'?ctrl=collections&amp;tab=site_settings' );
    }
    if(
$coll_ID == $Settings->get( 'login_blog_ID' ) )
    {
// This blog is used for login actions
       
$r .= action_icon( T_('Collection for login/registration'), 'coll_login', $admin_url.'?ctrl=collections&amp;tab=site_settings' );
    }
    if(
$coll_ID == $Settings->get( 'msg_blog_ID' ) )
    {
// This blog is used for messaging
       
$r .= action_icon( T_('Collection for profiles/messaging'), 'coll_message', $admin_url.'?ctrl=collections&amp;tab=site_settings' );
    }
    if(
$coll_ID == $Settings->get( 'info_blog_ID' ) )
    {
// This blog is used for info
       
$r .= action_icon( T_('Collection for shared content blocks'), 'coll_info', $admin_url.'?ctrl=collections&amp;tab=site_settings' );
    }

    return
$r;
}


/**
 * Get a blog locale with link to edit
 *
 * @param string Blog locale
 * @param integer Blog ID
 * @return string Link
 */
function blog_row_locale( $coll_locale, $coll_ID )
{
    global
$admin_url;

   
$coll_locale = locale_flag( $coll_locale, NULL, NULL, NULL, false );

    if(
check_user_perm( 'blog_properties', 'edit', false, $coll_ID ) )
    {
// Blog setting & can edit
       
$edit_url = $admin_url.'?ctrl=coll_settings&amp;blog='.$coll_ID;
       
$r = '<a href="'.$edit_url.'" title="'.T_('Edit properties...').'">';
       
$r .= $coll_locale;
       
$r .= '</a>';
    }
    else
    {
       
$r = $coll_locale;
    }

    return
$r;
}


/**
 * Get a blog order with link to edit
 *
 * @param integer Blog ID
 * @param integer Blog order
 * @return string Link or Text
 */
function blog_row_order( $blog_ID, $blog_order )
{
    global
$admin_url;

    if(
check_user_perm( 'blog_properties', 'edit', false, $blog_ID ) )
    {
// Blog setting & can edit
       
$edit_url = $admin_url.'?ctrl=coll_settings&amp;tab=general&amp;blog='.$blog_ID.'#blog_order';
       
$r = '<a href="'.$edit_url.'" id="order-blog-'.$blog_ID.'" style="display:block;">';
       
$r .= $blog_order;
       
$r .= '</a>';
    }
    else
    {
       
$r = $blog_order;
    }
    return
$r;
}


/**
 * Get a section order with link to edit
 *
 * @param integer Section ID
 * @param integer Section order
 * @return string Link or Text
 */
function blog_row_group_order( $sec_ID, $sec_order )
{
    global
$admin_url;

    if(
check_user_perm( 'section', 'edit', false, $sec_ID ) )
    {    
// Only if current user has a permission to edit sections:
       
$edit_url = $admin_url.'?ctrl=collections&amp;action=edit_section&amp;sec_ID='.$sec_ID;
       
$r = '<a href="'.$edit_url.'" id="order-section-'.$sec_ID.'" style="display:block;">';
       
$r .= $sec_order;
       
$r .= '</a>';
    }
    else
    {
       
$r = $sec_order;
    }

    return
'<b>'.$r.'</b>';
}


/**
 * Get the action icons to toggle caching settings of blog
 *
 * @param object Blog
 * @return string
 */
function blog_row_caching( $Blog )
{
    global
$admin_url;

   
// Get icon and title for page caching status
   
if( $Blog->get_setting( 'cache_enabled' ) )
    {
// Page cache is enabled
       
$page_cache_icon = 'page_cache_on';
       
$page_cache_title = T_('Page caching is on. Anonymous users may not see the latest content for 10 minutes.');
       
$page_cache_action = 'disable_setting';
    }
    else
    {
// Page cache is disabled
       
$page_cache_icon = 'page_cache_off';
       
$page_cache_title = T_('Page caching is off. Server performance will not be optimal.');
       
$page_cache_action = 'enable_setting';
    }

   
// Get icon and title for widget/block caching status
   
if( $Blog->get_setting( 'cache_enabled_widgets' ) )
    {
// Widget/block cache is enabled
       
$block_cache_icon = 'block_cache_on';
       
$block_cache_title = T_('Block caching is on. Some widgets may not update immediately.');
       
$block_cache_action = 'disable_setting';
    }
    else
    {
// Widget/block cache is disabled
       
$block_cache_icon = 'block_cache_off';
       
$block_cache_title = T_('Block caching is off. Server performance will not be optimal.');
       
$block_cache_action = 'enable_setting';
    }

   
$r = '';
   
$before = '<span class="column_icon">';
   
$after = '</span>';

    if(
check_user_perm( 'blog_properties', 'edit', false, $Blog->ID ) )
    {
// User has a permission to edit blog settings
       
$toggle_url = $admin_url.'?ctrl=coll_settings'
           
.'&amp;tab=general'
           
.'&amp;action=%s'
           
.'&amp;setting=%s'
           
.'&amp;blog='.$Blog->ID
           
.'&amp;'.url_crumb( 'collection' );
       
$r .= $before.action_icon( $page_cache_title, $page_cache_icon, sprintf( $toggle_url, $page_cache_action, 'page_cache' ) ).$after;
       
$r .= $before.action_icon( $block_cache_title, $block_cache_icon, sprintf( $toggle_url, $block_cache_action, 'block_cache' ) ).$after;
    }
    else
    {
// No permissions to edit
       
$r .= $before.get_icon( $page_cache_icon, 'imgtag', array( 'title' => $page_cache_title ) ).$after;
       
$r .= $before.get_icon( $block_cache_icon, 'imgtag', array( 'title' => $block_cache_title ) ).$after;
    }

    return
$r;
}


/**
 * Gat title of value for the blog field "blog_in_bloglist"
 *
 * @param integer Value
 * @return string Title
 */
function blog_row_listed( $value, $coll_ID )
{
    global
$admin_url;

    switch(
$value )
    {
        case
'public':
           
$title = T_('Always');
            break;
        case
'logged':
           
$title = T_('Logged in');
            break;
        case
'member':
           
$title = T_('Members');
            break;
        case
'never':
           
$title = T_('Never');
            break;
        default:
           
$title = $value;
            break;
    }

    if(
check_user_perm( 'blog_properties', 'edit', false, $coll_ID ) )
    {
// Blog setting & can edit
       
$edit_url = $admin_url.'?ctrl=coll_settings&amp;blog='.$coll_ID;
       
$r = '<a href="'.$edit_url.'" title="'.T_('Edit properties...').'">';
       
$r .= $title;
       
$r .= '</a>';
    }
    else
    {
       
$r = $title;
    }

    return
$r;
}


/**
 * Get an icon to show that blog setting is enabled or disabled
 * Make a link to switch setting value if user has permissions to edit blog settings
 *
 * @param integer Blog ID
 * @param boolean Blog setting name: 'fav'
 * @param boolean Blog setting value: 0, 1
 * @return string Icon or Link to change setting
 */
function blog_row_setting( $blog_ID, $setting_name, $setting_value )
{
    global
$admin_url;

    switch(
$setting_name )
    {
        case
'fav':
            return
get_coll_fav_icon( $blog_ID, array( 'class' => 'coll-fav' ) );

        case
'logo':
           
$FileCache = & get_FileCache();
            if(
$image_File = & $FileCache->get_by_ID( $setting_value, false, false ) )
            {
                return
$image_File->get_tag( '', '', '', '', 'crop-32x32', 'original', '', 'lightbox[c'.$image_File->ID.']' );
            }
            return;

        default:
           
// Incorrect setting name
           
return;
    }
}


/**
 * Get available actions for current blog
 *
 * @param object Blog
 * @param integer Section ID
 * @return string Action links
 */
function blog_row_actions( $Blog, $sec_ID )
{
    global
$admin_url;

   
$r = '<a href="'.$Blog->get( 'url' ).'" class="action_icon btn btn-info btn-xs" title="'.T_('View this collection').'">'.T_('View').'</a>';
    if(
check_user_perm( 'blog_properties', 'edit', false, $Blog->ID ) )
    {    
// If user can edit collection properties:
       
$r .= '<a href="'.$admin_url.'?ctrl=coll_settings&amp;tab=dashboard&amp;blog='.$Blog->ID.'" class="action_icon btn btn-primary btn-xs" title="'.T_('Manage this collection...').'">'.T_('Manage').'</a>';
    }
    if(
check_user_perm( 'blog_properties', 'copy', false, $Blog->ID ) )
    {    
// If user can copy collection properties:
       
$r .= action_icon( T_('Duplicate this collection...'), 'copy', $admin_url.'?ctrl=collections&amp;action=copy&amp;blog='.$Blog->ID );
    }
    if(
check_user_perm( 'blog_properties', 'edit', false, $Blog->ID ) )
    {    
// If user can edit collection properties:
           
$r .= action_icon( T_('Delete this blog...'), 'delete', $admin_url.'?ctrl=collections&amp;action=delete&amp;blog='.$Blog->ID.'&amp;'.url_crumb('collection').'&amp;redirect_to='.rawurlencode( regenerate_url( '', '', '', '&' ) ) );
    }

    if( empty(
$r) )
    {
// for IE
       
$r = '&nbsp;';
    }

    return
$r;
}


/**
 * Get available actions for current section
 *
 * @param object Row
 * @return string Action links
 */
function blog_row_group_actions( & $row )
{
    global
$admin_url;

   
$r = '';

    if(
check_user_perm( 'section', 'edit', false, $row->sec_ID ) )
    {    
// If user can edit the section:
       
$r .= action_icon( T_('Edit this section'), 'edit', $admin_url.'?ctrl=collections&amp;action=edit_section&amp;sec_ID='.$row->sec_ID );
    }
    if(
check_user_perm( 'blogs', 'create', false, $row->sec_ID ) )
    {    
// If user can create new collection in the section:
       
$r .= action_icon( T_('New Collection').'...', 'new', $admin_url.'?ctrl=collections&amp;action=new&amp;sec_ID='.$row->sec_ID );
    }
    if(
$row->sec_ID != 1 && $row->blog_ID === NULL && check_user_perm( 'section', 'edit', false, $row->sec_ID ) )
    {    
// If user can delete the section(only without collections):
       
$r .= action_icon( T_('Delete this section!'), 'delete', $admin_url.'?ctrl=collections&amp;action=delete_section&amp;sec_ID='.$row->sec_ID.'&amp;'.url_crumb( 'section' ) );
    }

    return
$r;
}


/**
 * Get available actions for current model
 *
 * @param object Blog
 * @return string Action links
 */
function model_row_actions( $Blog )
{
    global
$admin_url;
   
$r = '';

   
$r .= '<a href="'.$Blog->get( 'url' ).'" class="action_icon btn btn-info btn-xs" title="'.T_('View this collection').'">'.T_('View').'</a>';
   
$r .= '<a href="'.$admin_url.'?ctrl=collections&amp;action=copy&amp;blog='.$Blog->ID.'" class="action_icon btn btn-primary btn-xs" title="'.T_('Use this model').'">'.T_('Use this model').'</a>';
    if(
check_user_perm( 'blog_properties', 'edit', false, $Blog->ID ) )
    {
       
$r .= action_icon( T_('Edit this collection...'), 'edit', $admin_url.'?ctrl=coll_settings&amp;tab=general&amp;blog='.$Blog->ID );
       
$r .= action_icon( T_('Delete this blog...'), 'delete', $admin_url.'?ctrl=collections&amp;action=delete&amp;blog='.$Blog->ID.'&amp;'.url_crumb('collection').'&amp;redirect_to='.rawurlencode( regenerate_url( '', '', '', '&' ) ) );
    }

    if( empty(
$r) )
    {
// for IE
       
$r = '&nbsp;';
    }

    return
$r;
}

/**
 * End of helper functions block to display Blogs results.
 * New ( not display helper ) functions must be created above blogs_results function
 */

?>