<?php
/**
* This file implements the Blog class.
*
* 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}.
* Parts of this file are copyright (c)2005 by Jason Edgecombe.
*
* @package evocore
*/
if( !defined('EVO_MAIN_INIT') ) die( 'Please, do not access this page directly.' );
load_class( '_core/model/dataobjects/_dataobject.class.php', 'DataObject' );
/**
* Blog
*
* Blog object with params
*
* @package evocore
*/
class Blog extends DataObject
{
/**
* Group ID
* @var integer
*/
var $sec_ID;
/**
* Short name for use in navigation menus
* @var string
*/
var $shortname;
/**
* Complete name
* @var string
*/
var $name;
/**
* Tagline to be displayed on template
* @var string
*/
var $tagline;
var $shortdesc; // description
var $longdesc;
/**
* @var integer
*/
var $owner_user_ID;
/**
* Lazy filled
* @var User
* @see get_owner_User()
* @access protected
*/
var $owner_User = NULL;
var $advanced_perms = 0;
var $locale;
var $order;
var $access_type;
/*
* ?> TODO: we should have an extra DB column that either defines type of blog_siteurl
* OR split blog_siteurl into blog_siteurl_abs and blog_siteurl_rel (where blog_siteurl_rel could be "blog_sitepath")
*/
var $siteurl;
var $stub; // stub file (can be empty/virtual)
var $urlname; // used to identify blog in URLs
var $links_blog_ID = 0; // DEPRECATED
var $notes;
var $keywords;
var $allowtrackbacks = 0;
var $allowblogcss = 0;
var $allowusercss = 0;
var $in_bloglist = 'public';
var $media_location = 'default';
var $media_subdir = '';
var $media_fullpath = '';
var $media_url = '';
var $normal_skin_ID = NULL;
var $mobile_skin_ID = NULL;
var $tablet_skin_ID = NULL;
var $alt_skin_ID = NULL;
var $base_collection_ID = 0;
/**
* The basepath of that collection.
*
* Lazy filled by get_basepath()
*
* @var string
*/
var $basepath;
/**
* The URL to the basepath of that collection.
* This is supposed to be the same as $baseurl but localized to the domain of the blog/
*
* Lazy filled by get_basepath_url()
*
* @var string
*/
var $basepath_url;
/**
* The domain of that collection.
*
* Lazy filled by get_baseurl_root()
*
* @var string
*/
var $baseurl_root;
/**
* The URL aliases
*
* Lazy filled by get_url_aliases()
*
* @var array
*/
var $url_aliases;
var $update_url_aliases = false;
/**
* The domain for cookie of that collection.
*
* Lazy filled by get_cookie_domain()
*
* @var string
*/
var $cookie_domain;
/**
* The path for cookie of that collection.
*
* Lazy filled by get_cookie_path()
*
* @var string
*/
var $cookie_path;
/**
* The htsrv URLs to the basepath of that collection.
*
* Lazy filled by get_htsrv_url()
*
* @var array: 0 - normal URL, 1 - secure URL
*/
var $htsrv_urls;
/**
* Additional settings for the collection. lazy filled.
*
* @see Blog::get_setting()
* @see Blog::set_setting()
* @see Blog::load_CollectionSettings()
* Any non vital params should go into there (this includes many of the above).
*
* @var CollectionSettings
*/
var $CollectionSettings;
/**
* Lazy filled
*
* @var integer
*/
var $default_cat_ID;
/**
* @var string Type of blog ( 'std', 'photo', 'group', 'forum', 'manual' )
*/
var $type;
/**
* @var array Data of moderators which must be notified about new/edited comments
*/
var $comment_moderator_user_data;
/**
* @var array Locales:
* Key - Locale key
* Value - Collection ID or NULL for locale of this collection
*/
var $locales = NULL;
/**
* Constructor
*
* @param object DB row
*/
function __construct( $db_row = NULL )
{
global $Timer, $Settings;
$Timer->start( 'Blog constructor' );
// Call parent constructor:
parent::__construct( 'T_blogs', 'blog_', 'blog_ID' );
if( $db_row == NULL )
{
global $default_locale;
// echo 'Creating blank blog';
$this->owner_user_ID = 1; // DB default
$this->set( 'locale', $default_locale );
$this->set_locales( array( $default_locale ) );
// Use access type(Collection base URL) from general settings:
$this->set( 'access_type', $Settings->get( 'coll_access_type' ) );
if( is_logged_in() )
{ // Set section what is used as default for group of current user:
global $current_User;
$user_Group = & $current_User->get_Group();
$this->set( 'sec_ID', $user_Group->get_setting( 'perm_default_sec_ID' ) );
}
}
else
{
/**
* NOTE: Check each new added or renamed field by function isset() below,
* Otherwise it may create issues during upgrade process from old to new DB:
*/
$this->ID = $db_row->blog_ID;
$this->sec_ID = isset( $db_row->blog_sec_ID ) ? $db_row->blog_sec_ID : NULL;
$this->shortname = $db_row->blog_shortname;
$this->name = $db_row->blog_name;
$this->owner_user_ID = $db_row->blog_owner_user_ID;
$this->advanced_perms = $db_row->blog_advanced_perms;
$this->tagline = $db_row->blog_tagline;
$this->shortdesc = isset( $db_row->blog_shortdesc ) ? $db_row->blog_shortdesc : ''; // description
$this->longdesc = $db_row->blog_longdesc;
$this->locale = $db_row->blog_locale;
$this->access_type = $db_row->blog_access_type;
$this->siteurl = $db_row->blog_siteurl;
$this->urlname = $db_row->blog_urlname;
$this->links_blog_ID = $db_row->blog_links_blog_ID; // DEPRECATED
$this->notes = $db_row->blog_notes;
$this->keywords = $db_row->blog_keywords;
$this->allowtrackbacks = $db_row->blog_allowtrackbacks;
$this->allowblogcss = $db_row->blog_allowblogcss;
$this->allowusercss = $db_row->blog_allowusercss;
$this->in_bloglist = $db_row->blog_in_bloglist;
$this->media_location = $db_row->blog_media_location;
$this->media_subdir = $db_row->blog_media_subdir;
$this->media_fullpath = $db_row->blog_media_fullpath;
$this->media_url = $db_row->blog_media_url;
$this->type = isset( $db_row->blog_type ) ? $db_row->blog_type : 'std';
$this->order = isset( $db_row->blog_order ) ? $db_row->blog_order : 0;
$this->normal_skin_ID = isset( $db_row->blog_normal_skin_ID ) ? $db_row->blog_normal_skin_ID : NULL; // check by isset() to avoid warnings of deleting all tables before new install
$this->mobile_skin_ID = isset( $db_row->blog_mobile_skin_ID ) ? $db_row->blog_mobile_skin_ID : NULL; // NULL means the same as normal_skin_ID value
$this->tablet_skin_ID = isset( $db_row->blog_tablet_skin_ID ) ? $db_row->blog_tablet_skin_ID : NULL; // NULL means the same as normal_skin_ID value
$this->alt_skin_ID = isset( $db_row->blog_alt_skin_ID ) ? $db_row->blog_alt_skin_ID : NULL; // NULL means the same as normal_skin_ID value
}
$Timer->pause( 'Blog constructor' );
}
/**
* Get delete cascade settings
*
* @return array
*/
static function get_delete_cascades()
{
return array(
array( 'table'=>'T_coll_user_favs', 'fk'=>'cufv_blog_ID', 'msg'=>T_('%d user favorites') ),
array( 'table'=>'T_coll_settings', 'fk'=>'cset_coll_ID', 'msg'=>T_('%d blog settings') ),
array( 'table'=>'T_coll_locales', 'fk'=>'cl_coll_ID', 'msg'=>T_('%d extra locales associations') ),
array( 'table'=>'T_coll_url_aliases', 'fk'=>'cua_coll_ID', 'msg'=>T_('%d URL aliases') ),
array( 'table'=>'T_coll_user_perms', 'fk'=>'bloguser_blog_ID', 'msg'=>T_('%d user permission definitions') ),
array( 'table'=>'T_coll_group_perms', 'fk'=>'bloggroup_blog_ID', 'msg'=>T_('%d group permission definitions') ),
array( 'table'=>'T_subscriptions', 'fk'=>'sub_coll_ID', 'msg'=>T_('%d subscriptions') ),
array( 'table'=>'T_widget__container', 'fk'=>'wico_coll_ID', 'msg'=>T_('%d widget container'),
'class'=>'WidgetContainer', 'class_path'=>'widgets/model/_widgetcontainer.class.php' ),
array( 'table'=>'T_hitlog', 'fk'=>'hit_coll_ID', 'msg'=>T_('%d hits') ),
array( 'table'=>'T_hits__aggregate', 'fk'=>'hagg_coll_ID', 'msg'=>T_('%d hits aggregations') ),
array( 'table'=>'T_hits__aggregate_sessions', 'fk'=>'hags_coll_ID', 'msg'=>T_('%d sessions aggregations') ),
array( 'table'=>'T_items__type_coll', 'fk'=>'itc_coll_ID', 'msg'=>T_('%d Post type associations with collections') ),
array( 'table'=>'T_categories', 'fk'=>'cat_blog_ID', 'msg'=>T_('%d related categories with all of their content recursively'),
'class'=>'Chapter', 'class_path'=>'chapters/model/_chapter.class.php' ),
array( 'table'=>'T_files', 'fk'=>'file_root_ID', 'and_condition'=>'file_root_type = "collection"', 'msg'=>T_('%d files in this blog file root'),
'class'=>'File', 'class_path'=>'files/model/_file.class.php' ),
array( 'table'=>'T_temporary_ID', 'fk'=>'tmp_coll_ID', 'msg'=>T_('%d temporary uploaded links') ),
);
}
/**
* Get delete restriction settings
*
* @return array
*/
static function get_delete_restrictions()
{
global $admin_url;
return array(
array( 'table' => 'T_settings', 'fk' => 'set_value', 'and_condition' => 'set_name = "default_blog_ID"', 'msg' => sprintf( T_('This collection cannot be deleted because it is used as <a %s>Default collection to display</a>.'), 'href="'.$admin_url.'?ctrl=collections&tab=site_settings"' ) ),
array( 'table' => 'T_settings', 'fk' => 'set_value', 'and_condition' => 'set_name = "login_blog_ID"', 'msg' => sprintf( T_('This collection cannot be deleted because it is used as <a %s>Collection for login/registration</a>.'), 'href="'.$admin_url.'?ctrl=collections&tab=site_settings"' ) ),
array( 'table' => 'T_settings', 'fk' => 'set_value', 'and_condition' => 'set_name = "msg_blog_ID"', 'msg' => sprintf( T_('This collection cannot be deleted because it is used as <a %s>Collection for profiles/messaging</a>.'), 'href="'.$admin_url.'?ctrl=collections&tab=site_settings"' ) ),
array( 'table' => 'T_settings', 'fk' => 'set_value', 'and_condition' => 'set_name = "info_blog_ID"', 'msg' => sprintf( T_('This collection cannot be deleted because it is used as <a %s>Collection for shared content blocks</a>.'), 'href="'.$admin_url.'?ctrl=collections&tab=site_settings"' ) ),
);
}
/**
* Compare two Blog based on the common blog order setting
*
* @param Blog A
* @param Blog B
* @return number -1 if A < B, 1 if A > B, 0 if A == B
*/
static function compare_blogs( $a_Blog, $b_Blog )
{
global $Settings;
if( $a_Blog->ID == $b_Blog->ID )
{
return 0;
}
$order_by = $Settings->get('blogs_order_by');
$order_dir = $Settings->get('blogs_order_dir');
if( $order_by == 'RAND' )
{ // In case of Random order we consider every blog as equal
return 0;
}
$blog_a_value = $a_Blog->get( $order_by );
$blog_b_value = $b_Blog->get( $order_by );
if( $blog_a_value == $blog_b_value )
{ // The compare fields are equal sort based on the ID
$blog_a_value = $a_Blog->ID;
$blog_b_value = $b_Blog->ID;
}
$result = is_numeric( $blog_a_value ) ? ( $blog_a_value < $blog_b_value ? -1 : 1 ) : strcmp( $blog_a_value, $blog_b_value );
if( $order_dir == 'DESC' )
{ // Change the order direction
$result = $result * (-1);
}
return $result;
}
/**
* Initialize blog setting by kind
*
* @param string Kind: 'minisite', 'main', 'std', 'photo', 'group', 'forum', 'manual'
* @param string Name
* @param string Short name
* @param string Url/slug
*/
function init_by_kind( $kind, $name = NULL, $shortname = NULL, $urlname = NULL )
{
// Set default tagline for collection of any kind:
$this->set( 'tagline', T_('This is the collection\'s tagline.') );
switch( $kind )
{
case 'minisite':
$this->set( 'type', 'minisite' );
$this->set( 'name', empty( $name ) ? T_('Mini-Site Title') : $name );
$this->set( 'shortname', empty( $shortname ) ? T_('Mini-Site') : $shortname );
$this->set( 'urlname', empty( $urlname ) ? 'minisite' : $urlname );
$this->set_setting( 'front_disp', 'front' );
if( $blog_skin_ID = $this->get_skin_ID( 'normal' ) )
{
$this->set_setting( 'skin'.$blog_skin_ID.'_section_2_image_file_ID', NULL );
$this->set_setting( 'skin'.$blog_skin_ID.'_section_3_display', 1 );
$this->set_setting( 'skin'.$blog_skin_ID.'_section_3_title_color', '#FFFFFF' );
$this->set_setting( 'skin'.$blog_skin_ID.'_section_3_text_color', '#FFFFFF' );
$this->set_setting( 'skin'.$blog_skin_ID.'_section_3_link_color', '#FFFFFF' );
$this->set_setting( 'skin'.$blog_skin_ID.'_section_3_link_h_color', '#FFFFFF' );
$this->set_setting( 'skin'.$blog_skin_ID.'_section_4_image_file_ID', NULL );
}
break;
case 'main':
$this->set( 'type', 'main' );
$this->set( 'name', empty( $name ) ? T_('Homepage Title') : $name );
$this->set( 'shortname', empty( $shortname ) ? T_('Home') : $shortname );
$this->set( 'urlname', empty( $urlname ) ? 'home' : $urlname );
$this->set_setting( 'front_disp', 'front' );
$this->set_setting( 'in_skin_login', '1' );
break;
case 'photo':
$this->set( 'type', 'photo' );
$this->set( 'name', empty($name) ? T_('Photos') : $name );
$this->set( 'shortname', empty($shortname) ? T_('Photos') : $shortname );
$this->set( 'urlname', empty($urlname) ? 'photos' : $urlname );
$this->set_setting( 'posts_per_page', 12 );
$this->set_setting( 'archive_mode', 'postbypost' );
$this->set_setting( 'front_disp', 'posts' );
// Try to find post type "Photo Album" in DB:
global $DB;
$photo_album_type_ID = $DB->get_var( 'SELECT ityp_ID
FROM T_items__type
WHERE ityp_name = "Photo Album"' );
if( $photo_album_type_ID )
{ // Set default post type as "Photo Album":
$this->set_setting( 'default_post_type', $photo_album_type_ID );
}
if( is_pro() )
{ // Enable tracking of unread content only in PRO version:
$this->set_setting( 'track_unread_content', 1 );
}
break;
case 'group':
$this->set( 'type', 'group' );
$this->set( 'name', empty($name) ? T_('Tracker Title') : $name );
$this->set( 'shortname', empty($shortname) ? T_('Tracker') : $shortname );
$this->set( 'urlname', empty($urlname) ? 'tracker' : $urlname );
$this->set_setting( 'use_workflow', 1 );
$this->set_setting( 'in_skin_editing', '1' );
$this->set_setting( 'front_disp', 'front' );
$this->set_setting( 'download_enable', 0 );
// Try to find post type "Forum Topic" in DB
global $DB;
$forum_topic_type_ID = $DB->get_var( 'SELECT ityp_ID
FROM T_items__type
WHERE ityp_name = "Task"' );
if( $forum_topic_type_ID )
{ // Set default post type as "Forum Topic"
$this->set_setting( 'default_post_type', $forum_topic_type_ID );
}
if( is_pro() )
{ // Enable tracking of unread content only in PRO version:
$this->set_setting( 'track_unread_content', 1 );
}
break;
case 'forum':
$this->set( 'type', 'forum' );
$this->set( 'name', empty($name) ? T_('Forums Title') : $name );
$this->set( 'shortname', empty($shortname) ? T_('Forums') : $shortname );
$this->set( 'urlname', empty($urlname) ? 'forums' : $urlname );
$this->set( 'advanced_perms', 1 );
$this->set_setting( 'post_navigation', 'same_category' );
$this->set_setting( 'allow_comments', 'registered' );
$this->set_setting( 'in_skin_editing', '1' );
$this->set_setting( 'posts_per_page', 30 );
$this->set_setting( 'allow_html_comment', 0 );
$this->set_setting( 'comment_maxlen', '' );
$this->set_setting( 'orderby', 'contents_last_updated_ts' );
$this->set_setting( 'orderdir', 'DESC' );
$this->set_setting( 'enable_goto_blog', 'post' );
$this->set_setting( 'front_disp', 'front' );
$this->set_setting( 'track_unread_content', 1 );
$this->set_setting( 'allow_rating_comment_helpfulness', 1 );
$this->set_setting( 'category_ordering', 'manual' );
$this->set_setting( 'disp_featured_above_list', 1 );
$this->set_setting( 'download_enable', 0 );
// Try to find post type "Forum Topic" in DB
global $DB;
$forum_topic_type_ID = $DB->get_var( 'SELECT ityp_ID
FROM T_items__type
WHERE ityp_name = "Forum Topic"' );
if( $forum_topic_type_ID )
{ // Set default post type as "Forum Topic"
$this->set_setting( 'default_post_type', $forum_topic_type_ID );
}
break;
case 'manual':
$this->set( 'type', 'manual' );
$this->set( 'name', empty($name) ? T_('Manual Title') : $name );
$this->set( 'shortname', empty($shortname) ? T_('Manual') : $shortname );
$this->set( 'urlname', empty($urlname) ? 'manual' : $urlname );
$this->set_setting( 'post_navigation', 'same_category' );
$this->set_setting( 'single_links', 'chapters' );
$this->set_setting( 'enable_goto_blog', 'post' );
$this->set_setting( 'front_disp', 'front' );
$this->set_setting( 'category_ordering', 'manual' );
$this->set_setting( 'main_content', 'excerpt' );
$this->set_setting( 'chapter_content', 'excerpt' );
if( is_pro() )
{ // Enable tracking of unread content only in PRO version:
$this->set_setting( 'track_unread_content', 1 );
}
// Try to find post type "Manual Page" in DB
global $DB;
$manual_page_type_ID = $DB->get_var( 'SELECT ityp_ID
FROM T_items__type
WHERE ityp_name = "Manual Page"' );
if( $manual_page_type_ID )
{ // Set default post type as "Manual Page"
$this->set_setting( 'default_post_type', $manual_page_type_ID );
}
break;
case 'std':
default:
if( $kind != 'std' )
{ // Check if given kind is allowed by system or plugins:
$kinds = get_collection_kinds();
if( ! isset( $kinds[ $kind ] ) )
{ // If unknown kind, restrict this to standard:
$kind = 'std';
}
}
$this->set( 'type', $kind );
$this->set( 'name', empty($name) ? T_('Blog') : $name );
$this->set( 'shortname', empty($shortname) ? T_('Blog') : $shortname );
$this->set( 'urlname', empty($urlname) ? 'blog' : $urlname );
if( is_pro() )
{ // Enable tracking of unread content only in PRO version:
$this->set_setting( 'track_unread_content', 1 );
}
break;
}
if( empty($name) && empty($shortname) && empty($urlname) )
{ // Not in installation mode, init custom collection kinds.
global $Plugins;
// Defines blog settings by its kind.
$Plugins->trigger_event( 'InitCollectionKinds', array(
'Blog' => & $this,
'kind' => & $kind,
) );
}
}
/**
* Load data from Request form fields.
*
* @param array groups of params to load
* @return boolean true if loaded data seems valid.
*/
function load_from_Request( $groups = array() )
{
global $Messages, $default_locale, $DB, $Settings;
/**
* @var User
*/
global $admin_url, $current_User;
$notifications_mode = $Settings->get( 'outbound_notifications_mode' );
// Load collection settings and clear update cascade array
$this->load_CollectionSettings();
if( param( 'blog_name', 'string', NULL ) !== NULL )
{ // General params:
$this->set_setting( 'collection_logo_file_ID', param( 'collection_logo_file_ID', 'integer', NULL ) );
$this->set_setting( 'collection_favicon_file_ID', param( 'collection_favicon_file_ID', 'integer', NULL ) );
$this->set_from_Request( 'name' );
$this->set( 'shortname', param( 'blog_shortname', 'string', true ) );
// Section:
$SectionCache = & get_SectionCache();
$SectionCache->load_available();
if( count( $SectionCache->cache_available ) == 1 )
{ // Use single available section:
foreach( $SectionCache->cache_available as $available_Section )
{
$new_sec_ID = $available_Section->ID;
break;
}
}
else
{ // Get a section from the submitted form:
$new_sec_ID = param( 'sec_ID', 'integer', NULL );
param_string_not_empty( 'sec_ID', T_('Please select a section.') );
}
if( $new_sec_ID != $this->get( 'sec_ID' ) )
{ // If section has been changed to new:
if( ! check_user_perm( 'blogs', 'create', false, $new_sec_ID ) )
{
param_error( 'sec_ID', T_('You don\'t have a permission to create a collection in this section.') );
}
$this->set( 'sec_ID', $new_sec_ID );
}
// Language / locale:
if( param( 'blog_locale', 'string', NULL ) !== NULL )
{ // These settings can be hidden when only one locale is enabled in the system
$this->set_from_Request( 'locale' );
$this->set_setting( 'locale_source', param( 'blog_locale_source', 'string', 'blog' ) );
$this->set_setting( 'post_locale_source', param( 'blog_post_locale_source', 'string', 'post' ) );
$this->set_setting( 'new_item_locale_source', param( 'blog_new_item_locale_source', 'string', 'select_coll' ) );
$extra_locales = param( 'blog_locale_extra', 'array:string', NULL );
$linked_colls = param( 'blog_locale_link_coll', 'array:integer', NULL );
if( $extra_locales !== NULL || $linked_colls !== NULL )
{ // Set new extra locales and linked collections:
$this->set_locales( $extra_locales, $linked_colls );
}
}
// Collection permissions:
$prev_advanced_perms = $this->get( 'advanced_perms' );
$new_advanced_perms = param( 'advanced_perms', 'integer', 0 );
$prev_allow_access = $this->get_setting( 'allow_access' );
$new_allow_access = param( 'blog_allow_access', 'string', '' );
if( get_param( 'action' ) != 'update_confirm' && $this->ID > 0 &&
( $prev_allow_access != $new_allow_access || $prev_advanced_perms != $new_advanced_perms ) )
{ // One of these settings is changing, try to check if max allowed status will be changed too:
$prev_max_allowed_status = $this->get_max_allowed_status();
$prev_access_title = $this->get_access_title();
$this->set( 'advanced_perms', $new_advanced_perms );
$this->set_setting( 'allow_access', $new_allow_access );
$new_max_allowed_status = $this->get_max_allowed_status();
$new_access_title = $this->get_access_title();
$status_orders = get_visibility_statuses( 'ordered-index' );
if( $status_orders[ $new_max_allowed_status ] < $status_orders[ $prev_max_allowed_status ] )
{ // If max allowed status will be reduced after collection updating:
$count_reduced_status_data = $this->get_count_reduced_status_data( $new_max_allowed_status );
if( $count_reduced_status_data !== false )
{ // If some posts or comment will be updated:
$this->confirmation = array();
$this->confirmation['title'] = sprintf( T_('You changed the access setting of this collection from "%s" to "%s". This will also:'), $prev_access_title, $new_access_title );
$status_titles = get_visibility_statuses();
foreach( $count_reduced_status_data['posts'] as $status_key => $count )
{
$this->confirmation['messages'][] = sprintf( T_('change %d posts from "%s" to "%s"'), intval( $count ), $status_titles[ $status_key ], $status_titles[ $new_max_allowed_status ] );
}
foreach( $count_reduced_status_data['comments'] as $status_key => $count )
{
$this->confirmation['messages'][] = sprintf( T_('change %d comments from "%s" to "%s"'), intval( $count ), $status_titles[ $status_key ], $status_titles[ $new_max_allowed_status ] );
}
}
}
}
$this->set( 'advanced_perms', $new_advanced_perms );
$this->set_setting( 'allow_access', $new_allow_access );
if( $prev_allow_access != $this->get_setting( 'allow_access' ) )
{ // If setting "Allow access to" is changed to:
switch( $this->get_setting( 'allow_access' ) )
{ // Automatically enable/disable moderation statuses:
case 'public':
// Enable "Community" and "Members":
$enable_moderation_statuses = array( 'community', 'protected' );
$enable_comment_moderation_statuses = array( 'community', 'protected', 'review', 'draft' );
$disable_comment_moderation_statuses = array( 'private' );
break;
case 'users':
// Disable "Community" and Enable "Members":
$disable_moderation_statuses = array( 'community' );
$enable_moderation_statuses = array( 'protected' );
$enable_comment_moderation_statuses = array( 'protected', 'review', 'draft' );
$disable_comment_moderation_statuses = array( 'community', 'private' );
break;
case 'members':
// Disable "Community" and "Members":
$disable_moderation_statuses = array( 'community', 'protected' );
$enable_comment_moderation_statuses = array( 'review', 'draft' );
$disable_comment_moderation_statuses = array( 'community', 'protected', 'private' );
break;
}
$post_moderation_statuses = $this->get_setting( 'post_moderation_statuses' );
$post_moderation_statuses = empty( $post_moderation_statuses ) ? array() : explode( ',', $post_moderation_statuses );
$comment_moderation_statuses = $this->get_setting( 'moderation_statuses' );
$comment_moderation_statuses = empty( $comment_moderation_statuses ) ? array() : explode( ',', $comment_moderation_statuses );
if( ! empty( $disable_moderation_statuses ) )
{ // Disable moderation statuses:
$post_moderation_statuses = array_diff( $post_moderation_statuses, $disable_moderation_statuses );
$comment_moderation_statuses = array_diff( $comment_moderation_statuses, $disable_moderation_statuses );
}
if( ! empty( $enable_moderation_statuses ) )
{ // Enable moderation statuses:
$post_moderation_statuses = array_unique( array_merge( $enable_moderation_statuses, $post_moderation_statuses ) );
$comment_moderation_statuses = array_unique( array_merge( $enable_moderation_statuses, $comment_moderation_statuses ) );
}
if( ! empty( $disable_comment_moderation_statuses ) )
{
$comment_moderation_statuses = array_diff( $comment_moderation_statuses, $disable_comment_moderation_statuses );
}
if( ! empty( $enable_comment_moderation_statuses ) )
{
$comment_moderation_statuses = array_unique( array_merge( $enable_comment_moderation_statuses, $comment_moderation_statuses ) );
}
$this->set_setting( 'post_moderation_statuses', implode( ',', $post_moderation_statuses ) );
// Force enabled statuses regardless of previous settings
$this->set_setting( 'moderation_statuses', implode( ',', $enable_comment_moderation_statuses ) );
}
if( $this->get_setting( 'allow_access' ) != 'public' )
{ // Disable site maps, feeds and ping plugins for not public collection:
$this->set_setting( 'enable_sitemaps', 0 );
$this->set_setting( 'feed_content', 'none' );
$this->set_setting( 'ping_plugins', '' );
}
// Lists of collections:
$this->set( 'order', param( 'blog_order', 'integer' ) );
if( $this->ID > 0 )
{
$default_in_bloglist = 'public';
}
else
{
switch( $new_allow_access )
{
case 'public':
$default_in_bloglist = 'public';
break;
case 'users':
$default_in_bloglist = 'logged';
break;
case 'members':
$default_in_bloglist = 'member';
break;
default:
$default_in_bloglist = 'never';
}
}
$this->set( 'in_bloglist', param( 'blog_in_bloglist', 'string' ), $default_in_bloglist );
}
if( param( 'archive_links', 'string', NULL ) !== NULL )
{ // Archive link type:
$this->set_setting( 'archive_links', get_param( 'archive_links' ) );
}
if( param( 'archive_posts_per_page', 'integer', NULL ) !== NULL )
{ // Archive posts per page:
$this->set_setting( 'archive_posts_per_page', get_param( 'archive_posts_per_page' ) );
}
if( param( 'chapter_links', 'string', NULL ) !== NULL )
{ // Chapter link type:
$this->set_setting( 'chapter_links', get_param( 'chapter_links' ) );
}
if( param( 'category_prefix', 'string', NULL) !== NULL )
{
$category_prefix = get_param( 'category_prefix' );
if( ! preg_match( '|^([A-Za-z0-9\-_]+(/[A-Za-z0-9\-_]+)*)?$|', $category_prefix) )
{
param_error( 'category_prefix', T_('Invalid category prefix.') );
}
$this->set_setting( 'category_prefix', $category_prefix);
}
if( param( 'atom_redirect', 'url', NULL ) !== NULL )
{
param_check_url( 'atom_redirect', 'commenting' );
$this->set_setting( 'atom_redirect', get_param( 'atom_redirect' ) );
param( 'rss2_redirect', 'url', NULL );
param_check_url( 'rss2_redirect', 'commenting' );
$this->set_setting( 'rss2_redirect', get_param( 'rss2_redirect' ) );
}
if( in_array( 'template', $groups ) )
{
$this->set_setting( 'allow_duplicate', param( 'blog_allow_duplicate', 'integer', 0 ) );
}
if( in_array( 'metadata', $groups ) )
{
// Social media boilerplate
$this->set_setting( 'social_media_image_file_ID', param( 'social_media_image_file_ID', 'integer', NULL ) );
if( param( 'blog_shortdesc', 'string', NULL ) !== NULL )
{ // Description:
$this->set_from_Request( 'shortdesc' );
}
if( param( 'blog_longdesc', 'html', NULL ) !== NULL )
{ // HTML long description:
param_check_html( 'blog_longdesc', T_('Invalid long description') );
$this->set( 'longdesc', get_param( 'blog_longdesc' ) );
}
if( param( 'blog_keywords', 'string', NULL ) !== NULL )
{ // Keywords:
$this->set_from_Request( 'keywords' );
}
// Publisher logo:
$this->set_setting( 'publisher_logo_file_ID', param( 'blog_publisher_logo_file_ID', 'integer' ) );
if( param( 'blog_publisher_name', 'string', NULL ) !== NULL )
{ // Publisher name:
$this->set_setting( 'publisher_name', get_param( 'blog_publisher_name' ) );
}
if( param( 'blog_footer_text', 'html', NULL ) !== NULL )
{ // Blog footer:
param_check_html( 'blog_footer_text', T_('Invalid blog footer') );
$this->set_setting( 'blog_footer_text', get_param( 'blog_footer_text' ) );
}
if( param( 'single_item_footer_text', 'html', NULL ) !== NULL )
{ // Blog footer:
param_check_html( 'single_item_footer_text', T_('Invalid single post footer') );
$this->set_setting( 'single_item_footer_text', get_param( 'single_item_footer_text' ) );
}
if( param( 'xml_item_footer_text', 'html', NULL ) !== NULL )
{ // Blog footer:
param_check_html( 'xml_item_footer_text', T_('Invalid RSS footer') );
$this->set_setting( 'xml_item_footer_text', get_param( 'xml_item_footer_text' ) );
}
}
if( param( 'image_size', 'string', NULL ) !== NULL )
{
$this->set_setting( 'image_size', get_param( 'image_size' ));
}
if( param( 'tag_links', 'string', NULL ) !== NULL )
{ // Tag page link type:
$this->set_setting( 'tag_links', get_param( 'tag_links' ) );
}
if( param( 'tag_prefix', 'string', NULL) !== NULL )
{
$tag_prefix = get_param( 'tag_prefix' );
if( ! preg_match( '|^([A-Za-z0-9\-_]+(/[A-Za-z0-9\-_]+)*)?$|', $tag_prefix) )
{
param_error( 'tag_prefix', T_('Invalid tag prefix.') );
}
$this->set_setting( 'tag_prefix', $tag_prefix);
}
// Default to "tag", if "prefix-only" is used, but no tag_prefix was provided.
if( get_param('tag_links') == 'prefix-only' && ! strlen(param( 'tag_prefix', 'string', NULL)) )
{
$this->set_setting( 'tag_prefix', 'tag' );
}
// Use rel="tag" attribute? (checkbox)
$this->set_setting( 'tag_rel_attib', param('tag_rel_attib', 'integer', 0) );
if( param( 'chapter_content', 'string', NULL ) !== NULL )
{ // What kind of content on chapter pages?
$this->set_setting( 'chapter_content', get_param( 'chapter_content' ) );
}
if( param( 'tag_content', 'string', NULL ) !== NULL )
{ // What kind of content on tags pages?
$this->set_setting( 'tag_content', get_param( 'tag_content' ) );
}
if( param( 'archive_content', 'string', NULL ) !== NULL )
{ // What kind of content on archive pages?
$this->set_setting( 'archive_content', get_param( 'archive_content' ) );
}
if( param( 'filtered_content', 'string', NULL ) !== NULL )
{ // What kind of content on filtered pages?
$this->set_setting( 'filtered_content', get_param( 'filtered_content' ) );
}
if( param( 'main_content', 'string', NULL ) !== NULL )
{ // What kind of content on main pages?
$this->set_setting( 'main_content', get_param( 'main_content' ) );
}
// Chapter posts per page:
$this->set_setting( 'chapter_posts_per_page', param( 'chapter_posts_per_page', 'integer', NULL ), true );
// Tag posts per page:
$this->set_setting( 'tag_posts_per_page', param( 'tag_posts_per_page', 'integer', NULL ), true );
if( param( 'user_prefix', 'string', NULL ) !== NULL )
{ // User profile page prefix:
param_check_regexp( 'user_prefix', '#^[a-z0-9\-_]*$#i', sprintf( T_('User profile page prefix can contain only letters, digits, %s or %s.'), '<code>-</code>', '<code>_</code>' ) );
$this->set_setting( 'user_prefix', get_param( 'user_prefix' ) );
}
if( param( 'user_links', 'string', NULL ) !== NULL )
{ // User profile URLs:
$this->set_setting( 'user_links', get_param( 'user_links' ) );
}
if( param( 'single_links', 'string', NULL ) !== NULL )
{ // Single post link type:
$this->set_setting( 'single_links', get_param( 'single_links' ) );
}
if( param( 'slug_limit', 'integer', NULL ) !== NULL )
{ // Limit slug length:
$this->set_setting( 'slug_limit', get_param( 'slug_limit' ) );
}
if( param( 'normal_skin_ID', 'integer', NULL ) !== NULL )
{ // Normal skin ID:
$updated_skin_type = 'normal';
$updated_skin_ID = get_param( 'normal_skin_ID' );
$this->set( 'normal_skin_ID', $updated_skin_ID );
}
if( param( 'mobile_skin_ID', 'integer', NULL ) !== NULL )
{ // Mobile skin ID:
$updated_skin_type = 'mobile';
$updated_skin_ID = get_param( 'mobile_skin_ID' );
if( $updated_skin_ID == 0 )
{ // Don't store this empty setting in DB
$this->set( 'mobile_skin_ID', NULL );
}
else
{ // Set mobile skin
$this->set( 'mobile_skin_ID', $updated_skin_ID );
}
}
if( param( 'tablet_skin_ID', 'integer', NULL ) !== NULL )
{ // Tablet skin ID:
$updated_skin_type = 'tablet';
$updated_skin_ID = get_param( 'tablet_skin_ID' );
if( $updated_skin_ID == 0 )
{ // Don't store this empty setting in DB
$this->set( 'tablet_skin_ID', NULL );
}
else
{ // Set tablet skin
$this->set( 'tablet_skin_ID', $updated_skin_ID );
}
}
if( param( 'alt_skin_ID', 'integer', NULL ) !== NULL )
{ // Alt skin ID:
$updated_skin_type = 'alt';
$updated_skin_ID = get_param( 'alt_skin_ID' );
if( $updated_skin_ID == 0 )
{ // Don't store this empty setting in DB
$this->set( 'alt_skin_ID', NULL );
}
else
{ // Set alt skin
$this->set( 'alt_skin_ID', $updated_skin_ID );
}
}
if( ! empty( $updated_skin_ID ) )
{
load_funcs( 'skins/_skin.funcs.php' );
if( ! skin_check_compatibility( $updated_skin_ID, 'coll' ) )
{ // Redirect to admin skins page selector if the skin cannot be selected:
$Messages->add( T_('This skin cannot be used as a collection skin.'), 'error' );
}
}
if( param( 'archives_sort_order', 'string', NULL ) !== NULL )
{ // Archive sorting
$this->set_setting( 'archives_sort_order', param( 'archives_sort_order', 'string', false ) );
}
if( param( 'download_delay', 'integer', NULL ) !== NULL )
{ // Enable Download pages:
$this->set_setting( 'download_enable', param( 'download_enable', 'integer', 0 ) );
// Download delay
param_check_range( 'download_delay', 0, 10, T_('Download delay must be numeric (0-10).') );
$this->set_setting( 'download_delay', get_param( 'download_delay' ) );
}
if( param( 'feed_content', 'string', NULL ) !== NULL )
{ // How much content in feeds?
$this->set_setting( 'feed_content', get_param( 'feed_content' ) );
param_integer_range( 'posts_per_feed', 1, 9999, T_('Items per feed must be between %d and %d.') );
$this->set_setting( 'posts_per_feed', get_param( 'posts_per_feed' ) );
}
if( param( 'comment_feed_content', 'string', NULL ) !== NULL )
{ // How much content in comment feeds?
$this->set_setting( 'comment_feed_content', get_param( 'comment_feed_content' ) );
param_integer_range( 'comments_per_feed', 1, 9999, T_('Comments per feed must be between %d and %d.') );
$this->set_setting( 'comments_per_feed', get_param( 'comments_per_feed' ) );
}
if( param( 'blog_tagline', 'string', NULL ) !== NULL )
{ // tagline:
$this->set( 'tagline', get_param( 'blog_tagline' ) );
}
if( param( 'blog_notes', 'html', NULL ) !== NULL )
{ // HTML notes:
param_check_html( 'blog_notes', T_('Invalid Blog Notes') );
$this->set( 'notes', get_param( 'blog_notes' ) );
}
if( in_array( 'pings', $groups ) )
{ // we want to load the ping checkboxes:
$blog_ping_plugins = param( 'blog_ping_plugins', 'array:string', array() );
$this->set_setting( 'ping_plugins', implode( ',', array_unique( $blog_ping_plugins ) ) );
}
if( in_array( 'home', $groups ) )
{ // we want to load the front page params:
$front_disp = param( 'front_disp', 'string', '' );
$this->set_setting( 'front_disp', $front_disp );
if( $front_disp == 'mustread' && ! is_pro() )
{ // Don't allow to store not supported front page:
$Messages->add( T_('"Must Read" is supported only on b2evolution PRO.'), 'error' );
}
$front_post_ID = param( 'front_post_ID', 'integer', 0 );
if( $front_disp == 'page' )
{ // Post ID must be required
param_check_not_empty( 'front_post_ID', T_('Please enter a specific post ID') );
}
$this->set_setting( 'front_post_ID', $front_post_ID );
}
if( in_array( 'features', $groups ) )
{ // we want to load the posts related features:
$this->set_setting( 'use_workflow', param( 'blog_use_workflow', 'integer', 0 ) );
if( get_param( 'blog_use_workflow' ) )
{ // Update deadline setting only when workflow is enabled:
$this->set_setting( 'use_deadline', param( 'blog_use_deadline', 'integer', 0 ) );
}
$this->set_setting( 'enable_goto_blog', param( 'enable_goto_blog', 'string', NULL ) );
$this->set_setting( 'editing_goto_blog', param( 'editing_goto_blog', 'string', NULL ) );
$this->set_setting( 'post_anonymous', param( 'post_anonymous', 'integer', 0 ) );
$this->set_setting( 'default_post_status', param( 'default_post_status', 'string', NULL ) );
$this->set_setting( 'default_post_status_anon', param( 'default_post_status_anon', 'string', NULL ) );
param( 'old_content_alert', 'integer', NULL );
param_check_range( 'old_content_alert', 1, 12, T_('Stale content alert must be configured with a number of months.').'(1 - 12)', false );
$this->set_setting( 'old_content_alert', get_param( 'old_content_alert' ), true );
$this->set_setting( 'post_categories', param( 'post_categories', 'string', NULL ) );
if( check_user_perm( 'blog_admin', 'edit', false, $this->ID ) )
{ // We have permission to edit advanced admin settings:
$this->set_setting( 'in_skin_editing', param( 'in_skin_editing', 'integer', 0 ) );
if( $this->get_setting( 'in_skin_editing' ) )
{ // Only when in-skin editing in enabled
$this->set_setting( 'in_skin_editing_renderers', param( 'in_skin_editing_renderers', 'integer', 0 ) );
}
}
if( $this->get_setting( 'in_skin_editing' ) )
{ // Only when in-skin editing in enabled
$this->set_setting( 'in_skin_editing_category', param( 'in_skin_editing_category', 'integer', 0 ) );
$this->set_setting( 'in_skin_editing_category_order', param( 'in_skin_editing_category_order', 'integer', 0 ) );
}
$this->set_setting( 'post_navigation', param( 'post_navigation', 'string', NULL ) );
// Show x days or x posts?:
$this->set_setting( 'what_to_show', param( 'what_to_show', 'string', '' ) );
param_integer_range( 'posts_per_page', 1, 9999, T_('Items/days per page must be between %d and %d.') );
$this->set_setting( 'posts_per_page', get_param( 'posts_per_page' ) );
$this->set_setting( 'orderby', param( 'orderby', 'string', true ) );
$this->set_setting( 'orderdir', param( 'orderdir', 'string', true ) );
// Set additional order fields
$orderby_1 = param( 'orderby_1', 'string', '' );
if( empty( $orderby_1 ) )
{ // Delete if first additional field is not defined
$this->delete_setting( 'orderby_1' );
$this->delete_setting( 'orderdir_1' );
$this->delete_setting( 'orderby_2' );
$this->delete_setting( 'orderdir_2' );
}
else
{
$this->set_setting( 'orderby_1', $orderby_1 );
$this->set_setting( 'orderdir_1', param( 'orderdir_1', 'string', '' ) );
$this->set_setting( 'orderby_2', param( 'orderby_2', 'string', '' ) );
$this->set_setting( 'orderdir_2', param( 'orderdir_2', 'string', '' ) );
}
$postlist_enable = param( 'postlist_enable', 'integer', 0 );
$this->set_setting( 'postlist_enable', $postlist_enable );
$disp_featured_above_list = param( 'disp_featured_above_list', 'integer', 0 );
$this->set_setting( 'disp_featured_above_list', $disp_featured_above_list );
// Show post types:
$checked_item_types = param( 'show_post_types', 'array:integer', array() );
$unchecked_item_types = array_diff( $this->get_enabled_item_types( 'post' ), $checked_item_types );
// Store only unchecked item types in order to keep all new item types enabled by default:
$this->set_setting( 'show_post_types', implode( ',', $unchecked_item_types ) );
// Front office statuses
$this->load_inskin_statuses( 'post' );
// Time frame
$this->set_setting( 'timestamp_min', param( 'timestamp_min', 'string', '' ) );
$this->set_setting( 'timestamp_min_duration', param_duration( 'timestamp_min_duration' ) );
$this->set_setting( 'timestamp_max', param( 'timestamp_max', 'string', '' ) );
$this->set_setting( 'timestamp_max_duration', param_duration( 'timestamp_max_duration' ) );
// call modules update_collection_features on this blog
modules_call_method( 'update_collection_features', array( 'edited_Blog' => & $this ) );
// load post moderation statuses
$moderation_statuses = get_visibility_statuses( 'moderation' );
$post_moderation_statuses = array();
foreach( $moderation_statuses as $status )
{
if( param( 'post_notif_'.$status, 'integer', 0 ) )
{
$post_moderation_statuses[] = $status;
}
}
$this->set_setting( 'post_moderation_statuses', implode( ',', $post_moderation_statuses ) );
// If notifications are temporarily disabled, no subscription options should be lost when user saves.
// When notification are turned back on, the subscriptions will resume as they were before.
if( $notifications_mode != 'off' )
{
// Subscriptions:
$this->set_setting( 'allow_subscriptions', param( 'allow_subscriptions', 'integer', 0 ) );
$this->set_setting( 'allow_item_subscriptions', param( 'allow_item_subscriptions', 'integer', 0 ) );
$this->set_setting( 'allow_item_mod_subscriptions', param( 'allow_item_mod_subscriptions', 'integer', 0 ) );
}
// Voting options:
$this->set_setting( 'voting_positive', param( 'voting_positive', 'integer', 0 ) );
$this->set_setting( 'voting_neutral', param( 'voting_neutral', 'integer', 0 ) );
$this->set_setting( 'voting_negative', param( 'voting_negative', 'integer', 0 ) );
}
if( in_array( 'comments', $groups ) )
{ // we want to load the comments settings:
// load moderation statuses
$moderation_statuses = get_visibility_statuses( 'moderation' );
$blog_moderation_statuses = array();
foreach( $moderation_statuses as $status )
{
if( param( 'notif_'.$status, 'integer', 0 ) )
{
$blog_moderation_statuses[] = $status;
}
}
$this->set_setting( 'moderation_statuses', implode( ',', $blog_moderation_statuses ) );
$this->set_setting( 'comment_quick_moderation', param( 'comment_quick_moderation', 'string', 'expire' ) );
// If notifications are temporarily disabled, no subscription options should be lost when user saves.
// When notification are turned back on, the subscriptions will resume as they were before.
if( $notifications_mode != 'off' )
{
// Subscriptions:
$this->set_setting( 'allow_comment_subscriptions', param( 'allow_comment_subscriptions', 'integer', 0 ) );
$this->set_setting( 'allow_item_subscriptions', param( 'allow_item_subscriptions', 'integer', 0 ) );
$this->set_setting( 'allow_anon_subscriptions', param( 'allow_anon_subscriptions', 'integer', 0 ) );
$this->set_setting( 'default_anon_comment_notify', param( 'default_anon_comment_notify', 'integer', 0 ) );
$this->set_setting( 'anon_notification_email_limit', param( 'anon_notification_email_limit', 'integer', 0 ) );
}
$this->set_setting( 'comments_detect_email', param( 'comments_detect_email', 'integer', 0 ) );
$this->set_setting( 'comments_register', param( 'comments_register', 'integer', 0 ) );
$this->set_setting( 'meta_comments_frontoffice', param( 'meta_comments_frontoffice', 'integer', 0 ) );
}
if( in_array( 'contact', $groups ) )
{ // we want to load the contact form settings:
$this->set_setting( 'msgform_title', param( 'msgform_title', 'string' ) );
$this->set_setting( 'msgform_display_recipient', param( 'msgform_display_recipient', 'integer', 0 ) );
$this->set_setting( 'msgform_recipient_label', param( 'msgform_recipient_label', 'string' ) );
$this->set_setting( 'msgform_display_avatar', param( 'msgform_display_avatar', 'integer', 0 ) );
$this->set_setting( 'msgform_avatar_size', param( 'msgform_avatar_size', 'string' ) );
$this->set_setting( 'msgform_user_name', param( 'msgform_user_name', 'string' ) );
$this->set_setting( 'msgform_require_name', param( 'msgform_require_name', 'integer', 0 ) );
$this->set_setting( 'msgform_subject_list', param( 'msgform_subject_list', 'text' ) );
$this->set_setting( 'msgform_display_subject', param( 'msgform_display_subject', 'integer', 0 ) );
$this->set_setting( 'msgform_require_subject', param( 'msgform_require_subject', 'integer', 0 ) );
$msgform_additional_fields = param( 'msgform_additional_fields', 'array:integer', array() );
$this->set_setting( 'msgform_additional_fields', implode( ',', $msgform_additional_fields ) );
$this->set_setting( 'msgform_contact_method', param( 'msgform_contact_method', 'integer', 0 ) );
$this->set_setting( 'msgform_display_message', param( 'msgform_display_message', 'integer', 0 ) );
if( get_param( 'msgform_display_message' ) )
{ // Update these two fields only if message is allowed:
$this->set_setting( 'msgform_require_message', param( 'msgform_require_message', 'integer', 0 ) );
$this->set_setting( 'msgform_message_label', param( 'msgform_message_label', 'string' ) );
}
}
if( in_array( 'userdir', $groups ) )
{ // we want to load the user directory settings:
$this->set_setting( 'userdir_enable', param( 'userdir_enable', 'integer', 0 ) );
$this->set_setting( 'userdir_filter_restrict_to_members', param( 'userdir_filter_restrict_to_members', 'integer', 0 ) );
$this->set_setting( 'userdir_filter_name', param( 'userdir_filter_name', 'integer', 0 ) );
$this->set_setting( 'userdir_filter_email', param( 'userdir_filter_email', 'integer', 0 ) );
$this->set_setting( 'userdir_filter_country', param( 'userdir_filter_country', 'integer', 0 ) );
$this->set_setting( 'userdir_filter_region', param( 'userdir_filter_region', 'integer', 0 ) );
$this->set_setting( 'userdir_filter_subregion', param( 'userdir_filter_subregion', 'integer', 0 ) );
$this->set_setting( 'userdir_filter_city', param( 'userdir_filter_city', 'integer', 0 ) );
$this->set_setting( 'userdir_filter_age_group', param( 'userdir_filter_age_group', 'integer', 0 ) );
$this->set_setting( 'userdir_picture', param( 'userdir_picture', 'integer', 0 ) );
$this->set_setting( 'image_size_user_list', param( 'image_size_user_list', 'string' ) );
$this->set_setting( 'userdir_login', param( 'userdir_login', 'integer', 0 ) );
$this->set_setting( 'userdir_firstname', param( 'userdir_firstname', 'integer', 0 ) );
$this->set_setting( 'userdir_lastname', param( 'userdir_lastname', 'integer', 0 ) );
$this->set_setting( 'userdir_nickname', param( 'userdir_nickname', 'integer', 0 ) );
$this->set_setting( 'userdir_fullname', param( 'userdir_fullname', 'integer', 0 ) );
$this->set_setting( 'userdir_country', param( 'userdir_country', 'integer', 0 ) );
$this->set_setting( 'userdir_country_type', param( 'userdir_country_type', 'string' ) );
$this->set_setting( 'userdir_region', param( 'userdir_region', 'integer', 0 ) );
$this->set_setting( 'userdir_subregion', param( 'userdir_subregion', 'integer', 0 ) );
$this->set_setting( 'userdir_city', param( 'userdir_city', 'integer', 0 ) );
$this->set_setting( 'userdir_phone', param( 'userdir_phone', 'integer', 0 ) );
$this->set_setting( 'userdir_soclinks', param( 'userdir_soclinks', 'integer', 0 ) );
$this->set_setting( 'userdir_lastseen', param( 'userdir_lastseen', 'integer', 0 ) );
$this->set_setting( 'userdir_lastseen_view', param( 'userdir_lastseen_view', 'string' ) );
$this->set_setting( 'userdir_lastseen_cheat', param( 'userdir_lastseen_cheat', 'integer', 0 ) );
}
if( in_array( 'search', $groups ) )
{ // we want to load the search settings:
// Search results:
param_integer_range( 'search_per_page', 1, 9999, T_('Number of search results per page must be between %d and %d.') );
$this->set_setting( 'search_enable', param( 'search_enable', 'integer', 0 ) );
$this->set_setting( 'search_per_page', get_param( 'search_per_page' ) );
$this->set_setting( 'search_sort_by', param( 'search_sort_by', 'string' ) );
$this->set_setting( 'search_include_cats', param( 'search_include_cats', 'integer', 0 ) );
$this->set_setting( 'search_include_posts', param( 'search_include_posts', 'integer', 0 ) );
$this->set_setting( 'search_include_cmnts', param( 'search_include_cmnts', 'integer', 0 ) );
$this->set_setting( 'search_include_metas', param( 'search_include_metas', 'integer', 0 ) );
$this->set_setting( 'search_include_tags', param( 'search_include_tags', 'integer', 0 ) );
$this->set_setting( 'search_include_files', param( 'search_include_files', 'integer', 0 ) );
// Scoring for posts:
$this->set_setting( 'search_score_post_title', param( 'search_score_post_title', 'integer', 0 ) );
$this->set_setting( 'search_score_post_content', param( 'search_score_post_content', 'integer', 0 ) );
$this->set_setting( 'search_score_post_tags', param( 'search_score_post_tags', 'integer', 0 ) );
$this->set_setting( 'search_score_post_excerpt', param( 'search_score_post_excerpt', 'integer', 0 ) );
$this->set_setting( 'search_score_post_titletag', param( 'search_score_post_titletag', 'integer', 0 ) );
$this->set_setting( 'search_score_post_metakeywords', param( 'search_score_post_metakeywords', 'integer', 0 ) );
$this->set_setting( 'search_score_post_author', param( 'search_score_post_author', 'integer', 0 ) );
$this->set_setting( 'search_score_post_date_future', param( 'search_score_post_date_future', 'integer', 0 ) );
$this->set_setting( 'search_score_post_date_moremonth', param( 'search_score_post_date_moremonth', 'integer', 0 ) );
$this->set_setting( 'search_score_post_date_lastmonth', param( 'search_score_post_date_lastmonth', 'integer', 0 ) );
$this->set_setting( 'search_score_post_date_twoweeks', param( 'search_score_post_date_twoweeks', 'integer', 0 ) );
$this->set_setting( 'search_score_post_date_lastweek', param( 'search_score_post_date_lastweek', 'integer', 0 ) );
// Scoring for comments:
$this->set_setting( 'search_score_cmnt_post_title', param( 'search_score_cmnt_post_title', 'integer', 0 ) );
$this->set_setting( 'search_score_cmnt_content', param( 'search_score_cmnt_content', 'integer', 0 ) );
$this->set_setting( 'search_score_cmnt_author', param( 'search_score_cmnt_author', 'integer', 0 ) );
$this->set_setting( 'search_score_cmnt_date_future', param( 'search_score_cmnt_date_future', 'integer', 0 ) );
$this->set_setting( 'search_score_cmnt_date_moremonth', param( 'search_score_cmnt_date_moremonth', 'integer', 0 ) );
$this->set_setting( 'search_score_cmnt_date_lastmonth', param( 'search_score_cmnt_date_lastmonth', 'integer', 0 ) );
$this->set_setting( 'search_score_cmnt_date_twoweeks', param( 'search_score_cmnt_date_twoweeks', 'integer', 0 ) );
$this->set_setting( 'search_score_cmnt_date_lastweek', param( 'search_score_cmnt_date_lastweek', 'integer', 0 ) );
// Scoring for files:
$this->set_setting( 'search_score_file_name', param( 'search_score_file_name', 'integer', 0 ) );
$this->set_setting( 'search_score_file_path', param( 'search_score_file_path', 'integer', 0 ) );
$this->set_setting( 'search_score_file_title', param( 'search_score_file_title', 'integer', 0 ) );
$this->set_setting( 'search_score_file_alt', param( 'search_score_file_alt', 'integer', 0 ) );
$this->set_setting( 'search_score_file_description', param( 'search_score_file_description', 'integer', 0 ) );
// Scoring for categories:
$this->set_setting( 'search_score_cat_name', param( 'search_score_cat_name', 'integer', 0 ) );
$this->set_setting( 'search_score_cat_desc', param( 'search_score_cat_desc', 'integer', 0 ) );
// Scoring for tags:
$this->set_setting( 'search_score_tag_name', param( 'search_score_tag_name', 'integer', 0 ) );
// Quick Templates for search results:
$this->set_setting( 'search_result_template_item', param( 'search_result_template_item', 'string' ) );
$this->set_setting( 'search_result_template_comment', param( 'search_result_template_comment', 'string' ) );
$this->set_setting( 'search_result_template_meta', param( 'search_result_template_meta', 'string' ) );
$this->set_setting( 'search_result_template_file', param( 'search_result_template_file', 'string' ) );
$this->set_setting( 'search_result_template_category', param( 'search_result_template_category', 'string' ) );
$this->set_setting( 'search_result_template_tag', param( 'search_result_template_tag', 'string' ) );
}
if( in_array( 'other', $groups ) )
{ // we want to load the other settings:
// Latest comments :
param_integer_range( 'latest_comments_num', 1, 9999, T_('Number of shown comments must be between %d and %d.') );
$this->set_setting( 'latest_comments_num', get_param( 'latest_comments_num' ) );
// Messaging pages:
$this->set_setting( 'image_size_messaging', param( 'image_size_messaging', 'string' ) );
// Archive pages:
$this->set_setting( 'archive_mode', param( 'archive_mode', 'string', true ) );
}
if( in_array( 'popup', $groups ) )
{ // we want to load the popups settings:
// Marketing Popup:
$this->set_setting( 'marketing_popup_using', param( 'marketing_popup_using', 'string' ) );
$this->set_setting( 'marketing_popup_animation', param( 'marketing_popup_animation', 'string' ) );
$container_disps = array( 'front', 'posts', 'single', 'page', 'catdir' );
foreach( $container_disps as $container_disp )
{
$this->set_setting( 'marketing_popup_container_'.$container_disp, param( 'marketing_popup_container_'.$container_disp, 'string' ) );
}
$this->set_setting( 'marketing_popup_container_other_disps', param( 'marketing_popup_container_other_disps', 'string' ) );
$this->set_setting( 'marketing_popup_show_repeat', param( 'marketing_popup_show_repeat', 'integer', 0 ) );
$this->set_setting( 'marketing_popup_show_frequency', param( 'marketing_popup_show_frequency', 'string' ) );
$this->set_setting( 'marketing_popup_show_period_val', param( 'marketing_popup_show_period_val', 'integer', NULL ), true );
$this->set_setting( 'marketing_popup_show_period_unit', param( 'marketing_popup_show_period_unit', 'string' ) );
}
if( in_array( 'more', $groups ) )
{ // we want to load more settings:
// Tracking:
$this->set_setting( 'track_unread_content', param( 'track_unread_content', 'integer', 0 ) );
// If notifications are temporarily disabled, no subscription options should be lost when user saves.
// When notification are turned back on, the subscriptions will resume as they were before.
if( $notifications_mode != 'off' )
{
// Subscriptions:
$this->set_setting( 'allow_subscriptions', param( 'allow_subscriptions', 'integer', 0 ) );
$this->set_setting( 'opt_out_subscription', param( 'opt_out_subscription', 'integer', 0 ) );
$this->set_setting( 'allow_comment_subscriptions', param( 'allow_comment_subscriptions', 'integer', 0 ) );
$this->set_setting( 'opt_out_comment_subscription', param( 'opt_out_comment_subscription', 'integer', 0 ) );
$this->set_setting( 'allow_item_subscriptions', param( 'allow_item_subscriptions', 'integer', 0 ) );
$this->set_setting( 'opt_out_item_subscription', param( 'opt_out_item_subscription', 'integer', 0 ) );
$this->set_setting( 'allow_item_mod_subscriptions', param( 'allow_item_mod_subscriptions', 'integer', 0 ) );
$this->set_setting( 'opt_out_item_mod_subscription', param( 'opt_out_item_mod_subscription', 'integer', 0 ) );
}
// Sitemaps:
$this->set_setting( 'enable_sitemaps', param( 'enable_sitemaps', 'integer', 0 ) );
}
if( param( 'allow_comments', 'string', NULL ) !== NULL )
{ // Feedback options:
$this->set_setting( 'allow_comments', param( 'allow_comments', 'string', 'any' ) );
$this->set_setting( 'allow_view_comments', param( 'allow_view_comments', 'string', 'any' ) );
$new_feedback_status = param( 'new_feedback_status', 'string', 'draft' );
if( $new_feedback_status != $this->get_setting( 'new_feedback_status' ) && ( $new_feedback_status != 'published' || check_user_perm( 'blog_admin', 'edit', false, $this->ID ) ) )
{ // Only admin can set this setting to 'Public'
$this->set_setting( 'new_feedback_status', $new_feedback_status );
}
$this->set_setting( 'comment_form_msg', param( 'comment_form_msg', 'text' ) );
$this->set_setting( 'require_anon_name', param( 'require_anon_name', 'string', '0' ) );
$this->set_setting( 'require_anon_email', param( 'require_anon_email', 'string', '0' ) );
$this->set_setting( 'allow_anon_url', param( 'allow_anon_url', 'string', '0' ) );
$this->set_setting( 'comment_maxlen', param( 'comment_maxlen', 'integer', '' ) );
$this->set_setting( 'allow_html_comment', param( 'allow_html_comment', 'string', '0' ) );
$this->set_setting( 'allow_attachments', param( 'allow_attachments', 'string', 'registered' ) );
$this->set_setting( 'max_attachments', param( 'max_attachments', 'integer', '' ) );
$this->set_setting( 'autocomplete_usernames', param( 'autocomplete_usernames', 'integer', '' ) );
$this->set_setting( 'display_rating_summary', param( 'display_rating_summary', 'string', '0' ) );
$this->set_setting( 'allow_rating_items', param( 'allow_rating_items', 'string', 'never' ) );
$this->set_setting( 'rating_question', param( 'rating_question', 'text' ) );
$this->set_setting( 'allow_rating_comment_helpfulness', param( 'allow_rating_comment_helpfulness', 'string', '0' ) );
$blog_allowtrackbacks = param( 'blog_allowtrackbacks', 'integer', 0 );
if( $blog_allowtrackbacks != $this->get( 'allowtrackbacks' ) && ( $blog_allowtrackbacks == 0 || check_user_perm( 'blog_admin', 'edit', false, $this->ID ) ) )
{ // Only admin can turn ON this setting
$this->set( 'allowtrackbacks', $blog_allowtrackbacks );
}
$blog_webmentions = param( 'blog_webmentions', 'integer', 0 );
if( $blog_webmentions != $this->get_setting( 'webmentions' ) && ( $blog_webmentions == 0 || check_user_perm( 'blog_admin', 'edit', false, $this->ID ) ) )
{ // Only admin can turn ON this setting
$this->set_setting( 'webmentions', $blog_webmentions );
}
$this->set_setting( 'comments_orderdir', param( 'comments_orderdir', '/^(?:ASC|DESC)$/', 'ASC' ) );
// call modules update_collection_comments on this blog
modules_call_method( 'update_collection_comments', array( 'edited_Blog' => & $this ) );
$threaded_comments = param( 'threaded_comments', 'integer', 0 );
$this->set_setting( 'threaded_comments', $threaded_comments );
$this->set_setting( 'paged_comments', $threaded_comments ? 0 : param( 'paged_comments', 'integer', 0 ) );
param_integer_range( 'comments_per_page', 1, 9999, T_('Comments per page must be between %d and %d.') );
$this->set_setting( 'comments_per_page', get_param( 'comments_per_page' ) );
$this->set_setting( 'comments_avatars', param( 'comments_avatars', 'integer', 0 ) );
$this->set_setting( 'comments_latest', param( 'comments_latest', 'integer', 0 ) );
// load blog front office comment statuses
$this->load_inskin_statuses( 'comment' );
}
if( in_array( 'seo', $groups ) )
{ // we want to load the workflow checkboxes:
$this->set_setting( 'canonical_homepage', param( 'canonical_homepage', 'integer', 0 ) );
$this->set_setting( 'self_canonical_homepage', param( 'self_canonical_homepage', 'integer', 0 ) );
$this->set_setting( 'relcanonical_homepage', param( 'relcanonical_homepage', 'integer', 0 ) );
$this->set_setting( 'canonical_posts', param( 'canonical_posts', 'integer', 0 ) );
$this->set_setting( 'self_canonical_posts', param( 'self_canonical_posts', 'integer', 0 ) );
$this->set_setting( 'relcanonical_posts', param( 'relcanonical_posts', 'integer', 0 ) );
$this->set_setting( 'canonical_item_urls', param( 'canonical_item_urls', 'integer', 0 ) );
if( ! $this->get_setting( 'canonical_item_urls' ) )
{ // When "301 redirect to canonical URL" is disabled then we always must NOT do 301 redirect cross-posted Items:
$this->set_setting( 'allow_crosspost_urls', 1 );
}
else
{
$this->set_setting( 'allow_crosspost_urls', param( 'allow_crosspost_urls', 'integer', 0 ) );
}
$this->set_setting( 'self_canonical_item_urls', param( 'self_canonical_item_urls', 'integer', 0 ) );
$this->set_setting( 'relcanonical_item_urls', param( 'relcanonical_item_urls', 'integer', 0 ) );
$this->set_setting( 'canonical_archive_urls', param( 'canonical_archive_urls', 'integer', 0 ) );
$this->set_setting( 'self_canonical_archive_urls', param( 'self_canonical_archive_urls', 'integer', 0 ) );
$this->set_setting( 'relcanonical_archive_urls', param( 'relcanonical_archive_urls', 'integer', 0 ) );
$this->set_setting( 'canonical_cat_urls', param( 'canonical_cat_urls', 'integer', 0 ) );
$this->set_setting( 'self_canonical_cat_urls', param( 'self_canonical_cat_urls', 'integer', 0 ) );
$this->set_setting( 'relcanonical_cat_urls', param( 'relcanonical_cat_urls', 'integer', 0 ) );
$this->set_setting( 'canonical_tag_urls', param( 'canonical_tag_urls', 'integer', 0 ) );
$this->set_setting( 'self_canonical_tag_urls', param( 'self_canonical_tag_urls', 'integer', 0 ) );
$this->set_setting( 'relcanonical_tag_urls', param( 'relcanonical_tag_urls', 'integer', 0 ) );
$this->set_setting( 'default_noindex', param( 'default_noindex', 'integer', 0 ) );
$this->set_setting( 'posts_firstpage_noindex', param( 'posts_firstpage_noindex', 'integer', 0 ) );
$this->set_setting( 'paged_noindex', param( 'paged_noindex', 'integer', 0 ) );
$this->set_setting( 'paged_intro_noindex', param( 'paged_intro_noindex', 'integer', 0 ) );
$this->set_setting( 'paged_nofollowto', param( 'paged_nofollowto', 'integer', 0 ) );
$this->set_setting( 'single_noindex', param( 'single_noindex', 'integer', 0 ) );
$this->set_setting( 'archive_noindex', param( 'archive_noindex', 'integer', 0 ) );
$this->set_setting( 'archive_nofollowto', param( 'archive_nofollowto', 'integer', 0 ) );
$this->set_setting( 'chapter_noindex', param( 'chapter_noindex', 'integer', 0 ) );
$this->set_setting( 'chapter_intro_noindex', param( 'chapter_intro_noindex', 'integer', 0 ) );
$this->set_setting( 'tag_noindex', param( 'tag_noindex', 'integer', 0 ) );
$this->set_setting( 'tag_intro_noindex', param( 'tag_intro_noindex', 'integer', 0 ) );
$this->set_setting( 'filtered_noindex', param( 'filtered_noindex', 'integer', 0 ) );
$this->set_setting( 'filtered_intro_noindex', param( 'filtered_intro_noindex', 'integer', 0 ) );
$this->set_setting( 'arcdir_noindex', param( 'arcdir_noindex', 'integer', 0 ) );
$this->set_setting( 'catdir_noindex', param( 'catdir_noindex', 'integer', 0 ) );
$this->set_setting( 'feedback-popup_noindex', param( 'feedback-popup_noindex', 'integer', 0 ) );
$this->set_setting( 'msgform_noindex', param( 'msgform_noindex', 'integer', 0 ) );
$this->set_setting( 'msgform_nofollowto', param( 'msgform_nofollowto', 'integer', 0 ) );
$this->set_setting( 'msgform_redirect_slug', param( 'msgform_redirect_slug', 'string' ) );
$this->set_setting( 'special_noindex', param( 'special_noindex', 'integer', 0 ) );
$this->set_setting( 'title_link_type', param( 'title_link_type', 'string', '' ) );
$this->set_setting( 'permalinks', param( 'permalinks', 'string', '' ) );
$this->set_setting( '404_response', param( '404_response', 'string', '' ) );
$this->set_setting( 'help_link', param( 'help_link', 'string', '' ) );
$this->set_setting( 'excerpts_meta_description', param( 'excerpts_meta_description', 'integer', 0 ) );
$this->set_setting( 'categories_meta_description', param( 'categories_meta_description', 'integer', 0 ) );
$this->set_setting( 'tags_meta_keywords', param( 'tags_meta_keywords', 'integer', 0 ) );
$this->set_setting( 'tags_open_graph', param( 'tags_open_graph', 'integer', 0 ) );
$this->set_setting( 'tags_twitter_card', param( 'tags_twitter_card', 'integer', 0 ) );
$this->set_setting( 'tags_structured_data', param( 'tags_structured_data', 'integer', 0 ) );
$this->set_setting( 'download_noindex', param( 'download_noindex', 'integer', 0 ) );
$this->set_setting( 'download_nofollowto', param( 'download_nofollowto', 'integer', 0 ) );
$this->set_setting( 'canonical_user_urls', param( 'canonical_user_urls', 'integer', 0 ) );
}
if( in_array( 'credits', $groups ) )
{ // We want to load the software credits settings:
if( is_pro() )
{ // Allow to remove "Powered by b2evolution" logos only for PRO version:
$this->set_setting( 'powered_by_logos', param( 'powered_by_logos', 'integer', 0 ) );
}
param_integer_range( 'max_footer_credits', 0, 3, T_('Max credits must be between %d and %d.') );
$this->set_setting( 'max_footer_credits', get_param( 'max_footer_credits' ) );
}
/*
* ADVANCED ADMIN SETTINGS
*/
if( check_user_perm( 'blog_admin', 'edit', false, $this->ID ) ||
( $this->ID == 0 && check_user_perm( 'blogs', 'create', false, $this->sec_ID ) ) )
{ // We have permission to edit advanced admin settings,
// OR user is creating/coping new collection in section where he has an access:
if( ( $blog_urlname = param( 'blog_urlname', 'string', NULL ) ) !== NULL )
{ // check urlname
if( param_check_not_empty( 'blog_urlname', T_('You must provide an URL collection name!') ) )
{
if( ! preg_match( '|^[A-Za-z0-9\-]+$|', $blog_urlname ) )
{
param_error( 'blog_urlname', sprintf( T_('The url name %s is invalid.'), "«$blog_urlname»" ) );
$blog_urlname = NULL;
}
if( isset($blog_urlname) && $DB->get_var( 'SELECT COUNT(*)
FROM T_blogs
WHERE blog_urlname = '.$DB->quote($blog_urlname).'
AND blog_ID <> '.$this->ID
) )
{ // urlname is already in use
param_error( 'blog_urlname', sprintf( T_('The URL name %s is already in use by another collection. Please choose another name.'), "«$blog_urlname»" ) );
$blog_urlname = NULL;
}
if( isset( $blog_urlname ) )
{ // Set new urlname and save old media dir in order to rename folder to new
$old_media_dir = $this->get_media_dir( false );
$this->set_from_Request( 'urlname' );
}
}
}
}
if( check_user_perm( 'blog_admin', 'edit', false, $this->ID ) )
{ // We have permission to edit advanced admin settings:
if( in_array( 'cache', $groups ) )
{ // we want to load the cache params:
$this->set_setting( 'ajax_form_enabled', param( 'ajax_form_enabled', 'integer', 0 ) );
$this->set_setting( 'ajax_form_loggedin_enabled', param( 'ajax_form_loggedin_enabled', 'integer', 0 ) );
$this->set_setting( 'cache_enabled_widgets', param( 'cache_enabled_widgets', 'integer', 0 ) );
}
if( in_array( 'styles', $groups ) )
{ // we want to load the styles params:
$display_alt_skin_referer = param( 'display_alt_skin_referer', 'integer', 0 );
$this->set_setting( 'display_alt_skin_referer', $display_alt_skin_referer );
$display_alt_skin_referer_url = param( 'display_alt_skin_referer_url', 'string', NULL );
if( $display_alt_skin_referer )
{ // Check for not empty value only when setting is enabled:
param_check_not_empty( 'display_alt_skin_referer_url', T_('The Referer URL cannot be empty to display Alt skin automatically.') );
}
$this->set_setting( 'display_alt_skin_referer_url', $display_alt_skin_referer_url );
$this->set( 'allowblogcss', param( 'blog_allowblogcss', 'integer', 0 ) );
$this->set( 'allowusercss', param( 'blog_allowusercss', 'integer', 0 ) );
}
if( in_array( 'login', $groups ) )
{ // we want to load the login params:
if( ! get_setting_Blog( 'login_blog_ID', $this ) )
{ // Update this only when no blog is defined for login/registration
$this->set_setting( 'in_skin_login', param( 'in_skin_login', 'integer', 0 ) );
}
$this->set_setting( 'in_skin_editing', param( 'in_skin_editing', 'integer', 0 ) );
$this->set_setting( 'in_skin_change_proposal', param( 'in_skin_change_proposal', 'integer', 0 ) );
}
if( param( 'blog_head_includes', 'html', NULL ) !== NULL )
{ // HTML header includes:
param_check_html( 'blog_head_includes', T_('Invalid Custom meta tag/css section.').' '.sprintf( T_('You can loosen this restriction in the <a %s>Group settings</a>.'), 'href='.$admin_url.'?ctrl=groups&action=edit&grp_ID='.$current_User->grp_ID ), '#', 'head_extension' );
$this->set_setting( 'head_includes', get_param( 'blog_head_includes' ) );
}
if( param( 'blog_body_includes', 'html', NULL ) !== NULL )
{ // HTML body includes:
param_check_html( 'blog_body_includes', T_('Invalid Custom javascript section.').' '.sprintf( T_('You can loosen this restriction in the <a %s>Group settings</a>.'), 'href='.$admin_url.'?ctrl=groups&action=edit&grp_ID='.$current_User->grp_ID ), "#", 'body_extension' );
$this->set_setting( 'body_includes', get_param( 'blog_body_includes' ) );
}
if( param( 'blog_footer_includes', 'html', NULL ) !== NULL )
{ // HTML footer includes:
param_check_html( 'blog_footer_includes', T_('Invalid Custom javascript section.').' '.sprintf( T_('You can loosen this restriction in the <a %s>Group settings</a>.'), 'href='.$admin_url.'?ctrl=groups&action=edit&grp_ID='.$current_User->grp_ID ), "#", 'footer_extension' );
$this->set_setting( 'footer_includes', get_param( 'blog_footer_includes' ) );
}
if( param( 'owner_login', 'string', NULL ) !== NULL )
{ // Permissions:
$UserCache = & get_UserCache();
$owner_User = & $UserCache->get_by_login( get_param('owner_login') );
if( empty( $owner_User ) )
{
param_error( 'owner_login', sprintf( T_('User «%s» does not exist!'), get_param('owner_login') ) );
}
else
{
$this->set( 'owner_user_ID', $owner_User->ID );
$this->owner_User = & $owner_User;
}
}
if( ($access_type = param( 'blog_access_type', 'string', NULL )) !== NULL )
{ // Blog URL parameters:
// Note: We must avoid to set an invalid url, because the new blog url will be displayed in the evobar even if it was not saved
$allow_new_access_type = true;
if( $access_type == 'absolute' )
{
$blog_siteurl = param( 'blog_siteurl_absolute', 'url', true );
if( preg_match( '#^https?://[^/]+/.*#', $blog_siteurl, $matches ) )
{ // It looks like valid absolute URL, so we may update the blog siteurl
$this->set( 'siteurl', $blog_siteurl );
}
else
{ // It is not valid absolute URL, don't update the blog 'siteurl' to avoid errors
$allow_new_access_type = false; // If site url is not updated do not allow access_type update either
$Messages->add( T_('Collection base URL').': '.sprintf( T_('%s is an invalid absolute URL'), '«'.htmlspecialchars( $blog_siteurl ).'»' )
.'. '.T_('You must provide an absolute URL (starting with <code>http://</code> or <code>https://</code>) and it must contain at least one \'/\' sign after the domain name!'), 'error' );
}
}
elseif( $access_type == 'relative' )
{ // relative siteurl
$blog_siteurl = param( 'blog_siteurl_relative', 'string', true );
if( preg_match( '#^https?://#', $blog_siteurl ) )
{
$Messages->add( T_('Blog Folder URL').': '
.T_('You must provide a relative URL (without <code>http://</code> or <code>https://</code>)!'), 'error' );
}
$this->set( 'siteurl', $blog_siteurl );
}
else
{
$this->set( 'siteurl', '' );
}
if( $allow_new_access_type )
{ // The received siteurl value was correct, may update the access_type value
$this->set( 'access_type', $access_type );
}
}
if( ( $http_protocol = param( 'http_protocol', 'string', NULL ) ) !== NULL )
{ // SSL:
$this->set_setting( 'http_protocol', $http_protocol );
}
if( ( $url_aliases = param( 'blog_url_alias', 'array', NULL ) ) !== NULL )
{
$has_error = array();
foreach( $url_aliases as $key => $alias )
{
$alias = trim( $alias );
$url_aliases[$key] = $alias;
if( empty( $alias ) )
{
unset( $url_aliases[$key] );
continue;
}
if( ! preg_match( '#^https?://[^/]+/.*#', $alias, $matches ) )
{ // It is not valid absolute URL
$Messages->add( T_('Invalid URL format').': '.sprintf( T_('%s is an invalid absolute URL'), '«'.htmlspecialchars( $alias ).'»' )
.'. '.T_('You must provide an absolute URL (starting with <code>http://</code> or <code>https://</code>) and it must contain at least one \'/\' sign after the domain name!'), 'error' );
}
$has_error = validate_url( $alias, 'http-https' );
if( $has_error )
{
param_error( 'blog_url_alias', T_('Invalid URL format.') );
break;
}
$alias_wo_protocol = preg_replace( '#^https?(?=://)#', '', $alias );
// Check existing URL aliases in request array
foreach( $url_aliases as $sec_key => $sec_alias )
{
if( $sec_key == $key )
{
continue;
}
$re = "/^https?(.*)/i";
$subst = "https?$1";
$sec_alias = trim( $sec_alias );
$r = strlen( $alias ) - strlen( $sec_alias );
if( $r < 0 )
{
$alias = rtrim( $alias, "/\\" );
$str = preg_quote( $alias );
$subject = $sec_alias;
}
else
{
$sec_alias = rtrim( $sec_alias, "/\\" );
$str = preg_quote( $sec_alias );
$subject = $alias;
}
// Add trailing slash to subject
if( ! preg_match( '~(^|/|\.php.?)$~i', $subject ) )
{
$subject .= '/';
}
$url_regex = preg_replace( $re, $str, $subst );
// Remove trailing slash from url_regex
//die( var_dump( $url_regex ) );
if( preg_match( '#^'.$url_regex.'(?=/)#', $subject, $matches ) )
{
param_error( 'blog_url_alias', sprintf( T_('URL alias %s is already in use by another collection or contains an existing alias.'), '«'.$alias.'»' ) );
break;
}
}
$trailing_slash = '';
if( ! preg_match( '~(^|/|\.php.?)$~i', $alias_wo_protocol ) )
{
$trailing_slash = '/';
}
// Check existing URL aliases in other collections
$SQL = new SQL('Check existing URL aliases');
$SQL->SELECT( 'cua_url_alias' );
$SQL->FROM( 'T_coll_url_aliases' );
$SQL->WHERE( '( cua_coll_ID != '.$this->ID.' )' );
$SQL->WHERE_and( '( cua_url_alias IN ('.implode( ',', array( $DB->quote( 'http'.$alias_wo_protocol ), $DB->quote( 'https'.$alias_wo_protocol ) ) ).') )'
.'OR '.$DB->quote( 'http'.$alias_wo_protocol ).' LIKE CONCAT( cua_url_alias, IF(cua_url_alias REGEXP "(^|/|\.php)$", "", "/"), "%" )'
.'OR '. $DB->quote( 'https'.$alias_wo_protocol ).' LIKE CONCAT( cua_url_alias, IF(cua_url_alias REGEXP "(^|/|\.php)$", "", "/"), "%" )'
.'OR cua_url_alias LIKE '.$DB->quote( 'http'.$alias_wo_protocol.$trailing_slash.'%' )
.'OR cua_url_alias LIKE '.$DB->quote( 'https'.$alias_wo_protocol.$trailing_slash.'%' ) );
if( $DB->get_var( $SQL->get() ) )
{
param_error( 'blog_url_aliases', sprintf( T_('URL alias %s is already in use by another collection or contains an existing alias.'), '«'.$alias.'»' ) );
break;
}
}
if( ! param_has_error( 'blog_url_alias' ) )
{
$this->set( 'url_aliases', $url_aliases );
}
}
if( param( 'tinyurl_type', 'string', NULL ) !== NULL )
{ // Tiny URL type:
if( get_param( 'tinyurl_type') == 'advanced' )
{
$tinyurl_domain = param( 'tinyurl_domain', 'string', NULL );
if( ! preg_match( '#^https?://[a-z0-9]+([\-\.]{1}[a-z0-9]+)*\.[a-z]+/$#', $tinyurl_domain, $matches ) )
{ // It is not valid absolute URL
$Messages->add( T_('Tiny URL').': '.sprintf( T_('Supplied URL is invalid. (%s)'), '<code>'.htmlspecialchars( $tinyurl_domain ).'</code>' ), 'error' );
}
$this->set_setting( 'tinyurl_type', get_param( 'tinyurl_type' ) );
$this->set_setting( 'tinyurl_domain', $tinyurl_domain );
}
else
{
$this->set_setting( 'tinyurl_type', get_param( 'tinyurl_type' ) );
}
}
if( is_pro() && in_array( 'urls', $groups ) )
{ // Only PRO version and on update from tab "URLs":
// Tag source:
$this->set_setting( 'tinyurl_tag_source_enabled', param( 'tinyurl_tag_source_enabled', 'integer', 0 ) );
$this->set_setting( 'tinyurl_tag_source', param( 'tinyurl_tag_source', 'string', NULL ), true );
// Tag slug:
$this->set_setting( 'tinyurl_tag_slug_enabled', param( 'tinyurl_tag_slug_enabled', 'integer', 0 ) );
$this->set_setting( 'tinyurl_tag_slug', param( 'tinyurl_tag_slug', 'string', NULL ), true );
// Tag extra term:
$this->set_setting( 'tinyurl_tag_extra_term_enabled', param( 'tinyurl_tag_extra_term_enabled', 'integer', 0 ) );
$this->set_setting( 'tinyurl_tag_extra_term', param( 'tinyurl_tag_extra_term', 'string', NULL ), true );
}
if( ( param( 'cookie_domain_type', 'string', NULL ) !== NULL ) && check_user_perm( 'blog_admin', 'edit', false, $this->ID ) )
{ // Cookies:
$this->set_setting( 'cookie_domain_type', get_param( 'cookie_domain_type' ) );
if( get_param( 'cookie_domain_type' ) == 'custom' )
{ // Update custom cookie domain:
$cookie_domain_custom = param( 'cookie_domain_custom', 'string', NULL );
preg_match( '#^https?://(.+?)(:(.+?))?$#', $this->get_baseurl_root(), $coll_host );
if( empty( $coll_host[1] ) || ! preg_match( '#(^|\.)'.preg_quote( preg_replace( '#^\.#i', '', $cookie_domain_custom ), '#' ).'$#i', $coll_host[1] ) )
{ // Wrong cookie domain:
param_error( 'cookie_domain_custom', T_('The custom cookie domain must be a parent of the collection domain.') );
}
$this->set_setting( 'cookie_domain_custom', $cookie_domain_custom );
}
else
{ // Reset custom cookie domain:
$this->set_setting( 'cookie_domain_custom', '' );
}
$this->set_setting( 'cookie_path_type', param( 'cookie_path_type', 'string', NULL ) );
if( get_param( 'cookie_path_type' ) == 'custom' )
{ // Update custom cookie path:
$cookie_path_custom = param( 'cookie_path_custom', 'string', NULL );
if( ! preg_match( '#^'.preg_quote( preg_replace( '#/$#i', '', $cookie_path_custom ), '#' ).'(/|$)#i', $this->get_basepath() ) )
{ // Wrong cookie path:
param_error( 'cookie_path_custom', T_('The custom cookie path must be a parent of the collection path.') );
}
$this->set_setting( 'cookie_path_custom', $cookie_path_custom );
}
else
{ // Reset custom cookie path:
$this->set_setting( 'cookie_path_custom', '' );
}
}
if( ( param( 'rsc_assets_url_type', 'string', NULL ) !== NULL ) && check_user_perm( 'blog_admin', 'edit', false, $this->ID ) )
{ // Assets URLs / CDN:
// Check all assets types url settings:
$assets_url_data = array(
'rsc_assets_url_type' => array( 'url' => 'rsc_assets_absolute_url', 'folder' => '/rsc/' ),
'media_assets_url_type' => array( 'url' => 'media_assets_absolute_url', 'folder' => '/media/' ),
'skins_assets_url_type' => array( 'url' => 'skins_assets_absolute_url', 'folder' => '/skins/' ),
'plugins_assets_url_type' => array( 'url' => 'plugins_assets_absolute_url', 'folder' => '/plugins/' ),
'htsrv_assets_url_type' => array( 'url' => 'htsrv_assets_absolute_url', 'folder' => '/htsrv/' ),
);
foreach( $assets_url_data as $asset_url_type => $asset_url_data )
{
$asset_url_type_value = param( $asset_url_type, 'string', NULL );
if( $asset_url_type_value === NULL )
{ // Skip this setting to don't save when it doesn't exist on form
continue;
}
$this->set_setting( $asset_url_type, $asset_url_type_value );
$assets_absolute_url_value = param( $asset_url_data['url'], 'url', NULL );
if( ( get_param( $asset_url_type ) == 'absolute' ) && empty( $assets_absolute_url_value ) )
{ // Absolute URL cannot be empty
$Messages->add( sprintf( T_('Absolute URL for %s cannot be empty!'), $asset_url_data['folder'] ) );
}
elseif( empty( $assets_absolute_url_value ) || preg_match( '#^(https?:)?//.+/$#', $assets_absolute_url_value ) )
{ // It looks like valid absolute URL, so we may update it
$this->set_setting( $asset_url_data['url'], $assets_absolute_url_value, true );
}
else
{ // It is not valid absolute URL, don't update it to avoid errors
$Messages->add( sprintf( T_('Absolute URL for %s'), $asset_url_data['folder'] ).': '.sprintf( T_('%s is an invalid absolute URL'), '«'.htmlspecialchars( $assets_absolute_url_value ).'»' )
.'. '.T_('You must provide an absolute URL (starting with <code>http://</code>, <code>https://</code> or <code>//</code>) and it must ending with \'/\' sign!'), 'error' );
}
}
if( $this->get( 'access_type' ) == 'absolute' &&
( $this->get_setting( 'rsc_assets_url_type' ) == 'basic' ||
$this->get_setting( 'skins_assets_url_type' ) == 'basic' ||
$this->get_setting( 'plugins_assets_url_type' ) == 'basic' ) )
{ // Display warning for such settings combination:
$Messages->add( T_('WARNING: you will be loading your assets from a different domain. This may cause problems if you don\'t know exactly what you are doing. Please check the Assets URLs panel below.'), 'warning' );
}
if( $this->get_setting( 'skins_assets_url_type' ) != 'relative' )
{ // Display warning if skins path is used as NOT relative url:
if( $this->get_setting( 'rsc_assets_url_type' ) == 'relative' )
{ // If rsc path is relative url:
$Messages->add( sprintf( T_('WARNING: your %s and %s assets URL seem to be configured in a potentially undesirable way. Please check your Assets URLs below.'),
'<code>/rsc/</code>', '<code>/skins/</code>' ), 'warning' );
}
if( $this->get_setting( 'plugins_assets_url_type' ) == 'relative' )
{ // If plugins path is relative url:
$Messages->add( sprintf( T_('WARNING: your %s and %s assets URL seem to be configured in a potentially undesirable way. Please check your Assets URLs below.'),
'<code>/plugins/</code>', '<code>/skins/</code>' ), 'warning' );
}
}
}
if( $this->type != 'main' || ( $this->type == 'main' && $this->ID > 0 ) )
{
if( param( 'aggregate_coll_IDs', 'string', NULL ) !== NULL )
{ // Aggregate list: (can be '*')
$aggregate_coll_IDs = get_param( 'aggregate_coll_IDs' );
if( $aggregate_coll_IDs != '*' )
{ // Sanitize the string
$aggregate_coll_IDs = sanitize_id_list($aggregate_coll_IDs);
}
// fp> TODO: check perms on each aggregated blog (if changed)
// fp> TODO: better interface
if( $aggregate_coll_IDs != '*' && !preg_match( '#^([0-9]+(,[0-9]+)*)?$#', $aggregate_coll_IDs ) )
{
param_error( 'aggregate_coll_IDs', T_('Invalid aggregate collection ID list!') );
}
$this->set_setting( 'aggregate_coll_IDs', $aggregate_coll_IDs );
}
}
elseif( $this->type == 'main' && $this->ID === 0 )
{ // Only on new Home/Main collection
if( param( 'blog_aggregate', 'integer', 1 ) === 0 )
{
$this->set_setting( 'aggregate_coll_IDs', NULL );
}
else
{
$this->set_setting( 'aggregate_coll_IDs', '*' );
}
}
$media_location = param( 'blog_media_location', 'string', NULL );
if( $media_location !== NULL )
{ // Media files location:
$old_media_dir = $this->get_media_dir( false );
$old_media_location = $this->get( 'media_location' );
$this->set_from_Request( 'media_location' );
$this->set_media_subdir( param( 'blog_media_subdir', 'string', '' ) );
$this->set_media_fullpath( param( 'blog_media_fullpath', 'string', '' ) );
$this->set_media_url( param( 'blog_media_url', 'url', '' ) );
// check params
switch( $this->get( 'media_location' ) )
{
case 'custom': // custom path and URL
global $demo_mode, $media_path;
if( $this->get( 'media_fullpath' ) == '' )
{
param_error( 'blog_media_fullpath', T_('Media dir location').': '.T_('You must provide the full path of the media directory.') );
}
if( !preg_match( '#^https?://#', $this->get( 'media_url' ) ) )
{
param_error( 'blog_media_url', T_('Media dir location').': '
.T_('You must provide an absolute URL (starting with <code>http://</code> or <code>https://</code>)!') );
}
if( $demo_mode )
{
$canonical_fullpath = get_canonical_path($this->get('media_fullpath'));
if( ! $canonical_fullpath || strpos($canonical_fullpath, $media_path) !== 0 )
{
param_error( 'blog_media_fullpath', T_('Media dir location').': in demo mode the path must be inside of $media_path.' );
}
}
break;
case 'subdir':
global $media_path;
if( $this->get( 'media_subdir' ) == '' )
{
param_error( 'blog_media_subdir', T_('Media dir location').': '.T_('You must provide the media subdirectory.') );
}
else
{ // Test if it's below $media_path (subdir!)
$canonical_path = get_canonical_path($media_path.$this->get( 'media_subdir' ));
if( ! $canonical_path || strpos($canonical_path, $media_path) !== 0 )
{
param_error( 'blog_media_subdir', T_('Media dir location').': '.sprintf(T_('Invalid subdirectory «%s».'), format_to_output($this->get('media_subdir'))) );
}
else
{
// Validate if it's a valid directory name:
$subdir = no_trailing_slash(substr($canonical_path, strlen($media_path)));
if( $error = validate_dirname($subdir) )
{
param_error( 'blog_media_subdir', T_('Media dir location').': '.$error );
syslog_insert( sprintf( 'Invalid name is detected for folder %s', '[['.$subdir.']]' ), 'warning', 'file' );
}
}
}
break;
}
}
if( $this->ID > 0 && ! param_errors_detected() && ! empty( $old_media_dir ) )
{ // No error were detected before and possibly the media directory path was updated, check if it can be managed
$this->check_media_dir_change( $old_media_dir, isset( $old_media_location ) ? $old_media_location : NULL );
}
}
return ! param_errors_detected() && empty( $this->confirmation );
}
/**
* Load blog front office post/comment statuses
*
* @param string type = 'post' or 'comment'
*/
function load_inskin_statuses( $type )
{
if( ( $type != 'post' ) && ( $type != 'comment' ) )
{ // Invalid type
debug_die( 'Invalid type to load blog inskin statuses!' );
}
// Get possible front office statuses
$inskin_statuses = get_visibility_statuses( 'keys', array( 'deprecated', 'trash', 'redirected' ) );
$selected_inskin_statuses = array();
foreach( $inskin_statuses as $status )
{
if( param( $type.'_inskin_'.$status, 'integer', 0 ) )
{ // This status was selected
$selected_inskin_statuses[] = $status;
}
}
$this->set_setting( $type.'_inskin_statuses', implode( ',', $selected_inskin_statuses ) );
}
/**
* Set the media folder's subdir
*
* @param string the subdirectory
*/
function set_media_subdir( $path )
{
parent::set_param( 'media_subdir', 'string', trailing_slash( $path ) );
}
/**
* Set the full path of the media folder
*
* @param string the full path
*/
function set_media_fullpath( $path )
{
parent::set_param( 'media_fullpath', 'string', trailing_slash( $path ) );
}
/**
* Set the full URL of the media folder
*
* @param string the full URL
*/
function set_media_url( $url )
{
parent::set_param( 'media_url', 'string', trailing_slash( $url ) );
}
/**
* Set favorite status of current_user
*
* @param integer User ID, leave empty for current user
* @param integer Setting, leave empty to get favorite status
* @return mixed Current favorite status or if set, True if the setting was changed else false, NULL if unable to process
*/
function favorite( $user_ID = NULL, $setting = NULL )
{
global $DB, $current_User;
if( is_null( $user_ID ) && $current_User )
{
if( $current_User )
{
$user_ID = $current_User->ID;
}
else
{
return NULL;
}
}
if( $this->ID && $user_ID )
{
if( is_null( $setting ) )
{ // just return current favorite status
$fav_SQL = new SQL( 'Check if collection #'.$this->ID.' is a favorite for user #'.$user_ID );
$fav_SQL->SELECT( 'COUNT(*)' );
$fav_SQL->FROM( 'T_coll_user_favs' );
$fav_SQL->WHERE( 'cufv_blog_ID = '.$DB->quote( $this->ID ) );
$fav_SQL->WHERE_and( 'cufv_user_ID = '.$DB->quote( $user_ID ) );
return $DB->get_var( $fav_SQL );
}
if( $setting == 1 )
{
return $DB->query( 'REPLACE INTO T_coll_user_favs ( cufv_user_ID, cufv_blog_ID ) VALUES ( '.$user_ID.', '.$this->ID.' )' );
}
else
{
return $DB->query( 'DELETE FROM T_coll_user_favs WHERE cufv_user_ID = '.$user_ID.' AND cufv_blog_ID = '.$this->ID );
}
}
else
{
return NULL;
}
}
/**
* Set param value
*
* @param string Parameter name
* @param boolean true to set to NULL if empty value
* @return boolean true, if a value has been set; false if it has not changed
*/
function set( $parname, $parvalue, $make_null = false )
{
global $Settings;
switch( $parname )
{
case 'ID':
case 'allowtrackbacks':
return $this->set_param( $parname, 'number', $parvalue, $make_null );
break;
case 'url_aliases':
$this->url_aliases = $parvalue;
$this->update_url_aliases = true;
break;
default:
return $this->set_param( $parname, 'string', $parvalue, $make_null );
}
}
/**
* Generate blog URL. That is the URL of the main page/home page of the blog.
* This will not necessarily be a folder. For example, it can end in index.php?blog=4
*
* @param string Collection access type
* @return string Collection full URL
*/
function gen_blogurl( $type = 'default' )
{
global $baseprotocol, $basehost, $baseport, $baseurl, $Settings;
if( $type == 'default' )
{ // Use current access type of this collection:
$type = $this->get( 'access_type' );
}
switch( $type )
{
case 'baseurl':
case 'default':
// Access through index.php: match absolute URL or call default blog
if( ( $Settings->get('default_blog_ID') == $this->ID )
|| preg_match( '#^https?://#', $this->siteurl ) )
{ // Safety check! We only do that kind of linking if this is really the default blog...
// or if we call by absolute URL
if( $this->get( 'access_type' ) == 'default' )
{
return $this->get_protocol_url( $baseurl ).$this->siteurl.'index.php';
}
else
{
return $this->get_protocol_url( $baseurl ).$this->siteurl;
}
}
// ... otherwise, we add the blog ID:
case 'index.php':
// Access through index.php + blog qualifier
return $this->get_protocol_url( $baseurl ).$this->siteurl.'index.php?blog='.$this->ID;
case 'extrabase':
// We want to use extra path on base url, use the blog urlname:
return $this->get_protocol_url( $baseurl ).$this->siteurl.$this->urlname.'/';
case 'extrapath':
// We want to use extra path on index.php, use the blog urlname:
return $this->get_protocol_url( $baseurl ).$this->siteurl.'index.php/'.$this->urlname.'/';
case 'relative':
return $this->get_protocol_url( $baseurl ).$this->siteurl;
case 'subdom':
return $this->get_protocol_url( $baseprotocol.'://' ).$this->urlname.'.'.$basehost.$baseport.'/';
case 'absolute':
return $this->get_protocol_url( $this->siteurl );
default:
debug_die( 'Unhandled Blog access type ['.$type.']' );
}
}
/**
* Generate the baseurl of the blog (URL of the folder where the blog lives).
* Will always end with '/'.
*
* @param string Collection access type
* @return string Collection base URL
*/
function gen_baseurl( $type = 'default' )
{
if( $type == 'default' )
{ // Use current access type of this collection:
$type = $this->get( 'access_type' );
}
$url = $this->gen_blogurl( $type );
if( substr( $url, -1 ) != '/' )
{ // Crop an url part after the last "/":
$url = substr( $url, 0, strrpos( $url, '/' ) + 1 );
}
switch( $type )
{
case 'default':
case 'index.php':
// Must be ended with index.php:
$url .= 'index.php/';
break;
}
return $url;
}
/**
* This is the domain of the collection.
* This returns NO trailing slash.
*
* @return string
*/
function get_baseurl_root()
{
if( empty( $this->baseurl_root ) )
{ // Initialize collection domain only first time:
if( preg_match( '#^(https?://(.+?)(:.+?)?)/#', $this->gen_baseurl(), $matches ) )
{
$this->baseurl_root = $matches[1];
}
else
{
debug_die( 'Blog::get(baseurl)/baseurlroot - assertion failed [baseurl: '.$this->gen_baseurl().'].' );
}
}
return $this->baseurl_root;
}
/**
* Get the URL to the basepath of that collection.
* This is supposed to be the same as $baseurl but localized to the domain of the blog/
*
* @return string
*/
function get_basepath_url()
{
if( empty( $this->basepath_url ) )
{
if( $this->get( 'access_type' ) == 'absolute' )
{ // Use whole url when it is absolute:
// Remove text like 'index.php' at the end:
$this->basepath_url = preg_replace( '/^(.+\/)([^\/]+\.[^\/]+)?$/', '$1', $this->get( 'siteurl' ) );
}
else
{ // Build url from base and sub path:
$this->basepath_url = $this->get_baseurl_root().$this->get_basepath();
}
// Get URL with protocol which is defined by collection setting "SSL":
$this->basepath_url = $this->get_protocol_url( $this->basepath_url );
}
return $this->basepath_url;
}
/**
* Get the basepath of this collection relative to domain
*
* @return string
*/
function get_basepath()
{
if( empty( $this->basepath ) )
{ // Initialize base path only first time:
if( $this->get( 'access_type' ) == 'absolute' )
{ // If collection URL is absolute we should extract sub path from the URL because it can be different than site url:
$this->basepath = str_replace( $this->get_baseurl_root(), '', $this->get_basepath_url() );
}
else
{ // Otherwise we can use sub path of site url:
global $basesubpath;
$this->basepath = $basesubpath;
}
}
return $this->basepath;
}
/**
* Get cookie domain of this collection
*
* @param boolean|string FALSE - use dependon of setting,
* 'auto' - force to use automatic cookie domain,
* 'custom' - force to use custom cookie domain
* @return string
*/
function get_cookie_domain( $force_type = false )
{
if( empty( $this->cookie_domain ) )
{ // Initialize only first time:
$cookie_domain_type = ( $force_type === false ) ? $this->get_setting( 'cookie_domain_type' ) : $force_type;
if( $cookie_domain_type == 'custom' )
{ // Custom cookie domain:
return $this->get_setting( 'cookie_domain_custom' );
}
else
{ // Automatic cookie domain:
if( $this->get( 'access_type' ) == 'absolute' )
{ // If collection URL is absolute we should extract cookie domain from the URL because it can be different than site url:
preg_match( '#^https?://(.+?)(:(.+?))?$#', $this->get_baseurl_root(), $matches );
$coll_host = $matches[1];
if( strpos( $coll_host, '.' ) === false )
{ // localhost or windows machine name:
$this->cookie_domain = $coll_host;
}
elseif( preg_match( '~^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$~i', $coll_host ) )
{ // The basehost is an IP address, use the basehost as it is:
$this->cookie_domain = $coll_host;
}
else
{ // Keep the part of the basehost after the www. :
$this->cookie_domain = preg_replace( '/^(www\. )? (.+)$/xi', '.$2', $coll_host );
}
}
else
{ // Otherwise we can use sub path of site url:
global $cookie_domain;
$this->cookie_domain = $cookie_domain;
}
}
}
return $this->cookie_domain;
}
/**
* Get cookie path of this collection
*
* @param boolean|string FALSE - use dependon of setting,
* 'auto' - force to use automatic cookie path,
* 'custom' - force to use custom cookie path
* @return string
*/
function get_cookie_path( $force_type = false )
{
if( empty( $this->cookie_path ) )
{ // Initialize only first time:
$cookie_domain_type = ( $force_type === false ) ? $this->get_setting( 'cookie_path_type' ) : $force_type;
if( $cookie_domain_type == 'custom' )
{ // Custom cookie path:
return $this->get_setting( 'cookie_path_custom' );
}
else
{ // Automatic cookie path:
$this->cookie_path = $this->get_basepath();
}
}
return $this->cookie_path;
}
/**
* Get URL to htsrv folder
*
* Note: For back-office or no collection page _init_hit.inc.php should be called before this call, because ReqHost and ReqPath must be initialized
*
* @param boolean TRUE to use https URL
* @return string URL to htsrv folder
*/
function get_htsrv_url( $force_https = false )
{
if( ! isset( $this->htsrv_urls[ $force_https ] ) )
{ // Initialize collection htsrv URL only first time and store in cache:
global $htsrv_url, $htsrv_subdir;
if( ! is_array( $this->htsrv_urls ) )
{
$this->htsrv_urls = array();
}
// Get URL with protocol which is defined by collection setting "SSL":
$required_htsrv_url = $this->get_protocol_url( $htsrv_url );
// Force URL to https depending on the param $force_https:
$required_htsrv_url = force_https_url( $required_htsrv_url, $force_https );
// Cut htsrv folder from end of the URL:
$required_htsrv_url = substr( $required_htsrv_url, 0, strlen( $required_htsrv_url ) - strlen( $htsrv_subdir ) );
if( strpos( $this->get_basepath_url(), $required_htsrv_url ) !== false )
{ // If current request path contains the required htsrv URL:
return $required_htsrv_url.$htsrv_subdir;
}
$coll_url_parts = @parse_url( $this->get_basepath_url() );
$htsrv_url_parts = @parse_url( $required_htsrv_url );
if( ! isset( $coll_url_parts['host'] ) || ! isset( $htsrv_url_parts['host'] ) )
{
debug_die( 'Invalid hosts!' );
}
$coll_domain = $coll_url_parts['host']
.( empty( $coll_url_parts['port'] ) ? '' : ':'.$coll_url_parts['port'] )
.( empty( $coll_url_parts['path'] ) ? '' : $coll_url_parts['path'] );
$htsrv_domain = $htsrv_url_parts['host']
.( empty( $htsrv_url_parts['port'] ) ? '' : ':'.$htsrv_url_parts['port'] )
.( empty( $htsrv_url_parts['path'] ) ? '' : $htsrv_url_parts['path'] );
if( isset( $coll_url_parts['scheme'], $htsrv_url_parts['scheme'] ) &&
$htsrv_url_parts['scheme'] != 'https' && // Don't force htsrv back to http when it was already forced to https above by force_https_url()
$coll_url_parts['scheme'] != $htsrv_url_parts['scheme'] )
{ // If this collection uses an url with scheme like "https://" then
// htsrv url must also uses the same url scheme to avoid restriction by secure reason:
$required_htsrv_url = $coll_url_parts['scheme'].substr( $required_htsrv_url, strlen( $htsrv_url_parts['scheme'] ) );
}
// Replace domain + path of htsrv URL with current request:
$this->htsrv_urls[ $force_https ] = substr_replace( $required_htsrv_url, $coll_domain, strpos( $required_htsrv_url, $htsrv_domain ), strlen( $htsrv_domain ) );
// Revert htsrv folder to end of the URL which has been cut above:
$this->htsrv_urls[ $force_https ] .= $htsrv_subdir;
}
return $this->htsrv_urls[ $force_https ];
}
/**
* Get the URL of the htsrv folder, on the current collection's domain (which is NOT always the same as the $baseurl domain!).
*
* @param string NULL to use current htsrv_assets_url_type setting. Use 'basic', 'relative' or 'absolute' to force.
* @param boolean TRUE to use https URL
* @return string URL to /htsrv/ folder
*/
function get_local_htsrv_url( $url_type = NULL, $force_https = false )
{
$url_type = is_null( $url_type ) ? $this->get_setting( 'htsrv_assets_url_type' ) : $url_type;
if( $url_type == 'relative' )
{ // Relative URL:
return $this->get_htsrv_url( $force_https );
}
elseif( $url_type == 'absolute' )
{ // Absolute URL:
// Get URL with protocol which is defined by collection setting "SSL":
$htsrv_assets_absolute_url = $this->get_protocol_url( $this->get_setting( 'htsrv_assets_absolute_url' ) );
// Force URL to https depending on the param $force_https:
return force_https_url( $htsrv_assets_absolute_url, $force_https );
}
else// == 'basic'
{ // Basic Config URL from config:
global $htsrv_url;
// Get URL with protocol which is defined by collection setting "SSL":
$basic_htsrv_url = $this->get_protocol_url( $htsrv_url );
// Force URL to https depending on the param $force_https:
return force_https_url( $basic_htsrv_url, $force_https );
}
}
/**
* Get the URL of the media folder, on the current blog's domain (which is NOT always the same as the $baseurl domain!).
*
* @param string NULL to use current media_assets_url_type setting. Use 'basic', 'relative' or 'absolute' to force.
* @param boolean TRUE - to don't force relative URL to absolute on back-office, mail template and feed skin
* @return string URL to /media/ folder
*/
function get_local_media_url( $url_type = NULL, $force_normal_using = false )
{
$url_type = is_null( $url_type ) ? $this->get_setting( 'media_assets_url_type' ) : $url_type;
if( $url_type == 'relative' )
{ // Relative URL:
if( ! $force_normal_using && is_admin_page() )
{ // Force to absolute base URL on back-office side and email template:
global $media_url;
$local_media_url = $media_url;
}
else
{ // Use absolute URL relative to collection media folder:
global $media_subdir;
$local_media_url = $this->get_baseurl_root().$this->get_basepath().$media_subdir;
}
}
elseif( $url_type == 'absolute' )
{ // Absolute URL:
$local_media_url = $this->get_setting( 'media_assets_absolute_url' );
}
else// == 'basic'
{ // Basic URL from config:
global $media_url;
$local_media_url = $media_url;
}
// Get URL with protocol which is defined by collection setting "SSL":
return $this->get_protocol_url( $local_media_url );
}
/**
* Get the URL of the rsc folder, on the current blog's domain (which is NOT always the same as the $baseurl domain!).
*
* @param string NULL to use current rsc_assets_url_type setting. Use 'basic', 'relative' or 'absolute' to force.
* @return string URL to /rsc/ folder
*/
function get_local_rsc_url( $url_type = NULL )
{
$url_type = is_null( $url_type ) ? $this->get_setting( 'rsc_assets_url_type' ) : $url_type;
if( $url_type == 'relative' )
{ // Relative URL
global $rsc_subdir;
$local_rsc_url = $this->get_basepath().$rsc_subdir;
}
elseif( $url_type == 'absolute' )
{ // Absolute URL
$local_rsc_url = $this->get_setting( 'rsc_assets_absolute_url' );
}
else// == 'basic'
{ // Basic URL from config
global $rsc_url;
$local_rsc_url = $rsc_url;
}
// Get URL with protocol which is defined by collection setting "SSL":
return $this->get_protocol_url( $local_rsc_url );
}
/**
* Get the URL of the skins folder, on the current blog's domain (which is NOT always the same as the $baseurl domain!).
*
* @param string NULL to use current skins_assets_url_type setting. Use 'basic', 'relative' or 'absolute' to force.
* @return string URL to /skins/ folder
*/
function get_local_skins_url( $url_type = NULL )
{
$url_type = is_null( $url_type ) ? $this->get_setting( 'skins_assets_url_type' ) : $url_type;
if( $url_type == 'relative' )
{ // Relative URL
global $skins_subdir;
$local_skins_url = $this->get_basepath().$skins_subdir;
}
elseif( $url_type == 'absolute' )
{ // Absolute URL
$local_skins_url = $this->get_setting( 'skins_assets_absolute_url' );
}
else// == 'basic'
{ // Basic URL from config
global $skins_url;
$local_skins_url = $skins_url;
}
// Get URL with protocol which is defined by collection setting "SSL":
return $this->get_protocol_url( $local_skins_url );
}
/**
* Get the URL of the plugins folder, on the current collection's domain (which is NOT always the same as the $baseurl domain!).
*
* @param string NULL to use current plugins_assets_url_type setting. Use 'basic', 'relative' or 'absolute' to force.
* @return string URL to /plugins/ folder
*/
function get_local_plugins_url( $url_type = NULL )
{
$url_type = is_null( $url_type ) ? $this->get_setting( 'plugins_assets_url_type' ) : $url_type;
if( $url_type == 'relative' )
{ // Relative URL:
global $plugins_subdir;
$local_plugins_url = $this->get_basepath().$plugins_subdir;
}
elseif( $url_type == 'absolute' )
{ // Absolute URL:
$local_plugins_url = $this->get_setting( 'plugins_assets_absolute_url' );
}
else// == 'basic'
{ // Basic Config URL from config:
global $plugins_url;
$local_plugins_url = $plugins_url;
}
// Get URL with protocol which is defined by collection setting "SSL":
return $this->get_protocol_url( $local_plugins_url );
}
/**
* Get the URL of the xmlsrv folder, on the current blog's domain (which is NOT always the same as the $baseurl domain!).
*/
function get_local_xmlsrv_url()
{
global $xmlsrv_subdir;
return $this->get_basepath_url().$xmlsrv_subdir;
}
/**
* Generate archive page URL
*
* Note: there ate two similar functions here.
* @see Blog::get_archive_url()
*
* @param string year
* @param string month
* @param string day
* @param string week
*/
function gen_archive_url( $year, $month = NULL, $day = NULL, $week = NULL, $glue = '&', $paged = 1 )
{
$blogurl = $this->gen_blogurl();
$archive_links = $this->get_setting('archive_links');
if( $archive_links == 'param' )
{ // We reference by Query
$separator = '';
}
else
{ // We reference by extra path info
$separator = '/';
}
$datestring = $separator.$year.$separator;
if( !empty( $month ) )
{
$datestring .= zeroise($month,2).$separator;
if( !empty( $day ) )
{
$datestring .= zeroise($day,2).$separator;
}
}
elseif( !is_null($week) && $week !== '' ) // Note: week # can be 0 !
{
if( $archive_links == 'param' )
{ // We reference by Query
$datestring .= $glue.'w='.$week;
}
else
{ // extra path info
$datestring .= 'w'.zeroise($week,2).'/';
}
}
if( $archive_links == 'param' )
{ // We reference by Query
$link = url_add_param( $blogurl, 'm='.$datestring, $glue );
$archive_posts_per_page = $this->get_setting( 'archive_posts_per_page' );
if( !empty($archive_posts_per_page) && $archive_posts_per_page != $this->get_setting( 'posts_per_page' ) )
{ // We want a specific post per page count:
$link = url_add_param( $link, 'posts='.$archive_posts_per_page, $glue );
}
}
else
{ // We reference by extra path info
$link = url_add_tail( $blogurl, $datestring ); // there may already be a slash from a siteurl like 'http://example.com/'
}
if( $paged > 1 )
{ // We want a specific page:
$link = url_add_param( $link, 'paged='.$paged, $glue );
}
return $link;
}
/**
* Generate link to archive
* @uses Blog::gen_archive_url()
* @return string HTML A tag
*/
function gen_archive_link( $text, $title, $year, $month = NULL, $day = NULL, $week = NULL, $glue = '&', $paged = 1 )
{
$link = '<a';
if( $this->get_setting( 'archive_nofollowto' ) )
{
$link .= ' rel="nofollow"';
}
if( !empty($title) )
{
$link .= ' title="'.format_to_output( $title, 'htmlattr' ).'"';
}
$link .= ' href="'.$this->gen_archive_url( $year, $month, $day, $week, $glue, $paged ).'" >';
$link .= format_to_output( $text );
$link .= '</a>';
return $link;
}
/**
* Get archive page URL
*
* Note: there are two similar functions here.
*
* @uses Blog::gen_archive_url()
*
* @param string monthly, weekly, daily
*/
function get_archive_url( $date, $glue = '&' )
{
switch( $this->get_setting('archive_mode') )
{
case 'weekly':
global $cacheweekly, $DB;
if((!isset($cacheweekly)) || (empty($cacheweekly[$date])))
{
$cacheweekly[$date] = $DB->get_var( 'SELECT '.$DB->week( $DB->quote($date), locale_startofweek() ) );
}
return $this->gen_archive_url( substr( $date, 0, 4 ), NULL, NULL, $cacheweekly[$date], $glue );
break;
case 'daily':
return $this->gen_archive_url( substr( $date, 0, 4 ), substr( $date, 5, 2 ), substr( $date, 8, 2 ), NULL, $glue );
break;
case 'monthly':
default:
return $this->gen_archive_url( substr( $date, 0, 4 ), substr( $date, 5, 2 ), NULL, NULL, $glue );
}
}
/**
* Generate a tag url on this blog
*/
function gen_tag_url( $tag, $paged = 1, $glue = '&' )
{
$link_type = $this->get_setting( 'tag_links' );
switch( $link_type )
{
case 'param':
$r = url_add_param( $this->gen_blogurl(), 'tag='.urlencode( $tag ), $glue );
$tag_posts_per_page = $this->get_setting( 'tag_posts_per_page' );
if( !empty($tag_posts_per_page) && $tag_posts_per_page != $this->get_setting( 'posts_per_page' ) )
{ // We want a specific post per page count:
$r = url_add_param( $r, 'posts='.$tag_posts_per_page, $glue );
}
break;
default:
switch( $link_type )
{
case 'dash':
$trailer = '-';
break;
case 'semicol': // dh> TODO: old value. I had this in my DB. Convert this during upgrade?
case 'semicolon':
$trailer = ';';
break;
case 'colon':
$trailer = ':';
break;
case 'prefix-only':
default:
$trailer = '';
}
$tag_prefix = $this->get_setting('tag_prefix');
if( !empty( $tag_prefix ) )
{
$r = url_add_tail( $this->gen_blogurl(), '/'.$tag_prefix.'/'.urlencode( $tag ).$trailer );
}
else
{
$r = url_add_tail( $this->gen_blogurl(), '/'.urlencode( $tag ).$trailer );
}
}
if( $paged > 1 )
{ // We want a specific page:
$r = url_add_param( $r, 'paged='.$paged, $glue );
}
return $r;
}
/**
* Get a link (<a href>) to the tag page of a given tag.
*
* @param string Tag
* @param string Link text (defaults to tag name)
* @param array Additional attributes for the A tag (href gets overridden).
* @return string The <a href> link
*/
function get_tag_link( $tag, $text = NULL, $attribs = array() )
{
if( $this->get_setting('tag_rel_attrib') && $this->get_setting('tag_links') == 'prefix-only' )
{ // add rel=tag attrib -- valid only if the last part of the url is the tag name
if( ! isset($attribs['rel']) )
$attribs['rel'] = 'tag';
else
$attribs['rel'] .= ' tag';
}
$attribs['href'] = $this->gen_tag_url( $tag );
if( is_null($text) )
{
$text = $tag;
}
return '<a'.get_field_attribs_as_string($attribs).'>'.$text.'</a>';
}
/**
* Checks if the requested item status can be used by current user and if not, get max allowed item status of the collection
*
* @todo make default a Blog param
*
* @param string status to start with. Empty to use default.
* @param object Permission object: Item or Comment
* @return string authorized status; NULL if none
*/
function get_allowed_item_status( $status = NULL, $perm_target = NULL )
{
if( ! is_logged_in() )
{ // User must be logged in:
return $this->get_max_allowed_status( $status );
}
if( empty( $status ) )
{ // Get default item status:
$status = $this->get_setting( 'default_post_status' );
}
// Get max allowed visibility status:
$max_allowed_status = get_highest_publish_status( 'post', $this->ID, false, '', $perm_target );
$visibility_statuses = get_visibility_statuses();
$status_is_allowed = false;
$max_status_is_allowed = false;
$allowed_status = NULL;
foreach( $visibility_statuses as $status_key => $status_value )
{
if( $status_key == $status || empty( $status ) )
{ // Start to check statuses only after the requested status:
$status_is_allowed = true;
}
if( $status_key == $max_allowed_status )
{ // All next statuses are allowed for this collection:
$max_status_is_allowed = true;
}
if( $status_is_allowed && $max_status_is_allowed && check_user_perm( 'blog_post!'.$status_key, 'create', false, $this->ID ) )
{ // This status is allowed for this collection and current has a permission:
$allowed_status = $status_key;
break;
}
}
if( $allowed_status === NULL )
{ // Use max allowed status if it could not be found above:
$allowed_status = $max_allowed_status;
}
return $allowed_status;
}
/**
* Get default category ID of the current collection
*
* @todo fp> this is a super lame stub, but it's still better than nothing. Should be user configurable.
*
* @return integer Chapter ID
*/
function get_default_cat_ID()
{
global $DB, $Settings;
if( empty( $this->default_cat_ID ) )
{
if( $default_cat_ID = $this->get_setting( 'default_cat_ID' ) )
{ // A specific cat has previosuly been configured as the default:
// Try to get it from the DB (to make sure it exists and is in the right collection and not meta):
$SQL = new SQL( 'Check default category ID of collection #'.$this->ID );
$SQL->SELECT( 'cat_ID' );
$SQL->FROM( 'T_categories' );
$SQL->WHERE( 'cat_ID = '.$DB->quote( $default_cat_ID ) );
$SQL->WHERE_and( 'cat_blog_ID = '.$this->ID );
$SQL->WHERE_and( 'cat_meta = 0' );
$this->default_cat_ID = $DB->get_var( $SQL );
}
}
if( empty( $this->default_cat_ID ) )
{ // If the previous query has returned NULL
$SQL = new SQL( 'Get auto default category ID of collection #'.$this->ID );
$SQL->SELECT( 'cat_ID' );
$SQL->FROM( 'T_categories' );
$SQL->WHERE( 'cat_blog_ID = '.$this->ID );
$SQL->WHERE_and( 'cat_meta = 0' );
$SQL->LIMIT( '1' );
if( $this->get_setting('category_ordering') == 'manual' )
{ // Manual order
$SQL->SELECT_add( ', IF( cat_order IS NULL, 999999999, cat_order ) AS temp_order' );
$SQL->ORDER_BY( 'cat_parent_ID, temp_order' );
}
else
{ // Alphabetic order
$SQL->ORDER_BY( 'cat_parent_ID, cat_name' );
}
$this->default_cat_ID = $DB->get_var( $SQL );
}
return $this->default_cat_ID;
}
/**
* Get the blog's media directory (and create it if necessary).
*
* If we're {@link is_admin_page() on an admin page}, it adds status messages.
* @todo These status messages should rather go to a "syslog" and not be displayed to a normal user
* @todo dh> refactor this into e.g. create_media_dir() and use it for Blog::get_media_dir, too.
*
* @param boolean Create the directory, if it does not exist yet?
* @return string path string on success, false if the dir could not be created
*/
function get_media_dir( $create = true )
{
global $media_path, $Messages, $Settings, $Debuglog;
if( ! $Settings->get( 'fm_enable_roots_blog' ) )
{ // User directories are disabled:
$Debuglog->add( 'Attempt to access collection media dir, but this feature is globally disabled', 'files' );
return false;
}
switch( $this->media_location )
{
case 'default':
$mediadir = get_canonical_path( $media_path.'blogs/'.$this->urlname.'/' );
break;
case 'subdir':
$mediadir = get_canonical_path( $media_path.$this->media_subdir );
break;
case 'custom':
$mediadir = get_canonical_path( $this->media_fullpath );
break;
case 'none':
default:
$Debuglog->add( 'Attempt to access collection media dir, but this feature is disabled for this colletion', 'files' );
return false;
}
// TODO: use a File object here (to access perms, ..), using FileCache::get_by_root_and_path().
if( $create && ! is_dir( $mediadir ) )
{
// Display absolute path to blog admin and relative path to everyone else
$msg_mediadir_path = check_user_perm( 'blog_admin', 'edit', false, $this->ID ) ? $mediadir : rel_path_to_base( $mediadir );
// TODO: Link to some help page(s) with errors!
if( ! is_writable( dirname($mediadir) ) )
{ // add error
if( is_admin_page() )
{
$Messages->add_to_group( sprintf( T_("Media directory «%s» could not be created, because the parent directory is not writable or does not exist."), $msg_mediadir_path ),
'error', T_('Media directory file permission error').get_manual_link('media-file-permission-errors').':' );
}
return false;
}
elseif( ! evo_mkdir( $mediadir ) )
{ // add error
if( is_admin_page() )
{
$Messages->add_to_group( sprintf( T_("Media directory «%s» could not be created."), $msg_mediadir_path ),
'error', T_('Media directory creation error').get_manual_link('media-file-permission-errors').':' );
}
return false;
}
else
{ // add note:
if( is_admin_page() )
{
$Messages->add_to_group( sprintf( T_("Media directory «%s» has been created with permissions %s."), $msg_mediadir_path, substr( sprintf('%o', fileperms($mediadir)), -3 ) ), 'success', T_('Collection media directories created:') );
}
}
}
return $mediadir;
}
/**
* Get the URL to the media folder
*
* @return string the URL
*/
function get_media_url()
{
global $media_subdir, $Settings, $Debuglog;
if( ! $Settings->get( 'fm_enable_roots_blog' ) )
{ // User directories are disabled:
$Debuglog->add( 'Attempt to access blog media URL, but this feature is disabled', 'files' );
return false;
}
switch( $this->media_location )
{
case 'default':
return $this->get_local_media_url().'blogs/'.$this->urlname.'/';
case 'subdir':
return $this->get_local_media_url().$this->media_subdir;
break;
case 'custom':
return $this->get_protocol_url( $this->media_url );
case 'none':
default:
$Debuglog->add( 'Attempt to access blog media url, but this feature is disabled for this blog', 'files' );
return false;
}
}
/**
* Get link to edit files
*
* @param string link (false on error)
*/
function get_filemanager_link()
{
global $admin_url;
load_class( '/files/model/_fileroot.class.php', 'FileRoot' );
return $admin_url.'?ctrl=files&root='.FileRoot::gen_ID( 'collection', $this->ID );
}
/**
* Get URL to display the blog with a temporary skin.
*
* This is used to construct the various RSS/Atom feeds
*
* @param string Skin folder name
* @param string Additional params
* @param boolean Halt on unknown feed skin
* @return string|false URL or FALSE if none feed skin is not installed in system
*/
function get_tempskin_url( $skin_folder_name, $additional_params = '', $halt_on_error = false )
{
$SkinCache = & get_SkinCache();
if( ! $Skin = & $SkinCache->get_by_folder( $skin_folder_name, $halt_on_error ) )
{ // If no requested skin try to fallback to first found feed skin:
$SkinCache->load_by_type( 'feed' );
$skin_folder_name = false;
foreach( $SkinCache->cache as $Skin )
{
if( $Skin->type == 'feed' )
{ // Use the first found feed skin:
$skin_folder_name = $Skin->folder;
break;
}
}
if( $skin_folder_name === false )
{ // No feed skin found:
return false;
}
}
return url_add_param( $this->gen_blogurl( 'default' ), 'tempskin='.$skin_folder_name );
}
/**
* Get URL to display the blog posts in an XML feed.
*
* @param string
*/
function get_item_feed_url( $skin_folder_name )
{
return $this->get_tempskin_url( $skin_folder_name );
}
/**
* Get URL to display the blog comments in an XML feed.
*
* @param string
* @return string|false URL or FALSE if none feed skin is not installed in system
*/
function get_comment_feed_url( $skin_folder_name )
{
$tempskin_url = $this->get_tempskin_url( $skin_folder_name );
return ( $tempskin_url ? url_add_param( $tempskin_url, 'disp=comments' ) : false );
}
/**
* Callback function for footer_text()
* @param array
* @return string
*/
function replace_callback( $matches )
{
global $localtimenow;
switch( $matches[1] )
{
case 'year':
// for copyrigth year
return date( 'Y', $localtimenow );
case 'publisher':
$publisher_name = $this->get_setting( 'publisher_name' );
if( ! empty( $publisher_name) )
{
return $publisher_name;
}
// No break, use owner instead
case 'owner':
/**
* @var User
*/
$owner_User = $this->get_owner_User();
// Full name gets priority over prefered name because it makes more sense for DEFAULT copyright.
// Blog owner can set WHATEVER footer text she wants through the admin interface.
$owner = $owner_User->get( 'fullname' );
if( empty($owner) )
{
$owner = $owner_User->get_preferred_name();
}
return $owner;
default:
return $matches[1];
}
}
/**
* Get a param.
*
* @param string Parameter name
* @param array Additional params
* @return false|string The value as string or false in case of error (e.g. media dir is disabled).
*/
function get( $parname, $params = array() )
{
global $xmlsrv_url, $basehost, $baseurl, $basepath, $media_url, $current_User, $Settings, $Debuglog, $Session;
if( gettype( $params ) != 'array' )
{
debug_die('wrong $params');
}
$params = array_merge( array(
'glue' => '&',
'url_suffix' => '', // additional url params are appended at the end
), $params );
switch( $parname )
{
case 'access_type':
$access_type_value = parent::get( $parname );
if( $access_type_value == 'subdom' && is_valid_ip_format( $basehost ) )
{ // Don't allow subdomain for IP address:
$access_type_value = 'index.php';
}
return $access_type_value;
case 'blogurl': // Deprecated
case 'link': // Deprecated
case 'url':
return $this->gen_blogurl( 'default' );
case 'baseurl':
return $this->gen_baseurl();
case 'customizer_url':
if( check_user_perm( 'blog_properties', 'edit', false, $this->ID ) ||
( $Settings->get( 'site_skins_enabled' ) && check_user_perm( 'options', 'edit' ) ) )
{ // Return customizer URL only if current User can edit skin settings of collection or site:
if( ! empty( $params['customizing_url'] ) )
{ // Get customizing URL from passed param:
$customizing_url = $params['customizing_url'];
}
elseif( get_param( 'customizing_url' ) != '' )
{ // Get customizing URL from currently provided _GET param 'customizing_url':
$customizing_url = get_param( 'customizing_url' );
}
else
{ // Use current URL for customizing URL:
$customizing_url = get_current_url();
}
if( $customizing_url == '#baseurl#' )
{ // Use base URL of this collection:
$customizing_url = $this->get( 'baseurl' );
}
$customizer_mode_param = ( isset( $params['mode'] ) ? 'customizer_mode='.$params['mode'].$params['glue'] : '' );
$customizer_view_param = ( isset( $params['view'] ) ? 'view='.$params['view'].$params['glue'] : '' );
return get_customizer_url().'?'.$customizer_mode_param.$customizer_view_param.'blog='.$this->ID.$params['glue'].'customizing_url='.urlencode( $customizing_url );
}
else
{ // Return this collection URL instead:
return $this->get( 'url' );
}
case 'baseurlroot':
return $this->get_baseurl_root();
case 'recentpostsurl':
$disp_param = 'posts';
break;
case 'lastcommentsurl':
$disp_param = 'comments';
break;
case 'searchurl':
$disp_param = 'search';
break;
case 'arcdirurl':
$disp_param = 'arcdir';
break;
case 'catdirurl':
$disp_param = 'catdir';
break;
case 'postidxurl':
$disp_param = 'postidx';
break;
case 'mediaidxurl':
$disp_param = 'mediaidx';
break;
case 'sitemapurl':
$disp_param = 'sitemap';
break;
case 'msgformurl':
$disp_param = 'msgform';
break;
case 'profileurl':
$disp_param = 'profile';
break;
case 'avatarurl':
$disp_param = 'avatar';
break;
case 'pwdchangeurl':
$disp_param = 'pwdchange';
break;
case 'userprefsurl':
$disp_param = 'userprefs';
break;
case 'closeaccounturl':
$disp_param = 'closeaccount';
break;
case 'subsurl':
$disp_param = 'subs';
$params['url_suffix'] .= '#subs';
break;
case 'register_finishurl':
$disp_param = 'register_finish';
break;
case 'userurl':
$disp_param = 'user';
break;
case 'usersurl':
$disp_param = 'users';
break;
case 'visitsurl':
$disp_param = 'visits';
break;
case 'tagsurl':
$disp_param = 'tags';
break;
case 'termsurl':
$disp_param = 'terms';
break;
case 'loginurl':
case 'registerurl':
case 'lostpasswordurl':
case 'activateinfourl':
case 'access_requires_loginurl':
case 'content_requires_loginurl':
$url_disp = str_replace( 'url', '', $parname );
if( $login_Blog = & get_setting_Blog( 'login_blog_ID', $this ) )
{ // Use special blog for login/register actions if it is defined in general settings
$url = url_add_param( $login_Blog->gen_blogurl(), 'disp='.$url_disp, $params['glue'] );
}
else
{ // Use login/register urls of this blog
$url = url_add_param( $this->gen_blogurl(), 'disp='.$url_disp, $params['glue'] );
}
if( ! empty( $params['url_suffix'] ) )
{ // Append url suffix
$url = url_add_param( $url, $params['url_suffix'], $params['glue'] );
}
$url = force_https_url( $url, 'login' );
return $url;
case 'threadsurl':
$disp_param = 'threads';
break;
case 'messagesurl':
$disp_param = 'messages';
break;
case 'contactsurl':
$disp_param = 'contacts';
break;
case 'flaggedurl':
$disp_param = 'flagged';
break;
case 'mustreadurl':
$disp_param = 'mustread';
break;
case 'helpurl':
if( $this->get_setting( 'help_link' ) == 'slug' )
{
return url_add_tail( $this->gen_blogurl(), '/help' );
}
else
{
$disp_param = 'help';
break;
}
case 'skin_ID':
return $this->get_skin_ID();
case 'description': // RSS wording
case 'shortdesc':
return $this->shortdesc;
case 'rdf_url':
return $this->get_item_feed_url( '_rdf' );
case 'rss_url':
return $this->get_item_feed_url( '_rss' );
case 'rss2_url':
return $this->get_item_feed_url( '_rss2' );
case 'atom_url':
return $this->get_item_feed_url( '_atom' );
case 'comments_rdf_url':
return $this->get_comment_feed_url( '_rdf' );
case 'comments_rss_url':
return $this->get_comment_feed_url( '_rss' );
case 'comments_rss2_url':
return $this->get_comment_feed_url( '_rss2' );
case 'comments_atom_url':
return $this->get_comment_feed_url( '_atom' );
case 'rsd_url':
return $this->get_local_xmlsrv_url().'rsd.php?blog='.$this->ID;
/* Add the html for a blog-specified stylesheet
* All stylesheets will be included if the blog settings allow it
* and the file "style.css" exists. CSS rules say that the latter style sheets can
* override earlier stylesheets.
*/
case 'blog_css':
if( $this->allowblogcss
&& file_exists( $this->get_media_dir(false).'style.css' ) )
{
return '<link rel="stylesheet" href="'.$this->get_media_url().'style.css" type="text/css" />';
}
else
{
return '';
}
/* Add the html for a user-specified stylesheet
* All stylesheets will be included if the blog settings allow it
* and the file "style.css" exists. CSS rules say that the latter style sheets can
* override earlier stylesheets. A user-specified stylesheet will
* override a blog-specified stylesheet which will override a skin stylesheet.
*/
case 'user_css':
if( $this->allowusercss
&& isset( $current_User )
&& file_exists( $current_User->get_media_dir(false).'style.css' ) )
{
return '<link rel="stylesheet" href="'.$current_User->get_media_url().'style.css" type="text/css" />';
}
else
{
return '';
}
case 'normal_skin_ID':
case 'mobile_skin_ID':
case 'tablet_skin_ID':
case 'alt_skin_ID':
$result = parent::get( $parname );
if( $parname == 'mobile_skin_ID' || $parname == 'tablet_skin_ID' || $parname == 'alt_skin_ID' )
{
if( empty( $result ) && ! ( isset( $params['real_value'] ) && $params['real_value'] ) )
{ // Empty values(NULL, 0, '0', '') means that use the same as normal case:
$result = $this->get( 'normal_skin_ID' );
}
}
return $result;
case 'collection_image':
$FileCache = & get_FileCache();
if( $collection_image_ID = $this->get_setting( 'collection_logo_file_ID' ) )
{
if( $collection_image_File = & $FileCache->get_by_ID( $collection_image_ID, false, false ) )
{
return $collection_image_File;
}
}
return NULL;
case 'collection_favicon':
$FileCache = & get_FileCache();
if( $collection_favicon_ID = $this->get_setting( 'collection_favicon_file_ID' ) )
{
if( $collection_favicon_File = & $FileCache->get_by_ID( $collection_favicon_ID, false, false ) )
{
return $collection_favicon_File;
}
}
return NULL;
default:
// All other params:
return parent::get( $parname );
}
if( ! empty( $disp_param ) )
{ // Get url depending on value of param 'disp'
$this_Blog = & $this;
if( in_array( $disp_param, array( 'threads', 'messages', 'contacts', 'msgform', 'user', 'profile', 'avatar', 'pwdchange', 'userprefs', 'subs', 'register_finish', 'visits', 'closeaccount' ) ) )
{ // Check if we can use this blog for messaging actions or we should use spec blog
if( $msg_Blog = & get_setting_Blog( 'msg_blog_ID' ) )
{ // Use special blog for messaging actions if it is defined in general settings
$this_Blog = & $msg_Blog;
}
}
if( $this_Blog->get_setting( 'front_disp' ) == $disp_param )
{ // Get home page of this blog because front page displays current disp:
$url = $this_Blog->gen_blogurl( 'default' );
}
elseif( $disp_param == 'user' && ( isset( $params['user_login'] ) || isset( $params['user_ID'] ) ) )
{ // Use alias if user login or ID is provided:
$UserCache = & get_UserCache();
if( ! isset( $params['user_ID'] ) &&
( $this_Blog->get_setting( 'user_links' ) == 'params' || $this_Blog->get_setting( 'user_links' ) == 'prefix_id' ) )
{ // We need get user ID by login:
if( $param_User = & $UserCache->get_by_login( $params['user_login'] ) )
{ // Set user ID if it is detected by login:
$params['user_ID'] = $param_User->ID;
}
else
{ // Wrong request:
debug_die( 'Undefined param "user_ID" for Blog->get( "userurl" )' );
}
}
if( ! isset( $params['user_login'] ) &&
$this_Blog->get_setting( 'user_links' ) == 'prefix_login' )
{ // We need get user login by ID:
if( $param_User = & $UserCache->get_by_ID( $params['user_ID'], false, false ) )
{ // Use login if user is detected in DB:
$params['user_login'] = $param_User->get( 'login' );
}
else
{ // Wrong request:
debug_die( 'Undefined param "user_login" for Blog->get( "userurl" )' );
}
}
if( $this_Blog->get_setting( 'user_links' ) == 'params' || $this_Blog->get_setting( 'user_prefix' ) == '' )
{ // Use params E-g: ?disp=user&user_ID=4
$url = url_add_param( $this_Blog->gen_blogurl(), 'disp=user'.$params['glue'].'user_ID='.$params['user_ID'], $params['glue'] );
}
elseif( $this_Blog->get_setting( 'user_links' ) == 'prefix_id' )
{ // Use prefix with user ID:
$url = url_add_tail( $this_Blog->gen_blogurl(), '/'.$this_Blog->get_setting( 'user_prefix' ).':'.$params['user_ID'] );
}
else // 'prefix_login'
{ // Use prefix with user login:
$url = url_add_tail( $this_Blog->gen_blogurl(), '/'.$this_Blog->get_setting( 'user_prefix' ).':'.$params['user_login'] );
}
}
else
{ // Add disp param to blog's url when current disp is not a front page:
$url = url_add_param( $this_Blog->gen_blogurl(), 'disp='.$disp_param, $params['glue'] );
}
if( $disp_param == 'pwdchange' || $disp_param == 'register_finish' )
{ // Force these pages to https if it is required by setting "Require SSL":
$url = force_https_url( $url, 'login' );
}
if( ! empty( $params['url_suffix'] ) )
{ // Append url suffix
$url = url_add_param( $url, $params['url_suffix'], $params['glue'] );
}
return $url;
}
}
/**
* Get warning message about the enabled advanced perms for those cases when we grant some permission for anonymous users which can be restricted for logged in users
*
* @return mixed NULL if advanced perms are not enabled in this blog, the warning message otherwise
*/
function get_advanced_perms_warning()
{
global $admin_url;
if( $this->get( 'advanced_perms' ) )
{
$warning = T_('ATTENTION: advanced <a href="%s">user</a> & <a href="%s">group</a> permissions are enabled and some logged in users may have less permissions than anonymous users.');
$advanced_perm_url = url_add_param( $admin_url, 'ctrl=coll_settings&blog='.$this->ID.'&tab=' );
return ' <b class="warning text-danger">'.sprintf( $warning, $advanced_perm_url.'perm', $advanced_perm_url.'permgroup' ).'</b>';
}
return NULL;
}
/**
* Get a setting.
*
* @param string setting name
* @param boolean true to return param's real value
* @return string|false|NULL value as string on success; NULL if not found; false in case of error
*/
function get_setting( $parname, $real_value = false )
{
global $Settings;
$this->load_CollectionSettings();
$result = $this->CollectionSettings->get( $this->ID, $parname );
switch( $parname )
{
case 'moderation_statuses':
case 'post_moderation_statuses':
if( $result === NULL )
{ // moderation_statuses was not set yet, set the default value, which depends from the blog type
$default = 'review,draft';
$result = ( $this->type == 'forum' ) ? 'community,protected,'.$default : $default;
}
break;
case 'comment_inskin_statuses':
case 'post_inskin_statuses':
if( $result === NULL )
{ // inskin_statuses was not set yet, set the default value, which depends from the blog type
$default = 'published,community,protected,private,review';
$result = ( $this->type == 'forum' ) ? $default.',draft' : $default;
}
break;
case 'default_post_status':
case 'new_feedback_status':
if( $result === NULL )
{ // Default post/comment status was not set yet, use a default value corresponding to the blog type
$result = ( $this->type == 'forum' ) ? 'review' : 'draft';
}
break;
case 'aggregate_coll_IDs':
if( ! empty( $result ) && ( $result != '-' ) && ( $result != '*') )
{
$coll_IDs = explode( ',', $result );
if( ! in_array( $this->ID, $coll_IDs ) )
{
array_push( $coll_IDs, $this->ID );
$result = implode( ',', $coll_IDs );
}
}
break;
case 'msgform_subject_options':
$subject_list = utf8_trim( $this->get_setting( 'msgform_subject_list' ) );
$result = array();
if( ! empty( $subject_list ) )
{
$subject_list = explode( "\n", str_replace( "\r", '', $subject_list ) );
foreach( $subject_list as $subject_option )
{
if( utf8_trim( $subject_option ) != '' )
{ // Use only not empty line:
$result[ $subject_option ] = $subject_option;
}
}
}
break;
case 'webmentions':
if( $this->get_setting( 'allow_access' ) != 'public' )
{ // Disable receiving of webmentions for not public collections:
$result = 0;
}
break;
case 'ping_plugins':
if( $this->get_setting( 'allow_access' ) != 'public' )
{ // Disable ping plugins for not public collections:
$result = '';
}
break;
case 'social_media_image':
if( $result === NULL )
{
$FileCache = & get_FileCache();
$File = & $FileCache->get_by_ID( $this->get_setting( 'social_media_image_file_ID' ), false, false );
if( $File )
{
return $File;
}
}
break;
case 'allow_crosspost_urls':
if( ! $this->get_setting( 'canonical_item_urls' ) )
{ // When "301 redirect to canonical URL" is disabled then we always must NOT do 301 redirect cross-posted Items:
return 1;
}
break;
}
return $result;
}
/**
* Get a ready-to-display setting from the DB settings table.
*
* Same as disp but don't echo
*
* @param string Name of setting
* @param string Output format, see {@link format_to_output()}
*/
function dget_setting( $parname, $format = 'htmlbody' )
{
$this->load_CollectionSettings();
return format_to_output( $this->CollectionSettings->get( $this->ID, $parname ), $format );
}
/**
* Display a setting from the DB settings table.
*
* @param string Name of setting
* @param string Output format, see {@link format_to_output()}
*/
function disp_setting( $parname, $format = 'htmlbody' )
{
$this->load_CollectionSettings();
echo format_to_output( $this->CollectionSettings->get( $this->ID, $parname ), $format );
}
/**
* Set a setting.
*
* @return boolean true, if the value has been set, false if it has not changed.
*/
function set_setting( $parname, $value, $make_null = false )
{
// Make sure collection settings are loaded
$this->load_CollectionSettings();
if( $make_null && empty($value) )
{
$value = NULL;
}
return $this->CollectionSettings->set( $this->ID, $parname, $value );
}
/**
* Delete a setting.
*
* @return boolean true, if the value has been set, false if it has not changed.
*/
function delete_setting( $parname )
{
// Make sure collection settings are loaded
$this->load_CollectionSettings();
return $this->CollectionSettings->delete( $this->ID, $parname );
}
/**
* Make sure collection settings are loaded.
*/
function load_CollectionSettings()
{
if( ! isset( $this->CollectionSettings ) )
{
load_class( 'collections/model/_collsettings.class.php', 'CollectionSettings' );
$this->CollectionSettings = new CollectionSettings(); // COPY (function)
}
}
/**
* Insert into the DB
*
* @return boolean Result
*/
function dbinsert()
{
global $DB, $Plugins, $Settings;
// Set default skins on creating new collection:
$skin_types = array( 'normal', 'mobile', 'tablet', 'alt' );
foreach( $skin_types as $skin_type )
{
$skin_ID = $this->get( $skin_type.'_skin_ID', array( 'real_value' => true ) );
if( empty( $skin_ID ) )
{ // Only if skin is not selected during creating:
$default_skin_ID = $Settings->get( 'def_'.$skin_type.'_skin_ID' );
if( ! empty( $default_skin_ID ) )
{ // And if default skin is defined for the skin type:
$this->set( $skin_type.'_skin_ID', $default_skin_ID );
}
}
}
$DB->begin();
if( $this->get( 'order' ) == 0 )
{ // Set an order as max value of previous order + 1 if it is not defined yet
$SQL = new SQL( 'Get max collection order' );
$SQL->SELECT( 'MAX( blog_order )' );
$SQL->FROM( 'T_blogs' );
$max_order = intval( $DB->get_var( $SQL ) );
$this->set( 'order', $max_order + 1 );
}
$set_default_blog_ID = isset( $Settings );
if( $Settings->get( 'default_blog_ID' ) == -1 || get_setting_Blog( 'default_blog_ID' ) )
{ // Don't set a default collection if it is already defined and the collection exists in DB OR back-office page is used for this:
$set_default_blog_ID = false;
}
if( parent::dbinsert() )
{
// Reset "all_loaded" flag in order to allow getting new created collection by ID:
$BlogCache = & get_BlogCache();
$BlogCache->all_loaded = false;
if( $set_default_blog_ID )
{ // Use this blog as default because it is probably first created
$Settings->set( 'default_blog_ID', $this->ID );
$Settings->dbupdate();
}
if( isset( $this->CollectionSettings ) )
{
// So far all settings have been saved to collection #0 !
// Update the settings: hackish but the base class should not even store this value actually...
// dh> what do you mean? What "base class"? Is there a problem with CollectionSettings?
$this->CollectionSettings->cache[$this->ID] = $this->CollectionSettings->cache[0];
unset( $this->CollectionSettings->cache[0] );
$this->CollectionSettings->dbupdate();
}
// Update locales:
if( empty( $this->locales ) )
{ // Don't forget to store main locale in extra locales table:
$this->locales = array( $this->get( 'locale' ) => NULL );
}
$this->update_locales();
if( $this->base_collection_ID == 0 )
{
$default_post_type_ID = $this->get_setting( 'default_post_type' );
if( ! empty( $default_post_type_ID ) )
{ // Enable post type that is used by default for this collection:
global $DB;
$DB->query( 'INSERT INTO T_items__type_coll
( itc_ityp_ID, itc_coll_ID )
VALUES ( '.$DB->quote( $default_post_type_ID ).', '.$DB->quote( $this->ID ).' )' );
}
// Enable default item types for the inserted collection:
$this->enable_default_item_types();
}
else
{
// Enable default item types for the inserted collection from base collection settings:
$this->enable_duplicate_item_types();
}
// Owner automatically favorite the collection
$this->favorite( $this->owner_user_ID, 1 );
// All users automatically favorite the new blog if collection count < 5 and user count <= 10
load_funcs( 'tools/model/_system.funcs.php' );
$blog_count = count( system_get_blog_IDs( false ) );
$user_IDs = system_get_user_IDs();
$user_count = count( $user_IDs );
if( $blog_count < 5 && $user_count <= 10 )
{
foreach( $user_IDs as $id )
{
$this->favorite( $id, 1 );
}
}
$Plugins->trigger_event( 'AfterCollectionInsert', $params = array( 'Blog' => & $this ) );
$DB->commit();
// Create collection media directory:
$this->get_media_dir();
return true;
}
$DB->rollback();
return false;
}
/**
* Create a new blog...
*
* @param string Kind of blog ( 'std', 'photo', 'group', 'forum' )
* @param array Params
*/
function create( $kind = '', $params = array() )
{
global $DB, $Messages, $basepath, $admin_url, $Settings;
$params = array_merge( array(
'create_demo_contents' => false,
'create_demo_users' => false,
'create_demo_org' => false,
), $params );
$DB->begin();
// DB INSERT
$this->dbinsert();
// Change access mode if a stub file exists:
$stub_filename = 'blog'.$this->ID.'.php';
if( is_file( $basepath.$stub_filename ) )
{ // Stub file exists and is waiting ;)
$DB->query( 'UPDATE T_blogs
SET blog_access_type = "relative", blog_siteurl = "'.$stub_filename.'"
WHERE blog_ID = '.$this->ID );
$Messages->add_to_group( sprintf(T_('The new collection has been associated with the stub file «%s».'), $stub_filename ), 'success', T_('New collection created:') );
}
elseif( $this->get( 'access_type' ) == 'relative' )
{ // Show error message only if stub file should exists!
$Messages->add( sprintf(T_('No stub file named «%s» was found. You must create it for the blog to function properly with the current settings.'), $stub_filename ), 'error' );
}
// Set default user permissions for this collection (All permissions for the collection owner):
if( ! empty( $this->owner_user_ID ) )
{ // Proceed insertion:
$DB->query( 'INSERT INTO T_coll_user_perms
( bloguser_blog_ID, bloguser_user_ID, bloguser_ismember,
bloguser_can_be_assignee, bloguser_workflow_status, bloguser_workflow_user, bloguser_workflow_priority,
bloguser_perm_item_propose, bloguser_perm_poststatuses, bloguser_perm_item_type, bloguser_perm_edit,
bloguser_perm_delpost, bloguser_perm_edit_ts,
bloguser_perm_delcmts, bloguser_perm_recycle_owncmts, bloguser_perm_vote_spam_cmts,
bloguser_perm_cmtstatuses, bloguser_perm_edit_cmt,
bloguser_perm_meta_comment, bloguser_perm_cats, bloguser_perm_properties, bloguser_perm_admin,
bloguser_perm_media_upload, bloguser_perm_media_browse, bloguser_perm_media_change,
bloguser_perm_analytics )
VALUES ( '.$this->ID.', '.$this->owner_user_ID.', 1,
1, 1, 1, 1,
1, "published,community,deprecated,protected,private,review,draft,redirected", "admin", "all",
1, 1,
1, 1, 1,
"published,community,deprecated,protected,private,review,draft", "all",
1, 1, 1, 1,
1, 1, 1,
1 )' );
}
// Create default category:
load_class( 'chapters/model/_chapter.class.php', 'Chapter' );
$edited_Chapter = new Chapter( NULL, $this->ID );
$blog_urlname = $this->get( 'urlname' );
$edited_Chapter->set( 'name', T_('Uncategorized') );
$edited_Chapter->set( 'urlname', $blog_urlname.'-main' );
$edited_Chapter->dbinsert();
$Messages->add_to_group( T_('A default category has been created for this collection.'), 'success', T_('New collection created:') );
// Create demo contents for the new created collection:
// NOTE: This must be done before install default widgets!
if( $params['create_demo_contents'] )
{
global $user_org_IDs;
load_funcs( 'collections/_demo_content.funcs.php' );
$user_org_IDs = NULL;
if( $params['create_demo_org'] && check_user_perm( 'orgs', 'create', false ) )
{ // Create the demo organization
if( $new_demo_organization = create_demo_organization( $this->get( 'owner_user_ID' ) ) )
{
$user_org_IDs = array( $new_demo_organization->ID );
}
}
// Switch to collection locale:
locale_temp_switch( $this->get( 'locale' ) );
$error_messages = array();
if( $params['create_demo_users'] )
{
get_demo_users( true, false, $error_messages );
}
create_sample_content( $kind, $this->ID, $this->get( 'owner_user_ID' ), true, 86400, $error_messages );
if( $error_messages )
{
foreach( $error_messages as $error_message )
{
$Messages->add_to_group( $error_message, 'error', TB_('Demo contents').':' );
}
}
locale_restore_previous();
}
// ADD DEFAULT WIDGETS:
$this->setup_default_widgets();
$Messages->add_to_group( T_('Default widgets have been set-up for this collection.'), 'success', T_('New collection created:') );
$DB->commit();
// set caching
if( $Settings->get( 'newblog_cache_enabled' ) )
{
$result = set_cache_enabled( 'cache_enabled', true, $this->ID );
if( $result != NULL )
{
list( $status, $message ) = $result;
if( $status == 'success' )
{
$Messages->add_to_group( $message, $status, T_('New collection created:') );
}
else
{
$Messages->add( $message, $status );
}
}
}
$this->set_setting( 'cache_enabled_widgets', $Settings->get( 'newblog_cache_enabled_widget' ) );
// Insert default group permissions:
$default_perms_inserted = $this->insert_default_group_permissions();
if( $this->get( 'advanced_perms' ) && $default_perms_inserted )
{ // Display this warning if coolection has the enabled advanced perms AND default permissions have been inserted for at least one group:
$Messages->add( sprintf( T_('ATTENTION: We have set some advanced permissions for this collection. Please verify the <a %s>User permissions</a> and the <a %s>Group permissions</a> now.'),
'href='.$admin_url.'?ctrl=coll_settings&tab=perm&blog='.$this->ID,
'href='.$admin_url.'?ctrl=coll_settings&tab=permgroup&blog='.$this->ID ),
'warning' );
}
// Commit changes in cache:
$BlogCache = & get_BlogCache();
$BlogCache->add( $this );
}
/**
* Duplicate collection to new one
*
* @param boolean TRUE to duplicate categories and posts/items from source collection
* @return boolean Result
*/
function duplicate( $params = array() )
{
global $DB, $current_User;
$params = array_merge( array(
'duplicate_items' => false,
'duplicate_comments' => false,
), $params );
$DB->begin();
// Load all locales and linked collections:
$this->load_locales();
// Remember ID of the duplicated collection and Reset it to allow create new one:
$duplicated_coll_ID = $this->base_collection_ID = $this->ID;
$this->ID = 0;
// Get all fields of the duplicated collection:
$source_fields_SQL = new SQL( 'Get all fields of the duplicating collection #'.$duplicated_coll_ID );
$source_fields_SQL->SELECT( '*' );
$source_fields_SQL->FROM( 'T_blogs' );
$source_fields_SQL->WHERE( 'blog_ID = '.$DB->quote( $duplicated_coll_ID ) );
$source_fields = $DB->get_row( $source_fields_SQL, ARRAY_A );
// Use field values of duplicated collection by default:
foreach( $source_fields as $source_field_name => $source_field_value )
{
// Cut prefix "blog_" of each field:
$source_field_name = substr( $source_field_name, 5 );
if( $source_field_name == 'ID' )
{ // Skip field ID:
continue;
}
if( isset( $this->$source_field_name ) )
{ // Unset current value in order to assing new below, especially to update this in array $this->dbchanges:
unset( $this->$source_field_name );
}
$this->set( $source_field_name, $source_field_value );
}
// Get all settings of the duplicated collection:
$source_settings_SQL = new SQL( 'Get all settings of the duplicating collection #'.$duplicated_coll_ID );
$source_settings_SQL->SELECT( 'cset_name, cset_value' );
$source_settings_SQL->FROM( 'T_coll_settings' );
$source_settings_SQL->WHERE( 'cset_coll_ID = '.$DB->quote( $duplicated_coll_ID ) );
$source_settings = $DB->get_assoc( $source_settings_SQL );
// Use setting values of duplicated collection by default:
foreach( $source_settings as $source_setting_name => $source_setting_value )
{
if( $source_setting_name == 'allow_duplicate' )
{
continue;
}
$this->set_setting( $source_setting_name, $source_setting_value );
}
$blog_urlname = param( 'blog_urlname', 'string', true );
if( ! check_user_perm( 'blog_admin', 'edit', false, $duplicated_coll_ID ) )
{ // validate the urlname, which was already set by init_by_kind() function
// It needs to validated, because the user can not set the blog urlname, and every new blog would have the same urlname without validation.
// When user has edit permission to blog admin part, the urlname will be validated in load_from_request() function.
$this->set( 'urlname', urltitle_validate( empty( $blog_urlname ) ? $this->get( 'urlname' ) : $blog_urlname, '', 0, false, 'blog_urlname', 'blog_ID', 'T_blogs' ) );
}
// Duplicated collection should not have the same siteurl as original collection, set access type to default extrapath
// and empty the siteurl, similar to what a new blank collection have:
global $Settings;
$this->set( 'access_type', $Settings->get( 'coll_access_type' ) );
$this->set( 'siteurl', '' );
// Set collection owner to current user
$this->set( 'owner_user_ID', $current_User->ID );
// Call this firstly to find all possible errors before inserting:
// Also to set new values from submitted form:
if( ! $this->load_from_Request() )
{ // Error on handle new values from form:
$this->ID = $duplicated_coll_ID;
$DB->rollback();
return false;
}
// Try insert new collection in DB:
if( ! $this->dbinsert() )
{ // Error on insert collection in DB:
$this->ID = $duplicated_coll_ID;
$DB->rollback();
return false;
}
// Initialize fields of collection permission tables which must be duplicated:
$coll_perm_fields = '{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';
// Copy all permissions "collection per user" from duplicated collection to new created:
$coll_user_perm_fields = 'bloguser_user_ID, '.str_replace( '{prefix}', 'bloguser_', $coll_perm_fields );
$DB->query( 'INSERT INTO T_coll_user_perms
( bloguser_blog_ID, '.$coll_user_perm_fields.' )
SELECT '.$this->ID.', '.$coll_user_perm_fields.'
FROM T_coll_user_perms
WHERE bloguser_blog_ID = '.$DB->quote( $duplicated_coll_ID ),
'Duplicate all coll-user permissions from collection #'.$duplicated_coll_ID.' to #'.$this->ID );
// Copy all permissions "collection per group" from duplicated collection to new created:
$coll_group_perm_fields = 'bloggroup_group_ID, '.str_replace( '{prefix}', 'bloggroup_', $coll_perm_fields );
$DB->query( 'INSERT INTO T_coll_group_perms
( bloggroup_blog_ID, '.$coll_group_perm_fields.' )
SELECT '.$this->ID.', '.$coll_group_perm_fields.'
FROM T_coll_group_perms
WHERE bloggroup_blog_ID = '.$DB->quote( $duplicated_coll_ID ),
'Duplicate all coll-group permissions from collection #'.$duplicated_coll_ID.' to #'.$this->ID );
// Copy all widgets and containers from duplicated collection to new created:
$SQL = new SQL( 'Get all widget containers of the duplicating collection #'.$duplicated_coll_ID );
$SQL->SELECT( '*' );
$SQL->FROM( 'T_widget__container' );
$SQL->WHERE( 'wico_coll_ID = '.$DB->quote( $duplicated_coll_ID ) );
$widget_containers = $DB->get_results( $SQL, ARRAY_A );
foreach( $widget_containers as $widget_container )
{
$old_wico_ID = $widget_container['wico_ID'];
unset( $widget_container['wico_ID'] );
$widget_container['wico_coll_ID'] = $this->ID;
$r = $DB->query( 'INSERT INTO T_widget__container
( '.implode( ', ', array_keys( $widget_container ) ).' )
VALUES ( '.$DB->quote( $widget_container ).' )',
'Duplicate widget container #'.$old_wico_ID .' from collection #'.$duplicated_coll_ID.' to #'.$this->ID );
if( $r && $DB->insert_id > 0 )
{ // Duplicate all widgets of the inserted container:
$DB->query( 'INSERT INTO T_widget__widget
( wi_wico_ID, wi_order, wi_enabled, wi_type, wi_code, wi_params )
SELECT '.$DB->insert_id.', wi_order, wi_enabled, wi_type, wi_code, wi_params
FROM T_widget__widget
WHERE wi_wico_ID = '.$DB->quote( $old_wico_ID ),
'Duplicate all widgets of container #'.$old_wico_ID.' from collection #'.$duplicated_coll_ID.' to #'.$this->ID );
}
}
if( $params['duplicate_items'] )
{ // Duplicate categories and posts/items:
// Copy all categories from duplicated collection to new created:
$source_cats_SQL = new SQL( 'Get all categories of the duplicating collection #'.$duplicated_coll_ID );
$source_cats_SQL->SELECT( '*' );
$source_cats_SQL->FROM( 'T_categories' );
$source_cats_SQL->WHERE( 'cat_blog_ID = '.$DB->quote( $duplicated_coll_ID ) );
$source_cats = $DB->get_results( $source_cats_SQL, ARRAY_A );
$new_cats = array(); // Store all new created categories with key as ID of copied category in order to correct assign parent IDs
$ChapterCache = & get_ChapterCache();
foreach( $source_cats as $source_cat_fields )
{ // Copy each category separately because of unique field "cat_urlname":
$new_Chapter = & $ChapterCache->new_obj( NULL, $this->ID );
foreach( $source_cat_fields as $source_cat_field_name => $source_cat_field_value )
{
// Cut prefix "cat_" of each field:
$source_cat_field_name = substr( $source_cat_field_name, 4 );
if( $source_cat_field_name == 'ID' || $source_cat_field_name == 'blog_ID' )
{ // Skip these fields, they must be new:
continue;
}
$new_Chapter->set( $source_cat_field_name, $source_cat_field_value );
}
// Insert the duplicated category:
if( $new_Chapter->dbinsert() )
{ // If category has been inserted successfully, then update IDs for correct parent hierarchy:
// Key - ID of copied category, Value - new created category:
$new_cats[ $source_cat_fields['cat_ID'] ] = $new_Chapter;
}
}
foreach( $new_cats as $duplicated_cat_ID => $new_Chapter )
{ // Update wrong parent IDs to IDs of new created categories:
$old_cat_parent_ID = intval( $new_Chapter->get( 'parent_ID' ) );
if( $old_cat_parent_ID > 0 && isset( $new_cats[ $old_cat_parent_ID ] ) )
{
$new_parent_Chapter = $new_cats[ $old_cat_parent_ID ];
$new_Chapter->set( 'parent_ID', $new_parent_Chapter->ID );
$new_Chapter->dbupdate();
}
if( $this->get_setting( 'default_cat_ID' ) == $duplicated_cat_ID )
{ // Update wrong default category with correct ID of new duplicated category:
$this->set_setting( 'default_cat_ID', $new_Chapter->ID );
$this->dbupdate();
}
}
if( ! empty( $new_cats ) )
{ // Duplicate posts if collection has at least one category:
$old_items_SQL = new SQL( 'Get all posts of collection #'.$duplicated_coll_ID.' before duplicating them into collection #'.$this->ID );
$old_items_SQL->SELECT( 'T_items__item.*' );
$old_items_SQL->FROM( 'T_items__item' );
$old_items_SQL->FROM_add( 'INNER JOIN T_categories ON post_main_cat_ID = cat_ID' );
$old_items_SQL->WHERE( 'cat_blog_ID = '.$duplicated_coll_ID );
$old_items_SQL->ORDER_BY( 'post_ID' );
$old_items = $DB->get_results( $old_items_SQL, ARRAY_A );
$new_items = array();
foreach( $old_items as $old_item )
{
$old_item_ID = $old_item['post_ID'];
unset( $old_item['post_ID'] );
if( isset( $new_cats[ $old_item['post_main_cat_ID'] ] ) )
{ // Use correct category ID:
$new_item_Chapter = $new_cats[ $old_item['post_main_cat_ID'] ];
$old_item['post_main_cat_ID'] = $new_item_Chapter->ID;
}
// Get new unique slug:
$old_item['post_urltitle'] = urltitle_validate( $old_item['post_urltitle'], $old_item['post_title'], 0, false, 'slug_title', 'slug_itm_ID', 'T_slug', $old_item['post_locale'], 'T_items__item' );
// Duplicate a post:
$DB->query( 'INSERT INTO T_items__item ( '.implode( ', ', array_keys( $old_item ) ).' ) VALUES ( '.$DB->quote( $old_item ).' )',
'Duplicate from post #'.$old_item_ID );
$new_item_ID = $DB->insert_id;
// Create canonical and tiny slugs:
load_funcs( 'slugs/model/_slug.funcs.php' );
$new_canonical_Slug = new Slug();
$new_canonical_Slug->set( 'title', $old_item['post_urltitle'] );
$new_canonical_Slug->set( 'type', 'item' );
$new_canonical_Slug->set( 'itm_ID', $new_item_ID );
$new_canonical_Slug->dbinsert();
$new_tiny_Slug = new Slug();
$new_tiny_Slug->set( 'title', getnext_tinyurl() );
$new_tiny_Slug->set( 'type', 'item' );
$new_tiny_Slug->set( 'itm_ID', $new_item_ID );
$new_tiny_Slug->dbinsert();
$DB->query( 'UPDATE T_items__item
SET post_canonical_slug_ID = '.$new_canonical_Slug->ID.',
post_tiny_slug_ID = '.$new_tiny_Slug->ID.'
WHERE post_ID = '.$new_item_ID );
$new_items[ $old_item_ID ] = $new_item_ID;
}
// Update parent post IDs with correct IDs of new inserted posts:
$update_parent_items_sql = '';
foreach( $old_items as $old_item )
{
if( ! empty( $old_item['post_parent_ID'] ) && isset( $new_items[ $old_item['post_parent_ID'] ] ) )
{
$update_parent_items_sql .= ' WHEN post_parent_ID = '.$old_item['post_parent_ID'].' THEN '.$new_items[ $old_item['post_parent_ID'] ];
}
}
if( $update_parent_items_sql != '' )
{
$DB->query( 'UPDATE T_items__item
INNER JOIN T_categories ON post_main_cat_ID = cat_ID
SET post_parent_ID = CASE '.$update_parent_items_sql.' ELSE post_parent_ID END
WHERE cat_blog_ID = '.$this->ID );
}
if( ! empty( $new_items ) )
{
$old_items_IDs = $DB->quote( array_keys( $new_items ) );
// Duplicate extra categories:
$old_extra_cats_SQL = new SQL( 'Get all posts categories of collection #'.$duplicated_coll_ID.' before duplicating' );
$old_extra_cats_SQL->SELECT( 'postcat_post_ID, postcat_cat_ID' );
$old_extra_cats_SQL->FROM( 'T_postcats' );
$old_extra_cats_SQL->WHERE( 'postcat_post_ID IN ( '.$old_items_IDs.' )' );
$old_extra_cats = $DB->get_results( $old_extra_cats_SQL, ARRAY_A );
$new_extra_cats_values = array();
foreach( $old_extra_cats as $old_extra_cat )
{
if( isset( $new_items[ $old_extra_cat['postcat_post_ID'] ], $new_cats[ $old_extra_cat['postcat_cat_ID'] ] ) )
{
$new_extra_cats_values[] = '( '.$new_items[ $old_extra_cat['postcat_post_ID'] ].', '.$new_cats[ $old_extra_cat['postcat_cat_ID'] ]->ID.' )';
}
}
if( ! empty( $new_extra_cats_values ) )
{
$DB->query( 'INSERT INTO T_postcats ( '.$old_extra_cats_SQL->get_select( '' ).' ) VALUES '.implode( ', ', $new_extra_cats_values ),
'Duplicate extra categories for posts of collection #'.$duplicated_coll_ID );
}
// Duplicate tags:
$old_tags_SQL = new SQL( 'Get all posts tags of collection #'.$duplicated_coll_ID.' before duplicating' );
$old_tags_SQL->SELECT( 'itag_itm_ID, itag_tag_ID' );
$old_tags_SQL->FROM( 'T_items__itemtag' );
$old_tags_SQL->WHERE( 'itag_itm_ID IN ( '.$old_items_IDs.' )' );
$old_tags = $DB->get_results( $old_tags_SQL, ARRAY_A );
$new_tags_values = array();
foreach( $old_tags as $old_tag )
{
if( isset( $new_items[ $old_tag['itag_itm_ID'] ] ) )
{
$old_tag['itag_itm_ID'] = $new_items[ $old_tag['itag_itm_ID'] ];
$new_tags_values[] = '( '.$DB->quote( $old_tag ).' )';
}
}
if( ! empty( $new_tags_values ) )
{
$DB->query( 'INSERT INTO T_items__itemtag ( '.$old_tags_SQL->get_select( '' ).' ) VALUES '.implode( ', ', $new_tags_values ),
'Duplicate tags for posts of collection #'.$duplicated_coll_ID );
}
// Duplicate settings:
$old_settings_SQL = new SQL( 'Get all posts settings of collection #'.$duplicated_coll_ID.' before duplicating' );
$old_settings_SQL->SELECT( 'iset_item_ID, iset_name, iset_value' );
$old_settings_SQL->FROM( 'T_items__item_settings' );
$old_settings_SQL->WHERE( 'iset_item_ID IN ( '.$old_items_IDs.' )' );
$old_settings = $DB->get_results( $old_settings_SQL, ARRAY_A );
$new_settings_values = array();
foreach( $old_settings as $old_setting )
{
if( isset( $new_items[ $old_setting['iset_item_ID'] ] ) )
{
$old_setting['iset_item_ID'] = $new_items[ $old_setting['iset_item_ID'] ];
$new_settings_values[] = '( '.$DB->quote( $old_setting ).' )';
}
}
if( ! empty( $new_settings_values ) )
{
$DB->query( 'INSERT INTO T_items__item_settings ( '.$old_settings_SQL->get_select( '' ).' ) VALUES '.implode( ', ', $new_settings_values ),
'Duplicate settings for posts of collection #'.$duplicated_coll_ID );
}
// Duplicate links/attachments:
$old_links_SQL = new SQL( 'Get all posts attachments of collection #'.$duplicated_coll_ID.' before duplicating' );
$old_links_SQL->SELECT( 'link_datecreated, link_datemodified, link_creator_user_ID, link_lastedit_user_ID, link_itm_ID, link_file_ID, link_position, link_order' );
$old_links_SQL->FROM( 'T_links' );
$old_links_SQL->WHERE( 'link_itm_ID IN ( '.$old_items_IDs.' )' );
$old_links = $DB->get_results( $old_links_SQL, ARRAY_A );
$new_links_values = array();
foreach( $old_links as $old_link )
{
if( isset( $new_items[ $old_link['link_itm_ID'] ] ) )
{
$old_link['link_itm_ID'] = $new_items[ $old_link['link_itm_ID'] ];
$new_links_values[] = '( '.$DB->quote( $old_link ).' )';
}
}
if( ! empty( $new_links_values ) )
{
$DB->query( 'INSERT INTO T_links ( '.$old_links_SQL->get_select( '' ).' ) VALUES '.implode( ', ', $new_links_values ),
'Duplicate links for posts of collection #'.$duplicated_coll_ID );
}
if( $params['duplicate_comments'] )
{ // Duplicate comments:
$old_comments_SQL = new SQL( 'Get all comments of collection #'.$duplicated_coll_ID.' before duplicating' );
$old_comments_SQL->SELECT( '*' );
$old_comments_SQL->FROM( 'T_comments' );
$old_comments_SQL->WHERE( 'comment_item_ID IN ( '.$old_items_IDs.' )' );
$old_comments = $DB->get_results( $old_comments_SQL, ARRAY_A );
foreach( $old_comments as $old_comment )
{
if( isset( $new_items[ $old_comment['comment_item_ID'] ] ) )
{ // Insert only comments with correct item ID:
$old_comment_ID = $old_comment['comment_ID'];
unset( $old_comment['comment_ID'] );
$old_comment['comment_item_ID'] = $new_items[ $old_comment['comment_item_ID'] ];
$DB->query( 'INSERT INTO T_comments ( '.implode( ', ', array_keys( $old_comment ) ).' ) VALUES ( '.$DB->quote( $old_comment ).' )',
'Duplicate comment #'.$old_comment_ID.' of collection #'.$duplicated_coll_ID );
$new_comment_ID = $DB->insert_id;
$new_comments[ $old_comment_ID ] = $new_comment_ID;
}
}
// Update parent comment IDs with correct IDs of new inserted comments:
$update_parent_comments_sql = '';
foreach( $old_comments as $old_comment )
{
if( ! empty( $old_comment['comment_in_reply_to_cmt_ID'] ) && isset( $new_comments[ $old_comment['comment_in_reply_to_cmt_ID'] ] ) )
{
$update_parent_comments_sql .= ' WHEN comment_in_reply_to_cmt_ID = '.$old_comment['comment_in_reply_to_cmt_ID'].' THEN '.$new_comments[ $old_comment['comment_in_reply_to_cmt_ID'] ];
}
}
if( $update_parent_comments_sql != '' )
{
$DB->query( 'UPDATE T_comments
SET comment_in_reply_to_cmt_ID = CASE '.$update_parent_comments_sql.' ELSE comment_in_reply_to_cmt_ID END
WHERE comment_item_ID IN ( '.$DB->quote( $new_items ).' )' );
}
if( ! empty( $new_comments ) )
{ // Duplicate links/attachments of the comments:
$old_links_SQL = new SQL( 'Get all comments attachments of collection #'.$duplicated_coll_ID.' before duplicating' );
$old_links_SQL->SELECT( 'link_datecreated, link_datemodified, link_creator_user_ID, link_lastedit_user_ID, link_cmt_ID, link_file_ID, link_position, link_order' );
$old_links_SQL->FROM( 'T_links' );
$old_links_SQL->WHERE( 'link_cmt_ID IN ( '.$old_items_IDs.' )' );
$old_links = $DB->get_results( $old_links_SQL, ARRAY_A );
$new_links_values = array();
foreach( $old_links as $old_link )
{
if( isset( $new_comments[ $old_link['link_cmt_ID'] ] ) )
{
$old_link['link_cmt_ID'] = $new_comments[ $old_link['link_cmt_ID'] ];
$new_links_values[] = '( '.$DB->quote( $old_link ).' )';
}
}
if( ! empty( $new_links_values ) )
{
$DB->query( 'INSERT INTO T_links ( '.$old_links_SQL->get_select( '' ).' ) VALUES '.implode( ', ', $new_links_values ),
'Duplicate links for comments of collection #'.$duplicated_coll_ID );
}
}
}
}
}
}
else
{ // Create at least one default category:
load_class( 'chapters/model/_chapter.class.php', 'Chapter' );
$new_Chapter = new Chapter( NULL, $this->ID );
$new_Chapter->set( 'name', T_('Uncategorized') );
$new_Chapter->set( 'urlname', $this->get( 'urlname' ).'-main' );
$new_Chapter->dbinsert();
// Use this single category as default:
$this->set_setting( 'default_cat_ID', $new_Chapter->ID );
$this->dbupdate();
}
// The duplicating is successful, So commit all above changes:
$DB->commit();
// Commit changes in cache:
$BlogCache = & get_BlogCache();
$BlogCache->add( $this );
return true;
}
/**
* Insert default group permissions
*
* @return boolean TRUE on inserting the permissions for at least one group
*/
function insert_default_group_permissions()
{
global $DB, $default_locale;
$groups = array(
'admins' => array( 'ID' => 1, 'name' => 'Administrators' ),
'moderators' => array( 'ID' => 2, 'name' => 'Moderators' ),
'editors' => array( 'ID' => 3, 'name' => 'Editors' ),
'users' => array( 'ID' => 4, 'name' => 'Normal Users' ),
'suspect' => array( 'ID' => 5, 'name' => 'Misbehaving/Suspect Users' ),
'spam' => array( 'ID' => 6, 'name' => 'Spammers/Restricted Users' ),
'blogb' => array( 'ID' => 7, 'name' => 'Blog B Members' ),
);
// Define default group permissions for each group for any collection type:
// NOTE: The fields order should be same in each group array!
$group_permissions = array(
'admins' => array(
'ismember' => 1,
'can_be_assignee' => 1,
'workflow_status' => 1,
'workflow_user' => 1,
'workflow_priority' => 1,
'perm_item_propose' => 1,
'perm_poststatuses' => 'published,community,deprecated,protected,private,review,draft,redirected',
'perm_item_type' => 'admin',
'perm_edit' => 'all',
'perm_delpost' => 1,
'perm_edit_ts' => 1,
'perm_delcmts' => 1,
'perm_recycle_owncmts' => 1,
'perm_vote_spam_cmts' => 1,
'perm_cmtstatuses' => 'published,community,deprecated,protected,private,review,draft',
'perm_edit_cmt' => 'all',
'perm_meta_comment' => 1,
'perm_cats' => 1,
'perm_properties' => 1,
'perm_admin' => 1,
'perm_media_upload' => 1,
'perm_media_browse' => 1,
'perm_media_change' => 1,
'perm_analytics' => 1,
),
'moderators' => array(
'ismember' => 1,
'can_be_assignee' => 1,
'workflow_status' => 1,
'workflow_user' => 1,
'workflow_priority' => 1,
'perm_item_propose' => 1,
'perm_poststatuses' => 'published,community,deprecated,protected,private,review,draft',
'perm_item_type' => 'restricted',
'perm_edit' => 'le',
'perm_delpost' => 1,
'perm_edit_ts' => 1,
'perm_delcmts' => 1,
'perm_recycle_owncmts' => 1,
'perm_vote_spam_cmts' => 1,
'perm_cmtstatuses' => 'published,community,deprecated,protected,private,review,draft',
'perm_edit_cmt' => 'le',
'perm_meta_comment' => 1,
'perm_cats' => 0,
'perm_properties' => 0,
'perm_admin' => 0,
'perm_media_upload' => 1,
'perm_media_browse' => 1,
'perm_media_change' => 1,
'perm_analytics' => 0,
),
'editors' => array(
'ismember' => 1,
'can_be_assignee' => 0,
'workflow_status' => 0,
'workflow_user' => 0,
'workflow_priority' => 0,
'perm_item_propose' => 1,
'perm_poststatuses' => '',
'perm_item_type' => 'standard',
'perm_edit' => 'no',
'perm_delpost' => 0,
'perm_edit_ts' => 1,
'perm_delcmts' => 0,
'perm_recycle_owncmts' => 0,
'perm_vote_spam_cmts' => 1,
'perm_cmtstatuses' => $this->get_setting( 'new_feedback_status' ),
'perm_edit_cmt' => 'no',
'perm_meta_comment' => 1,
'perm_cats' => 0,
'perm_properties' => 0,
'perm_admin' => 0,
'perm_media_upload' => 1,
'perm_media_browse' => 1,
'perm_media_change' => 0,
'perm_analytics' => 0,
)
);
if( $this->type == 'forum' )
{ // Set special permissions for collection with type "Forum"
$group_permissions['editors'] = array(
'ismember' => 1,
'can_be_assignee' => 0,
'workflow_status' => 0,
'workflow_user' => 0,
'workflow_priority' => 0,
'perm_item_propose' => 0,
'perm_poststatuses' => 'community,protected,draft,deprecated',
'perm_item_type' => 'standard',
'perm_edit' => 'own',
'perm_delpost' => 0,
'perm_edit_ts' => 1,
'perm_delcmts' => 0,
'perm_recycle_owncmts' => 0,
'perm_vote_spam_cmts' => 1,
'perm_cmtstatuses' => 'community,protected,review,draft,deprecated',
'perm_edit_cmt' => 'own',
'perm_meta_comment' => 1,
'perm_cats' => 0,
'perm_properties' => 0,
'perm_admin' => 0,
'perm_media_upload' => 1,
'perm_media_browse' => 1,
'perm_media_change' => 0,
'perm_analytics' => 0,
);
$group_permissions['users'] = array(
'ismember' => 1,
'can_be_assignee' => 0,
'workflow_status' => 0,
'workflow_user' => 0,
'workflow_priority' => 0,
'perm_item_propose' => 0,
'perm_poststatuses' => 'community,draft',
'perm_item_type' => 'standard',
'perm_edit' => 'no',
'perm_delpost' => 0,
'perm_edit_ts' => 0,
'perm_delcmts' => 0,
'perm_recycle_owncmts' => 0,
'perm_vote_spam_cmts' => 0,
'perm_cmtstatuses' => 'community,draft',
'perm_edit_cmt' => 'no',
'perm_meta_comment' => 0,
'perm_cats' => 0,
'perm_properties' => 0,
'perm_admin' => 0,
'perm_media_upload' => 1,
'perm_media_browse' => 0,
'perm_media_change' => 0,
'perm_analytics' => 0,
);
$group_permissions['suspect'] = array(
'ismember' => 1,
'can_be_assignee' => 0,
'workflow_status' => 0,
'workflow_user' => 0,
'workflow_priority' => 0,
'perm_item_propose' => 0,
'perm_poststatuses' => 'review,draft',
'perm_item_type' => 'standard',
'perm_edit' => 'no',
'perm_delpost' => 0,
'perm_edit_ts' => 0,
'perm_delcmts' => 0,
'perm_recycle_owncmts' => 0,
'perm_vote_spam_cmts' => 0,
'perm_cmtstatuses' => 'review,draft',
'perm_edit_cmt' => 'no',
'perm_meta_comment' => 0,
'perm_cats' => 0,
'perm_properties' => 0,
'perm_admin' => 0,
'perm_media_upload' => 0,
'perm_media_browse' => 0,
'perm_media_change' => 0,
'perm_analytics' => 0,
);
}
if( $this->type == 'std' && $this->get( 'shortname' ) == 'Blog B' )
{ // Set special permission for group "Blog B Members" for collection "Blog B":
$group_permissions['blogb'] = array(
'ismember' => 1,
'can_be_assignee' => 0,
'workflow_status' => 0,
'workflow_user' => 0,
'workflow_priority' => 0,
'perm_item_propose' => 0,
'perm_poststatuses' => '',
'perm_item_type' => 'standard',
'perm_edit' => 'no',
'perm_delpost' => 0,
'perm_edit_ts' => 0,
'perm_delcmts' => 0,
'perm_recycle_owncmts' => 0,
'perm_vote_spam_cmts' => 0,
'perm_cmtstatuses' => $this->get_setting( 'new_feedback_status' ),
'perm_edit_cmt' => 'no',
'perm_meta_comment' => 0,
'perm_cats' => 0,
'perm_properties' => 0,
'perm_admin' => 0,
'perm_media_upload' => 0,
'perm_media_browse' => 0,
'perm_media_change' => 0,
'perm_analytics' => 0,
);
}
$insert_values = array();
foreach( $groups as $group_key => $group )
{
if( ! isset( $group_permissions[ $group_key ] ) )
{ // Skip group without default permissions:
continue;
}
// Check if the requested group still exists in DB:
$group_SQL = new SQL( 'Check if the requested group still exists in DB' );
$group_SQL->SELECT( 'grp_ID' );
$group_SQL->FROM( 'T_groups' );
$group_SQL->WHERE( 'grp_ID = '.$DB->quote( $group['ID'] ) );
$group_SQL->WHERE_and( 'grp_name = '.$DB->quote( $group['name'] ) );
$group_SQL->WHERE_and( 'grp_name = '.$DB->quote( T_( $group['name'], $default_locale ) ) );
if( ! $DB->get_var( $group_SQL ) )
{ // Skip this group because we cannot find it in DB:
continue;
}
if( ! isset( $insert_fields ) )
{ // Initialize DB field names only first time:
$insert_fields = 'bloggroup_'.implode( ', bloggroup_', array_keys( $group_permissions[ $group_key ] ) );
}
// Initialize permission values for each group:
$insert_values[] = $this->ID.', '.$group['ID'].', "'.implode( '", "', $group_permissions[ $group_key ] ).'"';
}
if( isset( $insert_fields ) )
{ // Insert group permissions into DB:
$r = $DB->query( 'INSERT INTO T_coll_group_perms ( bloggroup_blog_ID, bloggroup_group_ID, '.$insert_fields.' )
VALUES ( '.implode( ' ), ( ', $insert_values ).' )' );
if( $r )
{ // The permissions have been inserted successfully
return true;
}
}
// No permission insertion
return false;
}
/**
* Update the DB based on previously recorded changes
*/
function dbupdate()
{
global $DB, $Plugins, $servertimenow;
$DB->begin();
// Favorite blog by new owner
if( isset( $this->dbchanges['blog_owner_user_ID'] ) )
{
$this->favorite( $this->owner_user_ID, 1 );
}
// URL aliases
if( $this->update_url_aliases )
{
$insert_values = array();
foreach( $this->url_aliases as $alias )
{
if( ! empty( $alias ) )
{
$insert_values[] = '('.$DB->quote( $this->ID ).', '.$DB->quote( $alias ).')';
}
}
// Clear existing URL aliases first
$DB->query( 'DELETE FROM T_coll_url_aliases WHERE cua_coll_ID ='.$DB->quote( $this->ID ) );
if( ! empty( $insert_values ) )
{
$SQL = new SQL( 'Update URL aliases for collection #'.$this->ID );
$SQL = $DB->query( 'INSERT INTO T_coll_url_aliases ( cua_coll_ID, cua_url_alias ) VALUES '.implode( ', ', $insert_values ) );
}
}
parent::dbupdate();
// if this blog settings was modified we need to invalidate this blog's page caches
// this way all existing cached page on this blog will be regenerated during next display
// TODO: Ideally we want to detect if the changes are minor/irrelevant to caching and not invalidate the page cache if not necessary.
// In case of doubt (and for unknown changes), it's better to invalidate.
$this->set_setting( 'last_invalidation_timestamp', $servertimenow );
if( isset( $this->CollectionSettings ) )
{
$this->CollectionSettings->dbupdate();
}
// Update locales:
$this->update_locales();
$Plugins->trigger_event( 'AfterCollectionUpdate', $params = array( 'Blog' => & $this ) );
if( get_param( 'action' ) == 'update_confirm' )
{ // Reduce statuses of posts and comments by max allowed status of this collection ONLY if this has been confirmed:
$this->update_reduced_status_data();
}
$DB->commit();
// BLOCK CACHE INVALIDATION:
BlockCache::invalidate_key( 'set_coll_ID', $this->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
}
/**
* Delete a blog and dependencies from database
*
* @param boolean true if you want to echo progress
*/
function dbdelete( $echo = false )
{
global $DB, $Messages, $Plugins, $Settings;
// Try to obtain some serious time to do some serious processing (5 minutes)
set_max_execution_time(300);
if( $echo ) echo 'Delete collection with all of it\'s content... ';
// remember ID, because parent method resets it to 0
$old_ID = $this->ID;
// Delete main (blog) object:
if( ! parent::dbdelete() )
{
$Messages->add( 'Blog has not been deleted.', 'error' );
return false;
}
// Delete the blog cache folder - try to delete even if cache is disabled
load_class( '_core/model/_pagecache.class.php', 'PageCache' );
$PageCache = new PageCache( $this );
$PageCache->cache_delete();
// Delete blog's media folder recursively:
$FileRootCache = & get_FileRootCache();
if( $root_directory = $FileRootCache->get_root_dir( 'collection', $old_ID ) )
{ // Delete the folder only when it is detected
rmdir_r( $root_directory );
$Messages->add( T_('Deleted blog\'s files'), 'success' );
}
// re-set the ID for the Plugin event
$this->ID = $old_ID;
$Plugins->trigger_event( 'AfterCollectionDelete', $params = array( 'Blog' => & $this ) );
$this->ID = 0;
if( isset( $Settings ) )
{ // Reset settings related to the deleted blog
if( $Settings->get( 'default_blog_ID' ) == $old_ID )
{ // Reset default blog ID
$Settings->set( 'default_blog_ID', 0 );
}
if( $Settings->get( 'info_blog_ID' ) == $old_ID )
{ // Reset info blog ID
$Settings->set( 'info_blog_ID', 0 );
}
if( $Settings->get( 'login_blog_ID' ) == $old_ID )
{ // Reset login blog ID
$Settings->set( 'login_blog_ID', 0 );
}
if( $Settings->get( 'msg_blog_ID' ) == $old_ID )
{ // Reset messaging blog ID
$Settings->set( 'msg_blog_ID', 0 );
}
$Settings->dbupdate();
}
if( $echo ) echo '<br />Done.</p>';
return true;
}
/*
* Template function: display name of blog
*
* Template tag
*/
function name( $params = array() )
{
// Make sure we are not missing any param:
$params = array_merge( array(
'before' => ' ',
'after' => ' ',
'format' => 'htmlbody',
), $params );
if( !empty( $this->name ) )
{
echo $params['before'];
$this->disp( 'name', $params['format'] );
echo $params['after'];
}
}
/*
* Template function: display name of blog
*
* Template tag
*/
function tagline( $params = array() )
{
// Make sure we are not missing any param:
$params = array_merge( array(
'before' => ' ',
'after' => ' ',
'format' => 'htmlbody',
), $params );
if( !empty( $this->tagline ) )
{
echo $params['before'];
$this->disp( 'tagline', $params['format'] );
echo $params['after'];
}
}
/*
* Template function: display name of blog
*
* Template tag
*/
function longdesc( $params = array() )
{
// Make sure we are not missing any param:
$params = array_merge( array(
'before' => ' ',
'after' => ' ',
'format' => 'htmlbody',
), $params );
if( !empty( $this->longdesc ) )
{
echo $params['before'];
$this->disp( 'longdesc', $params['format'] );
echo $params['after'];
}
}
/**
* Get the name of the blog
*
* @return string
*/
function get_name()
{
return $this->name;
}
/**
* Get the short name of the blog
*
* @return sring
*/
function get_shortname()
{
return $this->shortname;
}
/**
* Get the name of the blog limited by length
*
* @param integer Max length
* @return string Limited name
*/
function get_maxlen_name( $maxlen = 50 )
{
return strmaxlen( $this->get_name(), $maxlen, NULL, 'raw' );
}
/**
* Get short and long name of the blog
*
* @return string
*/
function get_extended_name()
{
$names = array();
if( ! empty( $this->shortname ) )
{ // Short name
$names[] = $this->shortname;
}
if( ! empty( $this->name ) )
{ // Title
$names[] = $this->name;
}
return implode( ' - ', $names );
}
/**
* Get skin type which should be used for current session
*
* @return string Skin type
*/
function get_skin_type()
{
global $Session;
if( ! isset( $Session ) )
{ // Session must be defined to autodetect current skin type:
return 'normal';
}
if( $Session->is_mobile_session() )
{
$skin_type = 'mobile';
}
elseif( $Session->is_tablet_session() )
{
$skin_type = 'tablet';
}
elseif( $Session->is_alt_session() )
{
$skin_type = 'alt';
}
else
{
$skin_type = 'normal';
}
if( $skin_type == 'mobile' || $skin_type == 'tablet' || $skin_type == 'alt' )
{ // Check if collection use different mobile/tablet/alt skin or same as normal skin:
$skin_ID = $this->get( $skin_type.'_skin_ID', array( 'real_value' => true ) );
if( empty( $skin_ID ) )
{ // Force to use widgets for normal skin because collection doesn't use different skin for mobile/tablet session:
$skin_type = 'normal';
}
}
return $skin_type;
}
/*
* Get the blog skin ID which correspond to the current session device or which correspond to the selected skin type
*
* @param string Skin type: 'auto', 'normal', 'mobile', 'tablet', 'alt'
* @return integer skin ID
*/
function get_skin_ID( $skin_type = 'auto', $real_value = false )
{
switch( $skin_type )
{
case 'auto':
// Auto detect skin by session type
global $Session;
if( ! empty( $Session ) )
{
if( $Session->is_mobile_session() )
{
return $this->get( 'mobile_skin_ID', array( 'real_value' => $real_value ) );
}
if( $Session->is_tablet_session() )
{
return $this->get( 'tablet_skin_ID', array( 'real_value' => $real_value ) );
}
if( $Session->is_alt_session() )
{
return $this->get( 'alt_skin_ID', array( 'real_value' => $real_value ) );
}
}
return $this->get( 'normal_skin_ID' );
case 'normal':
// Normal skin
return $this->get( 'normal_skin_ID' );
case 'mobile':
// Mobile skin
return $this->get( 'mobile_skin_ID', array( 'real_value' => $real_value ) );
case 'tablet':
// Tablet skin
return $this->get( 'tablet_skin_ID', array( 'real_value' => $real_value ) );
case 'alt':
// Alt skin
return $this->get( 'alt_skin_ID', array( 'real_value' => $real_value ) );
}
// Deny to request invalid skin types
debug_die( 'The requested skin type is invalid.' );
}
/**
* Get distinct skin ids used by the current blog
*
* @return array Ids of skins which are used as normal, mobile, tablet or alt skin with the current Collection
*/
function get_skin_ids()
{
$skin_ids = array( $this->get( 'normal_skin_ID' ) );
if( $this->get( 'mobile_skin_ID' ) > 0 )
{
$skin_ids[] = $this->get( 'mobile_skin_ID' );
}
if( $this->get( 'tablet_skin_ID' ) > 0 )
{
$skin_ids[] = $this->get( 'tablet_skin_ID' );
}
if( $this->get( 'alt_skin_ID' ) > 0 )
{
$skin_ids[] = $this->get( 'alt_skin_ID' );
}
return array_unique( $skin_ids );
}
/**
* Get collection skin containers which correspond to the current session device or which correspond to the selected skin type
*
* @param string Skin type: 'auto', 'normal', 'mobile', 'tablet', 'alt'
* @return array
*/
function get_skin_containers( $skin_type = 'auto' )
{
$SkinCache = & get_SkinCache();
$coll_Skin = & $SkinCache->get_by_ID( $this->get_skin_ID( $skin_type, true ), false, false );
return $coll_Skin ? $coll_Skin->get_containers() : array();
}
/**
* Get collection main containers
*
* @param string Skin type: 'normal', 'mobile', 'tablet', 'alt'
* @param boolean TRUE to initialize IDs of containers
* @return array main container codes => array( name, order, id(optional) )
*/
function get_main_containers( $skin_type = 'normal', $load_container_ids = false )
{
if( ! isset( $this->widget_containers ) )
{ // Initialize
$this->widget_containers = array();
}
if( ! isset( $this->widget_containers[ $skin_type ] ) )
{ // Get widget containers of requested collection skin:
$this->widget_containers[ $skin_type ] = $this->get_skin_containers( $skin_type );
}
if( $load_container_ids &&
$this->ID > 0 &&
empty( $this->widget_containers_ids_loaded[ $skin_type ] ) &&
! empty( $this->widget_containers[ $skin_type ] ) )
{ // Initialize IDs of containers:
global $DB;
$SQL = new SQL( 'Load widget containers data of collection #'.$this->ID );
$SQL->SELECT( 'wico_code, wico_ID' );
$SQL->FROM( 'T_widget__container' );
$SQL->WHERE( 'wico_coll_ID = '.$this->ID );
$SQL->WHERE_and( 'wico_skin_type = '.$DB->quote( $skin_type ) );
$SQL->WHERE_and( 'wico_code IN ( '.$DB->quote( array_keys( $this->widget_containers[ $skin_type ] ) ).' )' );
$containers_data = $DB->get_assoc( $SQL );
foreach( $containers_data as $container_code => $container_ID )
{
if( isset( $this->widget_containers[ $skin_type ][ $container_code ] ) )
{
$this->widget_containers[ $skin_type ][ $container_code ]['ID'] = $container_ID;
}
}
// Set flag to don't load these data twice:
if( ! isset( $this->widget_containers_ids_loaded ) )
{
$this->widget_containers_ids_loaded = array();
}
$this->widget_containers_ids_loaded[ $skin_type ] = true;
}
return $this->widget_containers[ $skin_type ];
}
/**
* Get all collection main containers from either declared skin function or from scanned skin files
*
* @param boolean TRUE to display result messages
* @param string Skin type: 'all', 'normal', 'mobile', 'tablet', 'alt'
*/
function db_save_main_containers( $verbose = false, $skin_type = 'all' )
{
global $DB, $Messages;
$DB->begin();
if( $skin_type == 'all' )
{ // Use all skin types:
$skin_types = array( 'normal', 'mobile', 'tablet', 'alt' );
}
elseif( in_array( $skin_type, array( 'normal', 'mobile', 'tablet', 'alt' ) ) )
{ // Use single skin type:
$skin_types = array( $skin_type );
}
else
{ // Use Normal/Default skin for all other unknown requestes:
$skin_types = array( 'normal' );
}
// Get currently saved collection containers from DB:
$SQL = new SQL( 'Get widget containers for collection #'.$this->ID.' for skin types: "'.implode( '", "', $skin_types ).'"' );
$SQL->SELECT( 'wico_skin_type, wico_code, wico_ID, wico_name, wico_order, COUNT( wi_ID ) AS widgets_count' );
$SQL->FROM( 'T_widget__container' );
$SQL->FROM_add( 'LEFT JOIN T_widget__widget ON wi_wico_ID = wico_ID' );
$SQL->WHERE( 'wico_coll_ID = '.$this->ID );
$SQL->WHERE_and( 'wico_skin_type IN ( '.$DB->quote( $skin_types ).' )' );
$SQL->GROUP_BY( 'wico_ID' );
$coll_containers = $DB->get_results( $SQL );
// Group containers with skin type:
$coll_containers_skin_types = array();
foreach( $coll_containers as $coll_container )
{
$coll_containers_skin_types[ $coll_container->wico_skin_type ][ $coll_container->wico_code ] = array(
'ID' => $coll_container->wico_ID,
'name' => $coll_container->wico_name,
'order' => $coll_container->wico_order,
'count' => $coll_container->widgets_count,
);
}
$SkinCache = & get_SkinCache();
$skin_containers_num = 0;
$created_containers_num = 0;
$updated_containers_num = 0;
$deleted_containers_num = 0;
foreach( $skin_types as $skin_type )
{
if( ! ( $coll_Skin = & $SkinCache->get_by_ID( $this->get( $skin_type.'_skin_ID' ), false, false ) ) )
{ // Skip wrong skin to avoid errors:
continue;
}
// Get default widget containers which are recommended for all skins:
$skin_default_containers = get_skin_default_containers();
// Get skin containers either from declared function or from scaned skin files:
$skin_containers = $coll_Skin->get_containers();
$skin_containers_num += count( $skin_containers );
// Check all main containers and create insert rows for those which are not saved yet,
$update_widget_containers_sql_rows = array();
$new_widget_containers = array();
foreach( $skin_containers as $wico_code => $wico_data )
{
if( ! isset( $coll_containers_skin_types[ $skin_type ][ $wico_code ] ) )
{ // Create only those containers which are not saved yet:
$update_widget_containers_sql_rows[] = '( '.$DB->quote( $wico_code ).', '.$DB->quote( $skin_type ).', '.$DB->quote( $wico_data[0] ).', '.$this->ID.', '.$DB->quote( $wico_data[1] ).', 1 )';
$new_widget_containers[] = $wico_code;
}
else
{ // Check if we should update some container data:
$update_widget_container_sql_data = array();
if( $coll_containers_skin_types[ $skin_type ][ $wico_code ]['name'] != $wico_data[0] )
{ // Update if name is different:
$update_widget_container_sql_data[] = 'wico_name = '.$DB->quote( $wico_data[0] );
}
if( $coll_containers_skin_types[ $skin_type ][ $wico_code ]['order'] != $wico_data[1] )
{ // Update if order is different:
$update_widget_container_sql_data[] = 'wico_order = '.$DB->quote( $wico_data[1] );
}
if( ! empty( $update_widget_container_sql_data ) )
{ // Update different data of the container:
$updated_containers_num += $DB->query( 'UPDATE T_widget__container
SET '.implode( ', ', $update_widget_container_sql_data ).'
WHERE wico_ID = '.$coll_containers_skin_types[ $skin_type ][ $wico_code ]['ID'],
'Update widget #'.$coll_containers_skin_types[ $skin_type ][ $wico_code ]['ID'].' "'.$wico_code.'" of collection #'.$this->ID.' for skin type "'.$skin_type.'"' );
}
}
}
// Delete empty default containers if they are not declared in the Skin:
$delete_widget_containers = array();
foreach( $skin_default_containers as $wico_code => $wico_data )
{
if( ! isset( $skin_containers[ $wico_code ] ) &&
isset( $coll_containers_skin_types[ $skin_type ][ $wico_code ] ) &&
$coll_containers_skin_types[ $skin_type ][ $wico_code ]['count'] == 0 )
{ // Delete ONLY EMPTY default container if it exists in DB but not declared in the Skin (or cannot be found in fallback files of old skins):
$delete_widget_containers[] = $coll_containers_skin_types[ $skin_type ][ $wico_code ]['ID'];
}
}
if( $verbose )
{ // Display how many containers are declared or scanned by the collection skin:
$skin_declared_containers = $coll_Skin->get_declared_containers();
if( $coll_Skin->get_api_version() > 5 || ! empty( $skin_declared_containers ) )
{ // If skin has the declared widget containers:
$Messages->add( sprintf( T_('%d containers declared by skin "%s".'), $skin_containers_num, $coll_Skin->get_name() ), 'note' );
}
else
{ // If skin scans widget containers from skin and fallback files:
$Messages->add( sprintf( T_('WARNING: This is an old skin which provides no container declarations (%s). Falling back to scanning all skin files.'), '<code>function get_declared_containers()</code>' ), 'warning' );
$Messages->add( sprintf( T_('%d containers found by scanning templates of skin "%s" (including fall-back templates).'), $skin_containers_num, $coll_Skin->get_name() ), 'note' );
}
}
if( ! empty( $update_widget_containers_sql_rows ) )
{ // Insert all containers defined by the blog skins into the database
$created_containers_num += $DB->query( 'REPLACE INTO T_widget__container( wico_code, wico_skin_type, wico_name, wico_coll_ID, wico_order, wico_main ) VALUES'
.implode( ', ', $update_widget_containers_sql_rows ),
'Insert new widget containers for collection #'.$this->ID );
}
if( ! empty( $new_widget_containers ) )
{ // Install default widgets:
load_funcs( 'widgets/_widgets.funcs.php' );
$WidgetContainerCache = & get_WidgetContainerCache();
$new_container_messages = array();
foreach( $new_widget_containers as $new_widget_container_code )
{
$new_inserted_widgets_num = install_new_default_widgets( $new_widget_container_code, '*', $this->ID, $skin_type );
$new_WidgetContainer = & $WidgetContainerCache->get_by_coll_skintype_code( $this->ID, $skin_type, $new_widget_container_code );
$new_container_messages[] = sprintf( T_('%s has been added (populated with %d widgets)'),
( $new_WidgetContainer ? $new_WidgetContainer->get_type_title().' "'.$new_WidgetContainer->get( 'name' ).'"' : $new_widget_container_code ),
$new_inserted_widgets_num );
}
}
if( ! empty( $delete_widget_containers ) )
{ // Delete containers which are not used by Skin:
$deleted_containers_num += $DB->query( 'DELETE FROM T_widget__container
WHERE wico_ID IN ( '.$DB->quote( $delete_widget_containers ).' )',
'Delete unwanted empty widget containers from collection #'.$this->ID );
}
}
if( $verbose )
{
if( $created_containers_num > 0 )
{
$Messages->add( sprintf( T_('%d Containers are left untouched and %d Containers have been added:'), ( $skin_containers_num - $created_containers_num - $updated_containers_num - $deleted_containers_num ), $created_containers_num )
.( empty( $new_container_messages ) ? '' : '<ul class="message_group"><li>'.implode( '</li><li>', $new_container_messages ).'</li></ul>' ), 'success' );
}
else
{
$Messages->add( T_('All containers were already created.'), 'success' );
}
if( $updated_containers_num > 0 )
{
$Messages->add( sprintf( T_('%d container(s) were updated.'), $updated_containers_num ), 'success' );
}
if( $deleted_containers_num > 0 )
{
$Messages->add( sprintf( T_('%d container(s) were deleted.'), $deleted_containers_num ), 'success' );
}
}
$DB->commit();
}
/**
* Get skin folder/name by skin type
*
* @param string Force session type: 'auto', 'normal', 'mobile', 'tablet', 'alt'
* @return string Skin folder/name
*/
function get_skin_folder( $skin_type = 'auto' )
{
$blog_skin_ID = $this->get_skin_ID( $skin_type );
if( empty( $blog_skin_ID ) && $skin_type != 'auto' )
{ // Get default skin ID if it is not defined for the selected session type yet
$blog_skin_ID = $this->get_skin_ID( 'auto' );
}
$SkinCache = & get_SkinCache();
$Skin = & $SkinCache->get_by_ID( $blog_skin_ID );
return $Skin->folder;
}
/**
* Resolve user ID of owner
*
* @return User
*/
function & get_owner_User()
{
if( !isset($this->owner_User) )
{
$UserCache = & get_UserCache();
$this->owner_User = & $UserCache->get_by_ID($this->owner_user_ID);
}
return $this->owner_User;
}
/**
* Template tag: display a link leading to the contact form for the owner of the current Blog.
*
* @param array (empty default array is provided for compatibility with v 1.10)
*/
function contact_link( $params = array() )
{
// Make sure we are not missing any param:
$params = array_merge( array(
'before' => ' ',
'after' => ' ',
'text' => 'Contact', // Note: left untranslated, should be translated in skin anyway
'title' => 'Send a message to the owner of this blog...',
'class' => 'contact_link',
'with_redirect'=> false,
), $params );
$contact_url = $this->get_contact_url( $params['with_redirect'] );
if( empty( $contact_url ) )
{ // If contact URL is not available:
return false;
}
echo $params['before'];
echo '<a href="'.$contact_url.'" '
.( $this->get_setting( 'msgform_nofollowto' ) ? 'rel="nofollow" ' : '' )
.'title="'.format_to_output( $params['title'], 'htmlattr' ).'" '
.'class="'.format_to_output( $params['class'], 'htmlattr' ).'">'
.format_to_output( $params['text'] )
.'</a>';
echo $params['after'];
return true;
}
/**
* Template tag: display a link leading to the help page
*
* @param array
*/
function help_link( $params = array() )
{
// Make sure we are not missing any param:
$params = array_merge( array(
'before' => ' ',
'after' => ' ',
'text' => 'Help', // Note: left untranslated, should be translated in skin anyway
'title' => '',
), $params );
echo $params['before'];
echo '<a href="'.$this->get('helpurl').'" title="'.$params['title'].'" class="help_link">'
.$params['text'].'</a>';
echo $params['after'];
return true;
}
/**
* Template tag: display footer text for the current Blog.
*
* @param array
* @return boolean true if something has been displayed
*/
function footer_text( $params )
{
// Make sure we are not missing any param:
$params = array_merge( array(
'before' => ' ',
'after' => ' ',
), $params );
$text = $this->get_setting( 'blog_footer_text' );
$text = preg_replace_callback( '~\$([a-z]+)\$~', array( $this, 'replace_callback' ), $text );
if( empty($text) )
{
return false;
}
echo $params['before'];
echo $text;
echo $params['after'];
return true;
}
/**
* Get URL of message form to contact the owner
*
* @param boolean do we want to redirect back to where we came from after message?
*/
function get_contact_url( $with_redirect = false )
{
$owner_User = & $this->get_owner_User();
if( ! $owner_User->get_msgform_possibility() )
{ // user does not allow contact form
return NULL;
}
$blog_contact_url = $this->get( 'msgformurl', array(
'url_suffix' => 'recipient_id='.$owner_User->ID
) );
if( $with_redirect )
{
if( param( 'redirect_to', 'url', NULL ) !== NULL )
{ // Use current redirect URL:
$redirect_to = get_param( 'redirect_to' );
}
elseif( $owner_User->get_msgform_possibility() != 'login' )
{ // The URL will be made relative on the next page (this is needed when $htsrv_url is on another domain! -- multiblog situation )
$redirect_to = regenerate_url( '', '', '', '&' );
}
else
{ // no email option - try to log in and send private message (only registered users can send PM):
$redirect_to = url_add_param( $this->gen_blogurl(), 'disp=msgform', '&' );
}
$blog_contact_url = url_add_param( $blog_contact_url, 'redirect_to='.rawurlencode( $redirect_to ) );
}
return $blog_contact_url;
}
/**
* Get aggregate coll IDs
*
* @return integer|NULL|array
* - current blog ID if no aggreation
* - NULL if aggreagation of all blogs
* - array of aggreagated blog IDs
*/
function get_aggregate_coll_IDs()
{
$aggregate_coll_IDs = $this->get_setting( 'aggregate_coll_IDs' );
if( empty( $aggregate_coll_IDs ) || $aggregate_coll_IDs == '-' )
{ // No aggregation, return only the current blog:
return $this->ID;
}
elseif( $aggregate_coll_IDs == '*' )
{ // Aggregation of all blogs
return NULL;
}
return explode( ',', $aggregate_coll_IDs );
}
/**
* Get SQL expression to match the list of aggregates collection IDs.
*
* This resolves as follows:
* - empty: current blog only
* - "*": all blogs (returns " 1 " as in "WHERE 1")
* - other: as present in DB
*
* @param string SQL field name
* @param string Force current blog setting 'aggregate_coll_IDs'
* @return string e.g. "$field IN (1,5)". It will return " 1 ", when all blogs/cats are aggregated.
*/
function get_sql_where_aggregate_coll_IDs( $field, $force_coll_IDs = NULL )
{
if( is_null( $force_coll_IDs ) )
{ // Use collection IDs from blog setting
$aggregate_coll_IDs = $this->get_setting( 'aggregate_coll_IDs' );
}
else
{ // Force collections IDs
$aggregate_coll_IDs = $force_coll_IDs;
}
if( empty( $aggregate_coll_IDs ) || $aggregate_coll_IDs == '-' )
{ // We only want posts from the current blog:
return ' '.$field.' = '.$this->ID.' ';
}
elseif( $aggregate_coll_IDs == '*' )
{ // We are aggregating all blogs
return ' 1 ';
}
else
{ // We are aggregating posts from several blogs:
global $DB;
return ' '.$field.' IN ( '.$DB->quote( explode( ',', $aggregate_coll_IDs ) ).' )';
}
}
/**
* Get # of posts for a given tag
*/
function get_tag_post_count( $tag )
{
global $DB;
$sql = 'SELECT COUNT(DISTINCT itag_itm_ID)
FROM T_items__tag INNER JOIN T_items__itemtag ON itag_tag_ID = tag_ID
INNER JOIN T_postcats ON itag_itm_ID = postcat_post_ID
INNER JOIN T_categories ON postcat_cat_ID = cat_ID
WHERE cat_blog_ID = '.$this->ID.'
AND tag_name = '.$DB->quote( utf8_strtolower($tag) );
return $DB->get_var( $sql );
}
/**
* Get the number of items in this collection
* Note: It counts all items with any kind of visibility status
*
* @return integer the number of items
*/
function get_number_of_items()
{
global $DB;
$sql = 'SELECT COUNT(post_ID)
FROM T_items__item WHERE post_main_cat_ID IN (
SELECT cat_ID FROM T_categories
WHERE cat_blog_ID = '.$this->ID.' )';
return $DB->get_var( $sql );
}
/**
* Get the number of comments in this collection
* Note: It counts all comments with any kind of visibility status, except comments in trash
*
* @return integer the number of not recycled comments
*/
function get_number_of_comments()
{
global $DB;
$sql = 'SELECT COUNT(comment_ID)
FROM T_comments
LEFT JOIN T_items__item ON comment_item_ID = post_ID
WHERE comment_status != "trash" AND post_main_cat_ID IN (
SELECT cat_ID FROM T_categories
WHERE cat_blog_ID = '.$this->ID.' )';
return $DB->get_var( $sql );
}
/**
* Get the corresponding ajax form enabled setting
*
* @return boolean true if ajax form is enabled, false otherwise
*/
function get_ajax_form_enabled()
{
if( is_logged_in() )
{
return $this->get_setting( 'ajax_form_loggedin_enabled' );
}
return $this->get_setting( 'ajax_form_enabled' );
}
/**
* Get timestamp value from the setting "timestamp_min"
*
* @return string
*/
function get_timestamp_min()
{
$timestamp_min = $this->get_setting( 'timestamp_min' );
switch ( $timestamp_min )
{
case 'duration': // Set timestamp to show past posts after this date
$timestamp_value = time() - $this->get_setting( 'timestamp_min_duration' );
break;
case 'no': // Don't show past posts
$timestamp_value = 'now';
break;
case 'yes': // Show all past posts
default:
$timestamp_value = '';
break;
}
return $timestamp_value;
}
/**
* Get timestamp value from the setting "timestamp_max"
*
* @return string
*/
function get_timestamp_max()
{
$timestamp_max = $this->get_setting( 'timestamp_max' );
switch ( $timestamp_max )
{
case 'duration': // Set timestamp to show future posts before this date
$timestamp_value = time() + $this->get_setting( 'timestamp_max_duration' );
break;
case 'yes': // Show all future posts
$timestamp_value = '';
break;
case 'no': // Don't show future posts
default:
$timestamp_value = 'now';
break;
}
return $timestamp_value;
}
/**
* Get url to write a new Post
*
* @param integer Category ID
* @param string Post title
* @param string Post urltitle
* @param string Post type usage
* @return string Url to write a new Post
*/
function get_write_item_url( $cat_ID = 0, $post_title = '', $post_urltitle = '', $post_type_usage = '' )
{
$url = '';
if( is_logged_in( false ) ||
( ! is_logged_in() && $this->get_setting( 'post_anonymous' ) ) )
{ // Only logged in and activated users can write a Post,
// Or anonymous user can post if it is allowed with collection setting:
$ChapterCache = & get_ChapterCache();
$selected_Chapter = $ChapterCache->get_by_ID( $cat_ID, false, false );
if( $selected_Chapter &&
( $selected_Chapter->get( 'lock' ) ||
( $cat_ItemType = & $selected_Chapter->get_ItemType() ) === false ) )
{ // Don't allow to create new post with this category if it is locked or no default item type for the category:
return '';
}
if( ! is_logged_in() || check_user_perm( 'blog_post_statuses', 'edit', false, $this->ID ) )
{ // We have permission to add a post with at least one status:
if( $this->get_setting( 'in_skin_editing' ) && ! is_admin_page() )
{ // We have a mode 'In-skin editing' for the current Blog
// User must have a permission to publish a post in this blog
$cat_url_param = '';
if( $selected_Chapter )
{ // Link to create a Item with predefined category
$cat_url_param = '&cat='.$selected_Chapter->ID;
if( empty( $post_type_usage ) &&
( $cat_ItemType = & $selected_Chapter->get_ItemType() ) )
{ // Use predefined Item Type from selected category:
$cat_url_param .= '&item_typ_ID='.$cat_ItemType->ID;
}
}
$url = url_add_param( $this->get( 'url' ), ( is_logged_in() ? 'disp=edit' : 'disp=anonpost' ).$cat_url_param );
}
elseif( check_user_perm( 'admin', 'restricted' ) )
{ // Edit a post from Back-office
global $admin_url;
$url = $admin_url.'?ctrl=items&action=new&blog='.$this->ID;
if( !empty( $cat_ID ) )
{ // Add category param to preselect category on the form
$url = url_add_param( $url, 'cat='.$cat_ID );
}
}
else
{ // User does not have any means to edit the post!
return '';
}
if( !empty( $post_title ) )
{ // Append a post title
$url = url_add_param( $url, 'post_title='.urlencode( $post_title ) );
}
if( !empty( $post_urltitle ) )
{ // Append a post urltitle
$url = url_add_param( $url, 'post_urltitle='.urlencode( $post_urltitle ) );
}
if( ! empty( $post_type_usage ) )
{ // Append a post type ID
global $DB;
$post_type_ID = $DB->get_var( 'SELECT ityp_ID FROM T_items__type WHERE ityp_usage = '.$DB->quote( $post_type_usage ) );
if( ! empty( $post_type_ID ) )
{
$url = url_add_param( $url, 'item_typ_ID='.$post_type_ID );
}
}
}
}
return $url;
}
/**
* Get url to create a new Chapter
*
* @param integer Parent category ID
* @return string Url to create a new Chapter
*/
function get_create_chapter_url( $cat_ID = 0 )
{
$url = '';
if( is_logged_in( false ) )
{ // Only logged in and activated users can write a Post
if( check_user_perm( 'admin', 'restricted' ) &&
check_user_perm( 'blog_cats', 'edit', false, $this->ID ) )
{ // Check permissions to create a new chapter in this blog
global $admin_url;
$url = $admin_url.'?ctrl=chapters&action=new&blog='.$this->ID;
if( ! empty( $cat_ID ) )
{ // Add category param to preselect category on the form:
$url = url_add_param( $url, 'cat_parent_ID='.$cat_ID );
}
if( ! is_admin_page() )
{ // Add this param to redirect after saving to parent category permanent url:
$url = url_add_param( $url, 'redirect_page=parent' );
}
}
}
return $url;
}
/**
* Has current user an access to this collection depending on settings
*
* @return boolean TRUE on success
*/
function has_access( $User = NULL )
{
global $current_User;
if( is_null( $User ) )
{
$User = $current_User;
}
$allow_access = $this->get_setting( 'allow_access' );
if( $allow_access == 'public' )
{ // Everyone has an access to this collection:
return true;
}
if( ! is_logged_in() )
{ // Only logged in users have an access to this collection:
return false;
}
elseif( $allow_access == 'members' && ! $User->check_perm( 'blog_ismember', 'view', false, $this->ID ) )
{ // Current user must be a member of this collection:
return false;
}
return true;
}
/**
* Check if current user has access to this blog depending on settings
*
* @return boolean TRUE on success
*/
function check_access()
{
global $Messages, $skins_path, $ads_current_skin_path, $ReqURL, $disp;
$allow_access = $this->get_setting( 'allow_access' );
if( $allow_access == 'public' )
{ // Everyone has an access to this blog
return true;
}
if( in_array( $disp, array( 'login', 'lostpassword', 'register', 'help', 'msgform', 'access_requires_login', 'content_requires_login' ) ) )
{ // Don't restrict these pages
return true;
}
/**
* $allow_access == 'users' || 'members'
*/
if( ! is_logged_in() )
{ // Only logged in users have an access to this blog
$Messages->add( T_( 'You need to log in before you can access this section.' ), 'error' );
$login_Blog = & get_setting_Blog( 'login_blog_ID' );
if( $login_Blog && $login_Blog->ID != $this->ID )
{ // If this collection is not used for login actions,
// Redirect to login form on "access_requires_login.main.php":
header_redirect( get_login_url( 'no access to blog', NULL, false, NULL, 'access_requires_loginurl' ), 302 );
// will have exited
}
else
{ // This collection is used for login actions
// Don't redirect, just display a login form of this collection:
$disp = 'access_requires_login';
// Set redirect_to param to current url in order to display a requested page after login action:
global $ReqURI;
param( 'redirect_to', 'url', $ReqURI );
}
}
elseif( $allow_access == 'members' )
{ // Check if current user is member of this blog
if( ! check_user_perm( 'blog_ismember', 'view', false, $this->ID ) )
{ // Force disp to restrict access for current user
$disp = 'access_denied';
$Messages->add( T_( 'You are not a member of this section, therefore you are not allowed to access it.' ), 'error' );
$blog_skin_ID = $this->get_skin_ID();
if( ! empty( $blog_skin_ID ) )
{
$SkinCache = & get_SkinCache();
$Skin = & $SkinCache->get_by_ID( $blog_skin_ID );
$ads_current_skin_path = $skins_path.$Skin->folder.'/';
// Use 'access_denied.main.php' instead of real template when current User is not a member of this blog:
$skin_template_name = $ads_current_skin_path.'access_denied.main.php';
if( file_exists( $skin_template_name ) )
{ // Display a special template of this skin
require $skin_template_name;
exit;
}
else
{ // Display a template from site skins
siteskin_init();
siteskin_include( '_access_denied_site.main.php' );
exit;
}
}
}
}
return true;
}
/**
* Check if the media directory or it's location was changed and perform the required data migration
*
* @param string the media directory path before update
* @param string the media directory location before update
* @return boolean true if the media directory was not changed or the change was successful, false otherwise
*/
function check_media_dir_change( $old_media_dir, $old_media_location = NULL )
{
global $Messages;
$new_media_dir = $this->get_media_dir( false );
if( $new_media_dir == $old_media_dir )
{ // The media dir was not changed, no need fo further updates
return true;
}
$new_media_location = $this->get( 'media_location' );
if( $old_media_location == NULL )
{ // Media location was not changed
$old_media_location = $new_media_location;
}
switch( $new_media_location )
{
case 'none':
if( is_empty_directory( $old_media_dir ) )
{ // Delete old media dir if it is empty
if( file_exists( $old_media_dir ) && ( ! rmdir_r( $old_media_dir ) ) )
{
$Messages->add( T_('The old media dir could not be removed, please remove it manually!'), 'warning' );
}
}
else
{ // The old media dir is not empty, but it must be cleared before it can be changed to none
$Messages->add( T_('Blog media folder is not empty, you cannot change it to "None".'), 'error' );
return false;
}
break;
case 'default':
case 'subdir':
case 'custom':
global $media_path;
if( file_exists( $new_media_dir ) )
{ // Don't use the existing folder twice
$Messages->add( sprintf( T_('Folder %s already exists, it cannot be used for several media locations.'), '<b>'.$new_media_dir.'</b>' ), 'error' );
return false;
}
if( in_array( trim( $new_media_dir, '/\\' ), array( $media_path.'blogs', $media_path.'import', $media_path.'shared', $media_path.'users' ) ) )
{ // Don't use the reserved paths
$Messages->add( sprintf( T_('Please use another folder name, because %s is reserved.'), '<b>'.$new_media_dir.'</b>' ), 'error' );
return false;
}
if( $new_media_location == 'custom' )
{ // Check for folder is not used by other blog, and it is not a sub-folder of other blog folder
$BlogCache = & get_BlogCache();
$BlogCache->clear( true );
$BlogCache->load_where( 'blog_ID != '.$this->ID );
$other_blog_IDs = $BlogCache->get_ID_array();
foreach( $other_blog_IDs as $other_blog_ID )
{
$other_Blog = & $BlogCache->get_by_ID( $other_blog_ID, false, false );
$other_media_dir = $other_Blog->get_media_dir( false );
if( ! empty( $other_media_dir ) && strpos( $new_media_dir, $other_media_dir ) === 0 )
{
$Messages->add( sprintf( T_('Please use another folder name, because %s is already used for another media location.'), '<b>'.$new_media_dir.'</b>' ), 'error' );
return false;
}
}
}
if( ( $old_media_location == 'none' ) || ( ! file_exists( $old_media_dir ) ) )
{ // The media folder was not used before, create the new media folder
return $this->get_media_dir( true );
}
if( copy_r( $old_media_dir, $new_media_dir, '', array( '_evocache', '.evocache' ) ) )
{ // The file have been copied to new folder successfully
if( ! rmdir_r( $old_media_dir ) )
{ // Display a warning if old folder could not be deleted
$Messages->add( sprintf( T_('Could not delete the old media folder "%s", please try to delete it manually.'), '<b>'.$old_media_dir.'</b>' ), 'warning' );
}
}
else
{ // Display a message if some error on copying
$Messages->add( sprintf( T_('Could not move the media folder content from "%s" to the new "%s" location.'), '<b>'.$old_media_dir.'</b>', '<b>'.$new_media_dir.'</b>' ), 'error' );
return false;
}
break;
default:
debug_die('Invalid media location setting received!');
}
$Messages->add( T_('The media directory and all of its content were successfully moved to the new location.'), 'note' );
return true;
}
/**
* Get enabled item types for this collection by usage
*
* @param string|NULL Item type usage: 'post', 'page', 'intro-front' and etc.
* @return array
*/
function get_enabled_item_types( $usage = NULL )
{
if( empty( $this->ID ) )
{ // This is new blog, it doesn't have the enabled item types:
return array();
}
if( ! isset( $this->enabled_item_types ) )
{ // Get all enabled item types by one sql query and only first time to cache result:
global $DB;
$SQL = new SQL( 'Get all enabled item types for collection #'.$this->ID );
$SQL->SELECT( 'itc_ityp_ID, ityp_usage' );
$SQL->FROM( 'T_items__type_coll' );
$SQL->FROM_add( 'INNER JOIN T_items__type ON itc_ityp_ID = ityp_ID' );
$SQL->WHERE( 'itc_coll_ID = '.$this->ID );
$this->enabled_item_types = $DB->get_assoc( $SQL );
}
if( $usage === NULL )
{ // Get all item types:
return array_keys( $this->enabled_item_types );
}
else
{ // Restrict item types by requested usage value:
return array_keys( $this->enabled_item_types, $usage );
}
}
/**
* Check if item type is enabled for this collection
*
* @param integer Item type ID
* @return boolean TRUE if enabled
*/
function is_item_type_enabled( $item_type_ID )
{
if( empty( $this->ID ) )
{ // This is new blog, it doesn't have the enabled item types
return false;
}
return in_array( $item_type_ID, $this->get_enabled_item_types() );
}
/**
* Check if item type can be disabled
*
* @param integer Item type ID
* @param boolean TRUE to display a message about restriction
* @return boolean TRUE if can
*/
function can_be_item_type_disabled( $item_type_ID, $display_message = false )
{
if( empty( $this->ID ) )
{ // This is new blog, no restriction to disable any post type
return true;
}
if( $this->get_setting( 'default_post_type' ) == $item_type_ID )
{ // Don't allow to disable an item type which is used as default for this collection:
if( $display_message )
{
global $Messages;
$Messages->add( 'This Item type is used as the default for this collection. Thus you cannot disable it.', 'error' );
}
return false;
}
return true;
}
/**
* Check if this collection has items per requested Item Type
*
* @param integer Item Type ID
* @return boolean TRUE if at least one Item exists with given
*/
function has_items_per_item_type( $item_type_ID )
{
if( ! isset( $this->used_item_types ) )
{ // Get all Item Types which are used for Items in this Collection:
global $DB;
$coll_item_types_SQL = new SQL( 'Get all Item Types which are used for Items of Collection #'.$this->ID );
$coll_item_types_SQL->SELECT( 'post_ityp_ID' );
$coll_item_types_SQL->FROM( 'T_items__item' );
$coll_item_types_SQL->FROM_add( 'INNER JOIN T_categories ON post_main_cat_ID = cat_ID' );
$coll_item_types_SQL->WHERE( 'cat_blog_ID = '.$this->ID );
$coll_item_types_SQL->GROUP_BY( 'post_ityp_ID' );
$this->used_item_types = $DB->get_col( $coll_item_types_SQL );
}
return is_array( $this->used_item_types ) && in_array( $item_type_ID, $this->used_item_types );
}
/**
* Enable default item types for the collection
*/
function enable_default_item_types()
{
if( empty( $this->ID ) )
{ // Collection doesn't exist in DB yet:
return;
}
global $DB, $cache_all_item_type_data;
if( ! isset( $cache_all_item_type_data ) )
{ // Get all item type data only first time to save execution time:
$cache_all_item_type_data = $DB->get_results( 'SELECT ityp_ID, ityp_usage, ityp_name, ityp_template_name FROM T_items__type' );
}
// Decide what "post" item type we can enable depending on collection kind:
$default_post_types_by_template = array( 'recipe' );
$default_post_types = array( 'Post with Custom Fields', 'Child Post', 'Recipe' );
switch( $this->type )
{
case 'minisite':
$default_post_types[] = 'Homepage Content Tab';
break;
case 'main':
$default_post_types[] = 'Post';
$default_post_types[] = 'Homepage Content Tab';
break;
case 'photo':
$default_post_types[] = 'Photo Album';
break;
case 'forum':
$default_post_types = array(); // Don't install the default Item Types(see above) for forums collection.
$default_post_types[] = 'Forum Topic';
$default_post_types[] = 'Task';
break;
case 'manual':
$default_post_types[] = 'Manual Page';
break;
case 'group':
$default_post_types = array(); // Don't install the default Item Types(see above) for Tracker collection.
$default_post_types[] = 'Task';
break;
default: // 'std'
$default_post_types[] = 'Post';
$default_post_types[] = 'Podcast Episode';
break;
}
$enable_post_types = array();
foreach( $cache_all_item_type_data as $item_type )
{
if( $item_type->ityp_usage == 'post' &&
( in_array( $item_type->ityp_name, $default_post_types ) || in_array( $item_type->ityp_template_name, $default_post_types_by_template ) ) &&
! in_array( $item_type->ityp_ID, $enable_post_types ) )
{ // This "post" item type can be enabled:
$enable_post_types[] = $item_type->ityp_ID;
}
}
if( empty( $enable_post_types ) )
{ // Display a warning if we cannot find the default post types for current collection kind:
global $Messages;
$Messages->add( sprintf( T_('The expected item type(s) named %s have not been found. All item types have been enabled for this collection.'), '"'.implode( '", "', $default_post_types ).'"' ), 'warning' );
}
$insert_sql = 'REPLACE INTO T_items__type_coll ( itc_ityp_ID, itc_coll_ID ) VALUES ';
$i = 0;
foreach( $cache_all_item_type_data as $item_type )
{
if( $item_type->ityp_usage == 'post' &&
! empty( $enable_post_types ) &&
! in_array( $item_type->ityp_ID, $enable_post_types ) )
{ // Skip this item type for current collection kind:
continue;
}
if( $i > 0 )
{ // Add separator between rows:
$insert_sql .= ', ';
}
$insert_sql .= '( '.$item_type->ityp_ID.', '.$this->ID.' )';
$i++;
}
if( $i > 0 )
{ // Insert records to enable the default item types for this collection:
$DB->query( $insert_sql );
}
}
/**
* Enable item types for duplicate collection
*/
function enable_duplicate_item_types()
{
if( empty( $this->ID ) )
{ // Collection doesn't exist in DB yet:
return;
}
global $DB, $cache_all_item_type_data;
if( ! isset( $cache_all_item_type_data ) )
{ // Get all item type data only first time to save execution time:
$cache_all_item_type_data = $DB->get_results( 'SELECT ityp_ID, ityp_usage, ityp_name, ityp_template_name FROM T_items__type' );
}
$SQL = new SQL();
$SQL->SELECT( 't.ityp_ID, IF( tb.itc_ityp_ID > 0, 1, 0 ) AS type_enabled, IF( ityp_ID = '.$this->get_setting( 'default_post_type' ).', 1, 0 ) AS type_default' );
$SQL->FROM( 'T_items__type AS t' );
$SQL->FROM_add( 'LEFT JOIN T_items__type_coll AS tb ON itc_ityp_ID = ityp_ID AND itc_coll_ID = '.$this->base_collection_ID.' having type_enabled = 1 ' );
$base_blog_item_types = $DB->get_results($SQL->get());
$enable_post_types = array();
foreach ($base_blog_item_types as $key => $value)
{
$enable_post_types[] = $value->ityp_ID;
}
$insert_sql = 'REPLACE INTO T_items__type_coll ( itc_ityp_ID, itc_coll_ID ) VALUES ';
$i = 0;
foreach( $cache_all_item_type_data as $item_type )
{
if( !in_array( $item_type->ityp_ID, $enable_post_types ) )
{ // Skip this item type for current collection kind:
continue;
}
if( $i > 0 )
{ // Add separator between rows:
$insert_sql .= ', ';
}
$insert_sql .= '( '.$item_type->ityp_ID.', '.$this->ID.' )';
$i++;
}
if( $i > 0 )
{ // Insert records to enable the default item types for this collection:
$DB->query( $insert_sql );
}
}
/**
* Get first Item in Main List on disp=posts
*
* @return object Item
*/
function & get_first_mainlist_Item()
{
$ItemList2 = new ItemList2( $this, $this->get_timestamp_min(), $this->get_timestamp_max(), 1, 'ItemCache', 'first', 'first' );
// Set additional debug info prefix for SQL queries to know what code executes it:
$ItemList2->query_title_prefix = 'Blog->get_first_mainlist_Item()';
// Run the query:
$ItemList2->query();
// Get the expected Item:
$first_mainlist_Item = & $ItemList2->get_item();
return $first_mainlist_Item;
}
/**
* Get data of moderators which must be notified about new/edited comment
*
* @return array Array where each row is array with keys:
* - user_email
* - user_ID
* - notify_comment_moderation
* - notify_edit_cmt_moderation
* - notify_spam_cmt_moderation
*/
function get_comment_moderator_user_data()
{
if( ! isset( $this->comment_moderator_user_data ) )
{ // Get it from DB only first time and then cache in array:
global $DB;
$SQL = new SQL( 'Get list of moderators to notify about new/edited comment of collection #'.$this->ID );
$SQL->SELECT( 'DISTINCT user_email, user_ID, s1.uset_value as notify_comment_moderation, s2.uset_value as notify_edit_cmt_moderation, s3.uset_value as notify_spam_cmt_moderation' );
$SQL->FROM( 'T_users' );
$SQL->FROM_add( 'LEFT JOIN T_users__usersettings AS s1 ON s1.uset_user_ID = user_ID AND s1.uset_name = "notify_comment_moderation"' );
$SQL->FROM_add( 'LEFT JOIN T_users__usersettings AS s2 ON s2.uset_user_ID = user_ID AND s2.uset_name = "notify_edit_cmt_moderation"' );
$SQL->FROM_add( 'LEFT JOIN T_users__usersettings AS s3 ON s3.uset_user_ID = user_ID AND s3.uset_name = "notify_spam_cmt_moderation"' );
$SQL->FROM_add( 'LEFT JOIN T_groups ON grp_ID = user_grp_ID' );
$SQL->WHERE( 'LENGTH( TRIM( user_email ) ) > 0' );
$SQL->WHERE_and( 'user_status IN ( "activated", "autoactivated", "manualactivated" )' );
$SQL->WHERE_and( '( grp_perm_blogs = "editall" )
OR ( user_ID IN ( SELECT bloguser_user_ID FROM T_coll_user_perms WHERE bloguser_blog_ID = '.$this->ID.' AND bloguser_perm_edit_cmt IN ( "anon", "lt", "le", "all" ) ) )
OR ( grp_ID IN ( SELECT bloggroup_group_ID FROM T_coll_group_perms WHERE bloggroup_blog_ID = '.$this->ID.' AND bloggroup_perm_edit_cmt IN ( "anon", "lt", "le", "all" ) ) )' );
$this->comment_moderator_user_data = $DB->get_results( $SQL );
}
return $this->comment_moderator_user_data;
}
/**
* Get data of domain aliases for this collection
*
* @return array Array of domain aliases
*/
function get_url_aliases()
{
if( ! isset( $this->url_aliases ) )
{
global $DB;
$SQL = new SQL( 'Get list of URL aliases of collection #'.$this->ID );
$SQL->SELECT( 'cua_url_alias' );
$SQL->FROM( 'T_coll_url_aliases' );
$SQL->WHERE( 'cua_coll_ID = '.$DB->quote( $this->ID ) );
$this->url_aliases = $DB->get_col( $SQL->get() );
}
return $this->url_aliases;
}
/**
* Get collection type title depending on access settings:
*
* @return string
*/
function get_access_title()
{
switch( $this->get_setting( 'allow_access' ) )
{
case 'members':
if( $this->get( 'advanced_perms' ) )
{
return T_('Members only');
}
else
{
return T_('Private');
}
case 'users':
return T_('Community only');
default: // 'public'
return T_('Public');
}
}
/**
* Get max allowed post/comment status on this collection depending on access settings
*
* @param string|NULL Status to check and reduce by max allowed, NULL - to use max allowed status of this collection
* @return string
*/
function get_max_allowed_status( $check_status = NULL )
{
switch( $this->get_setting( 'allow_access' ) )
{
case 'members':
if( $this->get( 'advanced_perms' ) )
{
$max_allowed_status = 'protected';
}
else
{
$max_allowed_status = 'private';
}
break;
case 'users':
$max_allowed_status = 'community';
break;
default: // 'public'
$max_allowed_status = 'published';
break;
}
if( $check_status === NULL )
{ // Don't check the requested status:
return $max_allowed_status;
}
// Check if the requested status can be used on this collection:
$status_orders = get_visibility_statuses( 'ordered-index' );
$max_allowed_status_order = $status_orders[ $max_allowed_status ];
$check_status_order = $status_orders[ $check_status ];
if( $max_allowed_status_order >= $check_status_order )
{ // The requested status can be used on this collection:
return $check_status;
}
else
{ // Reduce the requested status by max allowed:
return $max_allowed_status;
}
}
/**
* Get what statuses should be reduced by max allowed:
*
* @param string Max allowed status, NULL to get current
* @return array Statuses
*/
function get_reduced_statuses( $max_allowed_status = NULL )
{
if( $max_allowed_status === NULL )
{ // Get current max allowed status for posts and comments o this collection:
$max_allowed_status = $this->get_max_allowed_status();
}
$status_orders = get_visibility_statuses( 'ordered-index' );
$max_allowed_status_order = $status_orders[ $max_allowed_status ];
// Find what statuses should be reduced by max allowed:
$reduced_statuses = array();
foreach( $status_orders as $status_key => $status_order )
{
if( $max_allowed_status_order < $status_order )
{ // This status must be updated because the level is more than max allowed:
$reduced_statuses[] = $status_key;
}
}
return $reduced_statuses;
}
/**
* Get a count how much statuses of posts and comments will be reduced after new max allowed status of this collection
*
* @return array|boolean Array with keys 'posts' and 'comments' where each is array with key as status and value as a count | FALSE if nothing to update
*/
function get_count_reduced_status_data( $new_max_allowed_status )
{
global $DB;
if( empty( $this->ID ) )
{ // Collection must be created before:
return false;
}
// Get statuses that should be reduced by max allowed:
$reduced_statuses = $this->get_reduced_statuses( $new_max_allowed_status );
if( empty( $reduced_statuses ) )
{ // No status to update:
return false;
}
$posts_SQL = new SQL( 'Get how much posts will be updated after new max allowed status of the collection #'.$this->ID );
$posts_SQL->SELECT( 'post_status, COUNT( post_ID )' );
$posts_SQL->FROM( 'T_items__item' );
$posts_SQL->FROM_add( 'INNER JOIN T_categories ON cat_ID = post_main_cat_ID' );
$posts_SQL->WHERE( 'cat_blog_ID = '.$this->ID );
$posts_SQL->WHERE_and( 'post_status IN ( '.$DB->quote( $reduced_statuses ).' )' );
$posts_SQL->GROUP_BY( 'post_status' );
$posts = $DB->get_assoc( $posts_SQL );
$comments_SQL = new SQL( 'Get how much comments will be updated after new max allowed status of the collection #'.$this->ID );
$comments_SQL->SELECT( 'comment_status, COUNT( comment_ID )' );
$comments_SQL->FROM( 'T_comments' );
$comments_SQL->FROM_add( 'INNER JOIN T_items__item ON comment_item_ID = post_ID' );
$comments_SQL->FROM_add( 'INNER JOIN T_categories ON cat_ID = post_main_cat_ID' );
$comments_SQL->WHERE( 'cat_blog_ID = '.$this->ID );
$comments_SQL->WHERE_and( 'comment_status IN ( '.$DB->quote( $reduced_statuses ).' )' );
$comments_SQL->GROUP_BY( 'comment_status' );
$comments = $DB->get_assoc( $comments_SQL );
if( empty( $posts ) && empty( $comments ) )
{ // All posts and comments have a correct status:
return false;
}
return array(
'posts' => $posts,
'comments' => $comments,
);
}
/**
* Reduce statuses of posts and comments by max allowed status of this collection
*/
function update_reduced_status_data()
{
global $DB;
// Get statuses that should be reduced by max allowed:
$reduced_statuses = $this->get_reduced_statuses();
if( empty( $reduced_statuses ) )
{ // Nothing to update:
return;
}
// Get max allowed status:
$max_allowed_status = $this->get_max_allowed_status();
// Update posts:
$DB->query( 'UPDATE T_items__item
INNER JOIN T_categories ON cat_ID = post_main_cat_ID
SET post_status = '.$DB->quote( $max_allowed_status ).'
WHERE cat_blog_ID = '.$this->ID.'
AND post_status IN ( '.$DB->quote( $reduced_statuses ).' )',
'Reduce posts statuses by max allowed status of the collection #'.$this->ID );
// Update comments:
$DB->query( 'UPDATE T_comments
INNER JOIN T_items__item ON comment_item_ID = post_ID
INNER JOIN T_categories ON cat_ID = post_main_cat_ID
SET comment_status = '.$DB->quote( $max_allowed_status ).'
WHERE cat_blog_ID = '.$this->ID.'
AND comment_status IN ( '.$DB->quote( $reduced_statuses ).' )',
'Reduce comments statuses by max allowed status of the collection #'.$this->ID );
}
/**
* Load locales of this collection into cache array
*/
function load_locales()
{
if( $this->locales === NULL && ! empty( $this->ID ) )
{ // Load locales from DB once and store in cache variable:
global $DB;
$SQL = new SQL( 'Get extra locales and linked collections of collection #'.$this->ID );
$SQL->SELECT( 'cl_locale, cl_linked_coll_ID' );
$SQL->FROM( 'T_coll_locales' );
$SQL->FROM_add( 'INNER JOIN T_locales ON loc_locale = cl_locale AND loc_enabled = 1' );
$SQL->WHERE( 'cl_coll_ID = '.$this->ID );
$SQL->ORDER_BY( 'loc_priority' );
$this->locales = $DB->get_assoc( $SQL );
if( ! array_key_exists( $this->get( 'locale' ), $this->locales ) )
{ // Add main locale if it is not stored in extra locales by some unknown reason:
$this->locales[ $this->get( 'locale' ) ] = NULL;
}
}
if( ! is_array( $this->locales ) )
{ // Set default array with main locale:
$this->locales = array( $this->get( 'locale' ) => NULL );
}
}
/**
* Get locales of this collection
*
* @param string Type of locales:
* - 'locale' - locales of this collection,
* - 'coll' - locales as links to other collections,
* - 'all' - all locales of this and links with other collections,
* @return array Array: Key is locale key, Value is ID of another collection or NULL
*/
function get_locales( $type = 'locale' )
{
// Load all locales:
$this->load_locales();
if( $type == 'locale' || $type == 'coll' )
{ // Get only locales or linked collections:
$locales = array();
foreach( $this->locales as $locale => $linked_coll_ID )
{
if( ( $type == 'locale' && empty( $linked_coll_ID ) ) ||
( $type == 'coll' && ! empty( $linked_coll_ID ) ) )
{
$locales[ $locale ] = $linked_coll_ID;
}
}
return $locales;
}
// Return all locales and linked collections:
return $this->locales;
}
/**
* Set locales for this collection
*
* @param array Locales
* @param array Linked collections
*/
function set_locales( $new_locales = array(), $new_linked_colls = array() )
{
global $locales;
// Reset previous values:
$this->locales = array();
$enabled_locales = array();
foreach( $locales as $locale_key => $locale_data )
{
if( $locale_data['enabled'] )
{ // If locale is enabled:
$enabled_locales[] = $locale_key;
}
}
if( is_array( $new_locales ) )
{ // Set locales:
foreach( $new_locales as $new_locale )
{
if( in_array( $new_locale, $enabled_locales ) )
{ // Set only enabled locale:
$this->locales[ $new_locale ] = NULL;
}
}
}
if( ! array_key_exists( $this->get( 'locale' ), $this->locales ) )
{ // Make sure main locale will be stored in the table of collection locales:
$this->locales[ $this->get( 'locale' ) ] = NULL;
}
if( is_array( $new_linked_colls ) )
{ // Set linked collections:
foreach( $new_linked_colls as $locale_key => $linked_coll_ID )
{
if( ! empty( $linked_coll_ID ) &&
in_array( $locale_key, $enabled_locales ) &&
! array_key_exists( $locale_key, $this->locales ) )
{ // Set collection only with enalbed locale link:
$this->locales[ $locale_key ] = $linked_coll_ID;
}
}
}
}
/**
* Update locales of this collection
* and also update a linking with other collection by locales
*
* @return boolean TRUE on success
*/
function update_locales()
{
global $DB;
if( empty( $this->ID ) || ! is_array( $this->locales ) )
{ // Collection must be stored in DB and new locales must be defined:
return false;
}
// Delete all previous locales before inserting new:
$DB->query( 'DELETE FROM T_coll_locales
WHERE cl_coll_ID = '.$this->ID );
$sql_coll_locales = array();
if( ! empty( $this->locales ) )
{ // If at least one new locale:
foreach( $this->locales as $coll_locale => $linked_coll_ID )
{
$sql_coll_locales[ $coll_locale ] = '( '.$this->ID.', '.$DB->quote( $coll_locale ).', '.$DB->quote( $linked_coll_ID ).' )';
}
}
if( ! empty( $sql_coll_locales ) )
{ // Insert new locales:
$DB->query( 'INSERT INTO T_coll_locales ( cl_coll_ID, cl_locale, cl_linked_coll_ID )
VALUES '.implode( ', ', $sql_coll_locales ) );
}
return true;
}
/**
* Check if this collection has a requested locale
*
* @param string Locale key
* @param string Type of locales:
* - 'locale' - locales of this collection,
* - 'coll' - locales as links to other collections,
* - 'all' - all locales of this and links with other collections,
* @return boolean
*/
function has_locale( $locale_key, $type = 'locale' )
{
return array_key_exists( $locale_key, $this->get_locales( $type ) );
}
/**
* Get a number of unread posts by current logged in User
*
* @return integer
*/
function get_unread_posts_count()
{
global $DB, $current_User, $localtimenow;
if( ! is_logged_in() || ! $this->get_setting( 'track_unread_content' ) )
{ // User must be logged in AND the tracking of unread content is turned ON for the collection:
return 0;
}
// Initialize SQL query to get only the posts which are displayed by global $MainList on disp=posts:
$ItemList2 = new ItemList2( $this, $this->get_timestamp_min(), $this->get_timestamp_max(), NULL, 'ItemCache', 'recent_topics' );
$ItemList2->set_default_filters( array(
'unit' => 'all', // set this to don't calculate total rows
) );
$ItemList2->query_init();
// Get a count of the unread topics for current user:
$unread_posts_SQL = new SQL( 'Get a count of the unread topics of collection #'.$this->ID.' for current user' );
$unread_posts_SQL->SELECT( 'COUNT( post_ID )' );
$unread_posts_SQL->FROM( 'T_items__item' );
$unread_posts_SQL->FROM_add( 'LEFT JOIN T_items__user_data ON post_ID = itud_item_ID AND itud_user_ID = '.$DB->quote( $current_User->ID ) );
$unread_posts_SQL->FROM_add( 'INNER JOIN T_categories ON post_main_cat_ID = cat_ID' );
$unread_posts_SQL->FROM_add( 'LEFT JOIN T_items__type ON post_ityp_ID = ityp_ID' );
$unread_posts_SQL->WHERE( $ItemList2->ItemQuery->get_where( '' ) );
$unread_posts_SQL->WHERE_and( 'post_contents_last_updated_ts > '.$DB->quote( date2mysql( $localtimenow - 30 * 86400 ) ) );
// In theory, it would be more safe to use this comparison:
// $unread_posts_SQL->WHERE_and( 'itud_item_ID IS NULL OR itud_read_item_ts <= post_contents_last_updated_ts' );
// But until we have milli- or micro-second precision on timestamps, we decided it was a better trade-off to never see our own edits as unread. So we use:
$unread_posts_SQL->WHERE_and( 'itud_item_ID IS NULL OR itud_read_item_ts < post_contents_last_updated_ts' );
// Execute a query with to know if current user has new data to view:
return intval( $DB->get_var( $unread_posts_SQL ) );
}
/**
* Get recipient link on disp=msgform
*
* @return string
*/
function get_msgform_recipient_link()
{
$recipient_link = '';
if( get_param( 'recipient_id' ) > 0 )
{ // Get recipient identity link for registered user:
$UserCache = & get_UserCache();
$recipient_User = & $UserCache->get_by_ID( get_param( 'recipient_id' ) );
if( $this->get_setting( 'msgform_display_avatar' ) )
{ // Display recipient name with avatar:
$recipient_link_params = array(
'link_text' => 'avatar_name',
'thumb_size' => $this->get_setting( 'msgform_avatar_size' ),
'thumb_class' => 'avatar_before_login_middle',
);
}
else
{ // Display only recipient name:
$recipient_link_params = array( 'link_text' => 'auto' );
}
$recipient_link = $recipient_User->get_identity_link( $recipient_link_params );
}
elseif( get_param( 'comment_id' ) > 0 )
{ // Get login name for anonymous user:
$CommentCache = & get_CommentCache();
$Comment = & $CommentCache->get_by_ID( get_param( 'comment_id' ) );
// Set a gender class for anonymous user if the setting is enabled:
$gender_class = check_setting( 'gender_colored' ) ? ' nogender' : '';
$recipient_link = '<span class="user anonymous'.$gender_class.'" rel="bubbletip_comment_'.$Comment->ID.'">'.$Comment->get_author_name().'</span>';
}
return $recipient_link;
}
/**
* Get additional fields on disp=msgform
*
* @return array
*/
function get_msgform_additional_fields()
{
$msgform_additional_fields = trim( $this->get_setting( 'msgform_additional_fields' ) );
$saved_additional_fields = array();
if( empty( $msgform_additional_fields ) )
{ // No saved additional fields for this collection:
return $saved_additional_fields;
}
// Get data of saved additional fields from DB by IDs:
$msgform_additional_fields = explode( ',', $msgform_additional_fields );
$UserFieldCache = & get_UserFieldCache();
foreach( $msgform_additional_fields as $user_field_ID )
{
if( $UserField = & $UserFieldCache->get_by_ID( $user_field_ID, false, false ) )
{
$saved_additional_fields[ $UserField->ID ] = $UserField;
}
}
return $saved_additional_fields;
}
/**
* Display all selected additional fields on disp=msgform
*
* @param object Form
* @param array Filled user fields from submitted form
* @return array
*/
function display_msgform_additional_fields( $Form, $filled_user_fields = array() )
{
$msgform_additional_fields = $this->get_msgform_additional_fields();
foreach( $msgform_additional_fields as $UserField )
{
$field_values = array();
if( ! empty( $filled_user_fields[ $UserField->ID ] ) )
{ // Get values from the submitted form:
if( is_array( $filled_user_fields[ $UserField->ID ] ) )
{ // Multiple field:
$field_values = $filled_user_fields[ $UserField->ID ];
}
else
{ // Single field:
$field_values = array( $filled_user_fields[ $UserField->ID ] );
}
}
if( is_logged_in() && empty( $field_values ) )
{ // Get saved field value from the current logged in User:
global $current_User;
$userfields = $current_User->userfields_by_ID( $UserField->ID );
if( is_array( $userfields ) )
{
foreach( $userfields as $userfield )
{
$field_values[] = $userfield->uf_varchar;
}
}
}
if( empty( $field_values ) )
{ // Display at least one additional field if user is not filled that in profile yet:
$field_values = array( '' );
}
foreach( $field_values as $f => $field_value )
{ // Display additional fields:
$this->display_msgform_additional_field( $Form, $UserField, $field_value, $f != 0 );
}
}
}
/**
* Display single additional field on disp=msgform
*
* @param object Form
* @param object UserField
* @param string Field value
* @param boolean Is field duplicated
* @return array
*/
function display_msgform_additional_field( $Form, $UserField, $field_value = '', $force_not_required = false )
{
$field_params = array();
if( ! $force_not_required && $UserField->get( 'required' ) == 'require' )
{ // Field is required and it is not a second copy of the field:
$field_params['required'] = true;
}
if( $UserField->get( 'suggest' ) == '1' && $UserField->get( 'type' ) == 'word' )
{ // Mark field with this tag to suggest a values
$field_params['autocomplete'] = 'on';
}
// Field name:
$field_name = 'user_fields['.$UserField->ID.']';
if( in_array( $UserField->get( 'duplicated' ), array( 'allowed', 'list' ) ) )
{ // If field can be duplicated:
$field_name .= '[]';
}
switch( $UserField->get( 'type' ) )
{
case 'text':
$field_params['cols'] = 38;
$Form->textarea_input( $field_name, $field_value, 5, $UserField->get_input_label(), $field_params );
break;
case 'list':
$uf_options = explode( "\n", str_replace( "\r", '', $UserField->get( 'options' ) ) );
if( $UserField->get( 'required' ) != 'require' )
{ // Add an empty value for not required field:
$uf_options = array_merge( array( '', '---' ), $uf_options );
}
$Form->select_input_array( $field_name, $field_value, $uf_options, $UserField->get_input_label(), '', $field_params );
break;
case 'user':
if( is_pro() )
{ // Display user selector by PRO function:
load_funcs( '_core/_pro_features.funcs.php' );
pro_display_user_field_input( $field_name, $UserField, $field_value, '', $field_params, $Form );
}
break;
default:
$field_params['maxlength'] = 255;
$field_params['style'] = 'max-width:90%';
$Form->text_input( $field_name, $field_value, ( $UserField->get( 'type' ) == 'url' ? 80 : 40 ), $UserField->get_input_label(), '', $field_params );
}
}
/**
* Get default item type object
*
* @return object ItemType
*/
function & get_default_ItemType()
{
if( ! isset( $this->default_ItemType ) )
{ // Initialize default item type object for this collection:
$ItemTypeCache = & get_ItemTypeCache();
$this->default_ItemType = & $ItemTypeCache->get_by_ID( $this->get_setting( 'default_post_type' ), false, false );
}
return $this->default_ItemType;
}
/**
* Setup default widgets for this collection
*
* @param string Skin type: 'all', 'normal', 'mobile', 'tablet'
* @param array Context
*/
function setup_default_widgets( $skin_type = 'all', $context = array() )
{
global $DB;
if( empty( $this->ID ) )
{ // This function should be called only for created collection:
return;
}
if( $skin_type == 'all' )
{ // Setaup default widgets for skins of all types:
$this->setup_default_widgets( 'normal', $context );
$this->setup_default_widgets( 'mobile', $context );
$this->setup_default_widgets( 'tablet', $context );
$this->setup_default_widgets( 'alt', $context );
return;
}
$coll_skin_ID = $this->get_skin_ID( $skin_type );
$SkinCache = & get_SkinCache();
if( ! ( $coll_Skin = & $SkinCache->get_by_ID( $coll_skin_ID, false, false ) ) )
{ // This collection must has a correct skin:
return;
}
// Get the declarations of the widgets that the skin wants to use:
$context['current_coll_ID'] = $this->ID;
$skin_widgets = $coll_Skin->get_default_widgets( $this->get( 'type' ), $skin_type, $context );
// Check if the skin wants to use all b2evolution default widgets:
if( isset( $skin_widgets['*'] ) )
{ // Depending on how the skin want to use this:
$use_all_b2evo_default_widgets = $skin_widgets['*'];
unset( $skin_widgets['*'] );
}
else
{ // Use all default widgets if the skin does NOT say about this:
$use_all_b2evo_default_widgets = true;
}
load_funcs( 'widgets/_widgets.funcs.php' );
// Get the declarations of the widgets that b2evolution recommends by default:
$b2evo_default_widgets = get_default_widgets( $this->get( 'type' ), $context );
// Merge the skin widget declarations with b2evolution default widgets:
foreach( $b2evo_default_widgets as $container_code => $widgets )
{
if( // The skin has no widget declarations for this container and it allows to use b2evolution default widgets:
( ! isset( $skin_widgets[ $container_code ] ) &&
$use_all_b2evo_default_widgets )
||
// The skin wants to use default widget declarations for this container:
( isset( $skin_widgets[ $container_code ] ) &&
$skin_widgets[ $container_code ] === true ) )
{ // Merge widgets from b2evolution default declarations to the skin:
$skin_widgets[ $container_code ] = $widgets;
}
elseif( isset( $skin_widgets[ $container_code ] ) &&
is_array( $skin_widgets[ $container_code ] ) )
{ // Append custom skin widgets to default widgets:
$skin_widgets[ $container_code ] = array_merge( $widgets, $skin_widgets[ $container_code ] );
}
}
// Check all skin widget containers to be sure they all are proper arrays and not other values like true, false and etc.:
foreach( $skin_widgets as $container_code => $container_widgets )
{
if( ! empty( $container_widgets['type'] ) &&
! in_array( $container_widgets['type'], array( 'main', 'sub', 'page' ) ) )
{ // Skip not collection container:
unset( $skin_widgets[ $container_code ] );
continue;
}
if( isset( $container_widgets['coll_type'] ) &&
! is_allowed_option( $this->get( 'type' ), $container_widgets['coll_type'] ) )
{ // Skip container because it should not be installed for the given collection kind:
unset( $skin_widgets[ $container_code ] );
continue;
}
if( isset( $container_widgets['skin_type'] ) &&
! is_allowed_option( $skin_type, $container_widgets['skin_type'] ) )
{ // Skip container because it should not be installed for the given skin type:
unset( $skin_widgets[ $container_code ] );
continue;
}
if( $container_widgets === true )
{ // Set empty container if it has not been detected in b2evolution default widget declarations above:
$skin_widgets[ $container_code ] = array();
}
elseif( ! is_array( $container_widgets ) )
{ // Ignore all other not array, probably it is a boolean false or some other string value which should be ignored indeed:
unset( $skin_widgets[ $container_code ] );
}
}
if( empty( $skin_widgets ) )
{ // No skin default widgets:
return;
}
// Get all containers declared in this collection skin type:
$blog_containers = $this->get_skin_containers( $skin_type );
// Install additional sub-containers and page containers from default config,
// which are not declared as main containers but should be installed too:
foreach( $skin_widgets as $container_code => $container_widgets )
{
if( isset( $container_widgets['type'] ) &&
( $container_widgets['type'] == 'sub' || $container_widgets['type'] == 'page' ) )
{ // If it is a sub-container or page container:
$blog_containers[ $container_code ] = array(
isset( $container_widgets['name'] ) ? $container_widgets['name'] : $container_code,
isset( $container_widgets['order'] ) ? $container_widgets['order'] : 1,
( $container_widgets['type'] == 'sub' ? 0 : 1 ), // Main or Sub-container
isset( $container_widgets['item_ID'] ) ? $container_widgets['item_ID'] : NULL,
);
}
}
// Create rows to insert for all collection containers:
$widget_containers_sql_rows = array();
foreach( $blog_containers as $container_code => $wico_data )
{
$widget_containers_sql_rows[] = '( '.$DB->quote( $container_code ).', '
.$DB->quote( $skin_type ).', '
.$DB->quote( $wico_data[0] ).', '
.$this->ID.', '
.$DB->quote( $wico_data[1] ).', '
.( isset( $wico_data[2] ) ? intval( $wico_data[2] ) : '1' ).', '
.( isset( $wico_data[3] ) ? intval( $wico_data[3] ) : 'NULL' ).' )';
}
if( empty( $widget_containers_sql_rows ) )
{ // No collection containers to install:
return;
}
// Insert widget containers records by one SQL query:
$DB->query( 'INSERT INTO T_widget__container ( wico_code, wico_skin_type, wico_name, wico_coll_ID, wico_order, wico_main, wico_item_ID ) VALUES'
.implode( ', ', $widget_containers_sql_rows ) );
$insert_id = $DB->insert_id;
foreach( $blog_containers as $container_code => $wico_data )
{
$blog_containers[ $container_code ]['wico_ID'] = $insert_id;
$insert_id++;
}
$basic_widgets_insert_sql_rows = array();
foreach( $skin_widgets as $container_code => $container_widgets )
{
if( ! isset( $blog_containers[ $container_code ] ) )
{ // Skip container which is not supported by current collection's skin:
continue;
}
$wico_id = $blog_containers[ $container_code ]['wico_ID'];
foreach( $container_widgets as $key => $widget )
{
if( ! is_number( $key ) )
{ // Skip the config data which is used as additional info for container like 'type', 'name', 'order', 'item_ID', 'coll_type':
continue;
}
if( isset( $widget['install'] ) && ! $widget['install'] )
{ // Skip widget because it should not be installed by condition from config:
continue;
}
if( isset( $widget['coll_type'] ) && ! is_allowed_option( $this->get( 'type' ), $widget['coll_type'] ) )
{ // Skip widget because it should not be installed for the given collection kind:
continue;
}
if( isset( $widget['is_pro'] ) && $widget['is_pro'] !== is_pro() )
{ // Skip widget because it should not be installed for the current version:
continue;
}
if( isset( $widget['coll_ID'] ) && ! is_allowed_option( $this->ID, $widget['coll_ID'] ) )
{ // Skip widget because it should not be installed for the given collection ID:
continue;
}
if( isset( $widget['skin_type'] ) && ! is_allowed_option( $skin_type, $widget['skin_type'] ) )
{ // Skip widget because it should not be installed for the given skin type:
continue;
}
// Initialize a widget row to insert into DB below by single query:
$widget_type = isset( $widget['type'] ) ? $widget['type'] : 'core';
$widget_params = isset( $widget['params'] ) ? ( is_array( $widget['params'] ) ? serialize( $widget['params'] ) : $widget['params'] ) : NULL;
$widget_enabled = isset( $widget['enabled'] ) ? intval( $widget['enabled'] ) : 1;
$basic_widgets_insert_sql_rows[] = '( '.$wico_id.', '.$widget[0].', '.$widget_enabled.', '.$DB->quote( $widget_type ).', '.$DB->quote( $widget[2] ).', '.$DB->quote( $widget_params ).' )';
}
}
// Check if there are widgets to create:
if( ! empty( $basic_widgets_insert_sql_rows ) )
{ // Insert the widget records by single SQL query:
$DB->query( 'INSERT INTO T_widget__widget ( wi_wico_ID, wi_order, wi_enabled, wi_type, wi_code, wi_params ) '
.'VALUES '.implode( ', ', $basic_widgets_insert_sql_rows ) );
}
}
/**
* Get name of default item type
*
* @return string Name of default ItemType object
*/
function get_default_item_type_name()
{
$default_ItemType = $this->get_default_ItemType();
return $default_ItemType ? $default_ItemType->get_name() : T_('Post');
}
/**
* Get URL with protocol which is defined by collection setting "SSL"
*
* @param string Requested URL
* @param string Forced URL
*/
function get_protocol_url( $url )
{
if( empty( $this->ID ) )
{
return $url;
}
switch( $this->get_setting( 'http_protocol' ) )
{ // Force URL's protocol depending on collection setting "SSL":
case 'always_http':
$url = preg_replace( '#^https://#', 'http://', $url );
break;
case 'always_https':
$url = preg_replace( '#^http://#', 'https://', $url );
break;
}
return $url;
}
/**
* Get default new item type based on the collection's default category or current working category
*
* @return object|false ItemType object, false if default item type is disabled
*/
function & get_default_new_ItemType()
{
global $cat;
// Get a working category:
$working_cat = $cat;
if( empty( $cat ) )
{ // Use default collection category when global category is not defined:
$working_cat = $this->get_default_cat_ID();
}
$ChapterCache = & get_ChapterCache();
$working_Chapter = & $ChapterCache->get_by_ID( $working_cat, false, false );
if( ! $working_Chapter ||
( ( $working_cat_ItemType = & $working_Chapter->get_ItemType() ) === false ) )
{ // The working category is not detected in DB or it has no default Item Type:
$r = false;
return $r;
}
if( $working_cat_ItemType === NULL )
{ // If the working category uses the same as collection default:
$coll_default_ItemType = $this->get_default_ItemType();
return $coll_default_ItemType;
}
// If the working category uses a custom Item Type:
return $working_cat_ItemType;
}
/**
* Get default item denomination depending on current collection type
*
* @param string Position where denomination will be used, can be one of the following: 'evobar_new', 'inskin_new_btn', 'title_new', 'title_update'
* @return string Item denomination
*/
function get_item_denomination( $position = 'evobar_new' )
{
switch( $this->get( 'type' ) )
{
case 'photo':
$denominations = array(
'evobar_new' => T_('Album'),
'inskin_new_btn' => T_('New album'),
'title_new' => T_('New album'),
'title_updated' => T_('Updated album'),
);
break;
case 'group':
$denominations = array(
'evobar_new' => T_('Task'),
'inskin_new_btn' => T_('New task'),
'title_new' => T_('New task'),
'title_updated' => T_('Updated task'),
);
break;
case 'forum':
$denominations = array(
'evobar_new' => T_('Topic'),
'inskin_new_btn' => T_('New topic'),
'title_new' => T_('New topic'),
'title_updated' => T_('Updated topic'),
);
break;
case 'manual':
$denominations = array(
'evobar_new' => T_('Page'),
'inskin_new_btn' => T_('New page'),
'title_new' => T_('New page'),
'title_updated' => T_('Updated page'),
);
break;
default:
$denominations = array(
'evobar_new' => T_('Post'),
'inskin_new_btn' => T_('New post'),
'title_new' => T_('New post'),
'title_updated' => T_('Updated post'),
);
}
return isset( $denominations[ $position ] ) ? $denominations[ $position ] : '';
}
/**
* Get last touched date of content in this collection
*
* @param string Date/Time format: leave empty to use locale default date format, use FALSE to don't format
* @param boolean TRUE if you want GMT
* @return string Last touched date
*/
function get_last_touched_date( $format = false, $useGM = false )
{
if( empty( $this->ID ) )
{ // Collection must be saved in DB:
return false;
}
if( ! isset( $this->last_touched_date ) )
{ // Load last touched date from DB:
global $DB;
$SQL = new SQL( 'Get last touched date for collection #'.$this->ID );
$SQL->SELECT( 'cat_last_touched_ts' );
$SQL->FROM( 'T_categories' );
$SQL->WHERE( 'cat_blog_ID = '.$this->ID );
$SQL->ORDER_BY( 'cat_last_touched_ts DESC' );
$SQL->LIMIT( '1' );
// Store date in cache:
$this->last_touched_date = $DB->get_var( $SQL );
}
if( $format === false )
{ // Don't format:
return $this->last_touched_date;
}
if( empty( $format ) )
{ // Use format of current locale:
$format = locale_datefmt();
}
return mysql2date( $format, $this->last_touched_date, $useGM );
}
/**
* Get a marketing popup container code if it is enabled for current requested page
*
* @return string|boolean Container code, FALSE if marketing popup is not enabled
*/
function get_marketing_popup_container()
{
if( is_admin_page() )
{ // Don't display on back-office:
return false;
}
if( $this->get_setting( 'marketing_popup_using' ) == 'never' )
{ // Marketing popup is disabled for all users:
return false;
}
if( is_logged_in() && $this->get_setting( 'marketing_popup_using' ) == 'anonymous' )
{ // Marketing popup is enabled only for anonymous users:
return false;
}
// Get widget container code depending on current disp:
global $disp;
$container_disp = in_array( $disp, array( 'front', 'posts', 'single', 'page', 'catdir' ) ) ? $disp : 'other_disps';
$container_code = $this->get_setting( 'marketing_popup_container_'.$container_disp );
if( empty( $container_code ) )
{ // Don't try to find a widget container without code:
return false;
}
// Check if widget container realy exists in DB for current collection or it is a shared container:
$WidgetContainerCache = & get_WidgetContainerCache();
$WidgetContainer = & $WidgetContainerCache->get_by_coll_skintype_code( $this->ID, $this->get_skin_type(), $container_code );
return $WidgetContainer ? $container_code : false;
}
/**
* Initialize JS & CSS for marketing popup container
*/
function init_marketing_popup_container()
{
$marketing_popup_container_code = $this->get_marketing_popup_container();
if( $marketing_popup_container_code )
{ // If marketing popup is enabled for current page and user:
// Load CSS right in the current calling place:
require_css( 'ddexitpop.bmin.css', 'blog', NULL, NULL, '#', true );
// Initialize JS code to display a marketing popup:
$marketing_popup_show_frequency = $this->get_setting( 'marketing_popup_show_frequency' );
if( $marketing_popup_show_frequency == 'period' )
{ // Use period frequency like X hours or X days:
$marketing_popup_show_frequency = $this->get_setting( 'marketing_popup_show_period_val' )
.$this->get_setting( 'marketing_popup_show_period_unit' );
}
expose_var_to_js( 'evo_ddexitpop_config', array(
'container_code' => $marketing_popup_container_code,
'animation' => $this->get_setting( 'marketing_popup_animation' ),
'show_repeat' => (boolean)$this->get_setting( 'marketing_popup_show_repeat' ),
'show_frequency' => $marketing_popup_show_frequency,
) );
require_js_defer( 'build/ddexitpop.bmin.js', 'blog', false, '#', 'footerlines' );
}
}
/**
* Get a count of must read items of this collection
*
* @param string 'unread' - Items which are not read by current User yet,
* 'read' - Items which are already read by current User,
* 'all' - All(Read and Unread) items with "must read" flag.
* @return integer
*/
function get_mustread_items_count( $read_status = 'all' )
{
if( ! $this->get_setting( 'track_unread_content' ) )
{ // No must read items when tracking of unread content is enabled for this collection:
return 0;
}
if( ! in_array( $read_status, array( 'all', 'unread', 'read' ) ) )
{ // Ignore wrong param value:
return 0;
}
if( ! isset( $this->mustread_items_count ) )
{ // Initialize array for cache:
$this->mustread_items_count = array();
}
if( ! isset( $this->mustread_items_count[ $read_status ] ) )
{ // Get it from DB only first time and then cache in var:
$mustread_ItemList2 = new ItemList2( $this, $this->get_timestamp_min(), $this->get_timestamp_max() );
// Set additional debug info prefix for SQL queries in order to know what code executes it:
$mustread_ItemList2->query_title_prefix = 'Must Read Items (status = '.$read_status.')';
// Filter only the flagged items:
$mustread_ItemList2->set_default_filters( array(
'itemtype_usage' => 'post,page,intro-front,intro-main,intro-cat,intro-tag,intro-sub,intro-all',
'mustread' => $read_status
) );
// Run query initialization to get total rows:
$mustread_ItemList2->query_init();
$this->mustread_items_count[ $read_status ] = $mustread_ItemList2->total_rows;
}
return $this->mustread_items_count[ $read_status ];
}
/**
* Get a selector to link this collection with other collections
* which have same main or extra locale as requested
*
* @param string Field name
* @param string Locale to search other collections
* @return string
*/
function get_link_locale_selector( $field_name, $locale, $restrict_used_locales = true )
{
global $DB;
if( $restrict_used_locales &&
( $this->get( 'locale' ) == $locale ||
in_array( $locale, array_keys( $this->get_locales() ) ) ) )
{ // Don't allow selector if this collection already uses the requested locale:
return T_('N/A');
}
$linked_colls = $this->get_locales( 'coll' );
if( ! check_user_perm( 'blogs', 'editall' ) )
{ // Display only the stored value because current User has no permission to edit all collections:
if( isset( $linked_colls[ $locale ] ) )
{ // Get the linked collection:
$BlogCache = & get_BlogCache();
$linked_Blog = & $BlogCache->get_by_ID( $linked_colls[ $locale ], false, false );
}
return empty( $linked_Blog ) ? T_('None') : $linked_Blog->get( 'name' );
}
$main_locale_SQL = new SQL( 'Get collections with locale '.$locale.' to link with coolection #'.$this->ID );
$main_locale_SQL->SELECT( 'blog_ID' );
$main_locale_SQL->FROM( 'T_blogs' );
$main_locale_SQL->WHERE( 'blog_locale = '.$DB->quote( $locale ) );
if( $this->ID > 0 )
{
$main_locale_SQL->WHERE_and( 'blog_ID != '.$this->ID );
}
$extra_locale_SQL = new SQL( 'Get collections with locale '.$locale.' to link with coolection #'.$this->ID );
$extra_locale_SQL->SELECT( 'cl_coll_ID' );
$extra_locale_SQL->FROM( 'T_coll_locales' );
$extra_locale_SQL->WHERE( 'cl_locale = '.$DB->quote( $locale ) );
$extra_locale_SQL->WHERE_and( 'cl_linked_coll_ID IS NULL' );
if( $this->ID > 0 )
{
$extra_locale_SQL->WHERE_and( 'cl_coll_ID != '.$this->ID );
}
$colls = $DB->get_col( 'SELECT blog_ID
FROM ( '.$main_locale_SQL->get().' UNION ' .$extra_locale_SQL->get().' ) AS locale_colls
ORDER BY blog_ID' );
if( empty( $colls ) )
{ // No collection with requested locale:
return T_('None');
}
$BlogCache = get_BlogCache();
$BlogCache->load_list( $colls );
$r = '<select name="'.$field_name.'_link_coll['.$locale.']" class="form-control" style="width:100%">';
$r .= '<option value="">'.T_('None').'</option>';
foreach( $colls as $coll_ID )
{
if( $locale_Blog = & $BlogCache->get_by_ID( $coll_ID, false, false ) )
{
$r .= '<option value="'.$coll_ID.'"'
.( isset( $linked_colls[ $locale ] ) && $linked_colls[ $locale ] == $coll_ID ? ' selected="selected"' : '' ).'>'
.$locale_Blog->get( 'name' ).'</option>';
}
}
$r .= '</select>';
return $r;
}
/**
* Reset widgets for this collection
*
* @param string Skin type: 'all', 'normal', 'mobile', 'tablet'
*/
function reset_widgets( $skin_type = 'all' )
{
if( empty( $this->ID ) )
{ // This function should be called only for created collection:
return;
}
global $DB;
$all_skin_types = array( 'normal', 'mobile', 'tablet', 'alt' );
if( $skin_type == 'all' )
{ // Reset widgets for all skin types:
$skin_types = $all_skin_types;
}
elseif( in_array( $skin_type, $all_skin_types ) )
{ // Reset widgets only for requested skin type:
$skin_types = array( $skin_type );
}
else
{ // No correct skin type is requested:
return;
}
foreach( $skin_types as $skin_type )
{ // Remove previous widgets:
$DB->query( 'DELETE T_widget__container, T_widget__widget
FROM T_widget__container
LEFT JOIN T_widget__widget ON wico_ID = wi_wico_ID
WHERE wico_coll_ID = '.$DB->quote( $this->ID )
.( empty( $skin_type ) ? '' :
' AND wico_skin_type = '.$DB->quote( $skin_type ) ) );
// Add default widgets:
$this->setup_default_widgets( $skin_type );
}
}
}
?>