<?php
/**
* This file implements the Chapter 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)2005-2006 by PROGIDISTRI - {@link http://progidistri.com/}.
*
* @package evocore
*/
if( !defined('EVO_MAIN_INIT') ) die( 'Please, do not access this page directly.' );
/**
* Chapter Class
*
* @package evocore
*/
class Chapter extends DataObject
{
/**
* Name of Chapter
*
* @var string
* @access protected
*/
var $name;
var $parent_ID;
/**
* To display parent name in form
*/
var $parent_name;
/**
* Category children list
*/
var $children = array();
var $children_sorted = false;
/**
* @var integer
*/
var $blog_ID;
/**
* The Blog of the Item (lazy filled, use {@link get_Blog()} to access it.
* @access protected
* @var Blog
*/
var $Blog;
var $urlname;
var $description;
var $order;
var $meta;
var $lock;
var $ityp_ID = NULL;
/**
* Default Item Type
* @var object|NULL|false
*/
var $ItemType = NULL;
/**
* Lazy filled
* @var Chapter
*/
var $parent_Chapter;
/**
* Date when items or comments were added/edited/deleted for this Chapter last time (timestamp)
* @see Chapter::update_last_touched_date()
* @var integer
*/
var $last_touched_ts;
/**
* The sub categories sort order.
*
* Possible values:
* 'parent' - same as in case of parent,
* 'alpha' - sort alphabetically,
* 'manual' - sort manually
*
* @var string
*/
var $subcat_ordering;
/**
* Category image
*/
var $image_file_ID;
/**
* Social media image
*/
var $social_media_image_file_ID;
/**
* Constructor
*
* @param table Database row
* @param integer|NULL subset to use for new object
*/
function __construct( $db_row = NULL, $subset_ID = NULL )
{
// Call parent constructor:
parent::__construct( 'T_categories', 'cat_', 'cat_ID' );
if( is_null( $db_row ) )
{ // We are creating an object here:
$this->set( 'blog_ID', $subset_ID );
}
else
{ // We are loading an object:
$this->ID = $db_row->cat_ID;
$this->name = $db_row->cat_name;
$this->parent_ID = $db_row->cat_parent_ID;
$this->blog_ID = $db_row->cat_blog_ID;
$this->image_file_ID = $db_row->cat_image_file_ID;
$this->social_media_image_file_ID = $db_row->cat_social_media_image_file_ID;
$this->urlname = $db_row->cat_urlname;
$this->description = $db_row->cat_description;
$this->order = $db_row->cat_order;
$this->subcat_ordering = $db_row->cat_subcat_ordering;
$this->meta = $db_row->cat_meta;
$this->lock = $db_row->cat_lock;
$this->last_touched_ts = $db_row->cat_last_touched_ts; // When Chapter received last visible change (edit, item, comment, etc.)
$this->ityp_ID = isset( $db_row->cat_ityp_ID ) ? $db_row->cat_ityp_ID : NULL;
}
}
/**
* Get this class db table config params
*
* @return array
*/
static function get_class_db_config()
{
static $chapter_db_config;
if( !isset( $chapter_db_config ) )
{
$chapter_db_config = array_merge( parent::get_class_db_config(),
array(
'dbtablename' => 'T_categories',
'dbprefix' => 'cat_',
'dbIDname' => 'cat_ID',
)
);
}
return $chapter_db_config;
}
/**
* Get delete restriction settings
*
* @return array
*/
static function get_delete_restrictions()
{
return array(
array( 'table'=>'T_categories', 'fk'=>'cat_parent_ID', 'msg'=>T_('%d sub categories'),
'class'=>'Chapter', 'class_path'=>'chapters/model/_chapter.class.php' ),
array( 'table'=>'T_items__item', 'fk'=>'post_main_cat_ID', 'msg'=>T_('%d posts within category through main cat'),
'class'=>'Item', 'class_path'=>'items/model/_item.class.php' ),
array( 'table'=>'T_postcats', 'fk'=>'postcat_cat_ID', 'msg'=>T_('%d posts within category through extra cat') ),
);
}
/**
* Compare two Chapters based on the parent/blog sort category setting
*
* @param Chapter A
* @param Chapter B
* @return number -1 if A < B, 1 if A > B, 0 if A == B
*/
static function compare_chapters( $a_Chapter, $b_Chapter )
{
if( $a_Chapter == NULL || $b_Chapter == NULL ) {
debug_die('Invalid category objects received to compare.');
}
if( $a_Chapter->ID == $b_Chapter->ID )
{ // The two chapters are the same
return 0;
}
if( $a_Chapter->blog_ID != $b_Chapter->blog_ID )
{ // Sort based on the ordering between different blogs
$a_Chapter->load_Blog();
$b_Chapter->load_Blog();
return Blog::compare_blogs($a_Chapter->Blog, $b_Chapter->Blog);
}
$ChapterCache= & get_ChapterCache();
if( $a_Chapter->parent_ID != $b_Chapter->parent_ID )
{ // Two chapters from the same blog, but different parrents
// Compare those parents of these chapters which have a common parent Chapter or they are both root Chapters.
$path_to_root_a = array_reverse( $ChapterCache->get_chapter_path( $a_Chapter->blog_ID, $a_Chapter->ID ) );
$path_to_root_b = array_reverse( $ChapterCache->get_chapter_path( $b_Chapter->blog_ID, $b_Chapter->ID ) );
$index = 0;
while( isset( $path_to_root_a[$index] ) && isset( $path_to_root_b[$index] ) )
{
if( $path_to_root_a[$index] != $path_to_root_b[$index] )
{ // The first different parent on the same level was found, compare parent objects
$parent_a_Chapter = $ChapterCache->get_by_ID( $path_to_root_a[$index] );
$parent_b_Chapter = $ChapterCache->get_by_ID( $path_to_root_b[$index] );
return self::compare_chapters( $parent_a_Chapter, $parent_b_Chapter );
}
$index++;
}
// One of the chapters is a parent of the other, the parent is considered greater than the other
return isset( $path_to_root_a[$index] ) ? 1 : -1;
}
if( empty( $a_Chapter->parent_ID ) )
{
$a_Chapter->load_Blog();
$cat_order = $a_Chapter->Blog->get_setting('category_ordering');
}
else
{
$parent_Chapter = $ChapterCache->get_by_ID( $a_Chapter->parent_ID );
$cat_order = $parent_Chapter->get_subcat_ordering();
}
switch( $cat_order )
{
case 'alpha':
$result = strcmp( $a_Chapter->name, $b_Chapter->name );
break;
case 'manual':
if( $a_Chapter->order === NULL )
{ // NULL values are greater than any number
$result = ( $b_Chapter->order !== NULL ) ? 1 : 0;
break;
}
if( $b_Chapter->order === NULL )
{ // NULL values are greater than any number, so a is lower than b
$result = -1;
break;
}
$result = ( $a_Chapter->order > $b_Chapter->order ) ? 1 : ( ( $a_Chapter->order < $b_Chapter->order ) ? -1 : 0 );
break;
default:
debug_die("Invalid category ordering value!");
}
if( $result == 0 )
{ // In case if the order fields are equal order by ID
$result = $a_Chapter->ID > $b_Chapter->ID ? 1 : -1;
}
return $result;
}
/**
* Sort chapter childer
*/
function sort_children()
{
if( $this->children_sorted )
{ // Category children list is already sorted
return;
}
// Sort children list
uasort( $this->children, array( 'Chapter','compare_chapters' ) );
}
/**
* Get children/sub-chapters of this category
*
* @param boolean set to true to sort children, leave false otherwise
* @return array of Chapter - children of this Chapter
*/
function get_children( $sorted = false )
{
if( $sorted )
{ // sort childrens if required
$this->sort_children();
}
return $this->children;
}
/**
* Load data from Request form fields.
*
* @return boolean true if loaded data seems valid.
*/
function load_from_request()
{
param_string_not_empty( 'cat_name', T_('Please enter a name.') );
$this->set_from_Request( 'name' );
if( param( 'cat_parent_ID', 'integer', -1 ) !== -1 )
{ // Set parent ID:
$this->set_from_Request( 'parent_ID' );
}
// Check image file
param( 'cat_image_file_ID', 'integer' );
$this->set_from_Request( 'image_file_ID' );
// Check social media boilerplate image
param( 'cat_social_media_image_file_ID', 'integer' );
$this->set_from_Request( 'social_media_image_file_ID' );
// Check url name
param( 'cat_urlname', 'string' );
// Replace special chars/umlauts:
load_funcs( 'locales/_charset.funcs.php' );
set_param( 'cat_urlname', replace_special_chars( get_param( 'cat_urlname' ) ) );
param_check_regexp( 'cat_urlname', '#^[^a-z0-9]*[0-9]*[^a-z0-9]*$#i', T_('All slugs must contain at least 1 non-numeric character.'), NULL, false, false );
$this->set_from_Request( 'urlname' );
// Check description
param( 'cat_description', 'string' );
$this->set_from_Request( 'description' );
$cat_Blog = & $this->get_Blog();
if( $cat_Blog && $cat_Blog->get_setting('category_ordering') == 'manual' )
{ // Manual ordering
param( 'cat_order', 'integer', NULL );
$this->set_from_Request( 'order', 'cat_order', true );
}
// Sort sub-categories
param( 'cat_subcat_ordering', 'string' );
$this->set_from_Request( 'subcat_ordering' );
// Meta category
$cat_meta = param( 'cat_meta', 'integer', 0 );
if( $this->has_posts() && $cat_meta )
{ // Display error message if we want make the meta category from category with posts
global $Messages;
$Messages->add( sprintf( T_('The category «%s» cannot be set as meta category. You must remove the posts it contains first.'), $this->dget('name') ) );
}
else
{ // Save the category as 'Meta' only if it has no posts
$this->set_from_Request( 'meta' );
}
// Locked category
param( 'cat_lock', 'integer', 0 );
$this->set_from_Request( 'lock' );
// Default Item Type:
param( 'cat_ityp_ID', 'integer', NULL );
$this->set_from_Request( 'ityp_ID' );
return ! param_errors_detected();
}
/**
*
*/
function & get_parent_Chapter()
{
if( ! isset( $this->parent_Chapter ) )
{ // Not resoleved yet!
if( empty( $this->parent_ID ) )
{
$this->parent_Chapter = NULL;
}
else
{
$ChapterCache = & get_ChapterCache();
$this->parent_Chapter = & $ChapterCache->get_by_ID( $this->parent_ID, false );
}
}
return $this->parent_Chapter;
}
/**
* Get URL path (made of URL names) back to the root
*/
function get_url_path()
{
$r = $this->urlname.'/';
$parent_Chapter = & $this->get_parent_Chapter();
if( !is_null( $parent_Chapter ) )
{ // Recurse:
$r = $parent_Chapter->get_url_path().$r;
}
return $r;
}
/**
* Generate the URL to access the category.
*
* @param string|NULL 'param_num', 'subchap', 'chapters'
* @param string|NULL url to use
* @param integer category page to link to, default:1
* @param integer|NULL number of posts per page (used for param_num only)
* @param string glue between url params
*/
function get_permanent_url( $link_type = NULL, $blogurl = NULL, $paged = 1, $chapter_posts_per_page = NULL, $glue = '&' )
{
global $DB, $cacheweekly, $Settings;
if( empty( $link_type ) )
{ // Use default from settings:
$this->get_Blog();
$link_type = $this->Blog->get_setting( 'chapter_links' );
}
if( empty( $blogurl ) )
{
$this->get_Blog();
$blogurl = $this->Blog->gen_blogurl();
}
switch( $link_type )
{
case 'param_num':
$r = url_add_param( $blogurl, 'cat='.$this->ID, $glue );
if( empty($chapter_posts_per_page) )
{ // Use default from Blog
$this->get_Blog();
$chapter_posts_per_page = $this->Blog->get_setting( 'chapter_posts_per_page' );
}
if( !empty($chapter_posts_per_page) && $chapter_posts_per_page != $this->Blog->get_setting( 'posts_per_page' ) )
{ // We want a specific post per page count:
$r = url_add_param( $r, 'posts='.$chapter_posts_per_page, $glue );
}
break;
case 'subchap':
$this->get_Blog();
$category_prefix = $this->Blog->get_setting('category_prefix');
if( !empty( $category_prefix ) )
{
$r = url_add_tail( $blogurl, '/'.$category_prefix.'/'.$this->urlname.'/' );
}
else
{
$r = url_add_tail( $blogurl, '/'.$this->urlname.'/' );
}
break;
case 'chapters':
default:
$this->get_Blog();
$category_prefix = $this->Blog->get_setting('category_prefix');
if( !empty( $category_prefix ) )
{
$r = url_add_tail( $blogurl, '/'.$category_prefix.'/'.$this->get_url_path() );
}
else
{
$r = url_add_tail( $blogurl, '/'.$this->get_url_path() );
}
break;
}
if( $paged > 1 )
{
$r = url_add_param( $r, 'paged='.$paged, $glue );
}
return $r;
}
/**
* Get the Blog object for the Chapter.
*
* @return Blog
*/
function & get_Blog()
{
if( is_null($this->Blog) )
{
$this->load_Blog();
}
return $this->Blog;
}
/**
* Load the Blog object for the Chapter, without returning it.
*/
function load_Blog()
{
if( is_null($this->Blog) )
{
$BlogCache = & get_BlogCache();
$this->Blog = & $BlogCache->get_by_ID( $this->blog_ID );
}
}
/**
* Get sub-category ordering
*
* @param boolean actual ordering - set to false to get raw setting value with default fallback to 'parent'
* @return string
* - the setting value if actual_ordering param is false
* - the actual ordering value computed recursively from parents/blog if the actual_ordering param is true
*/
function get_subcat_ordering( $actual_ordering = true )
{
$setting_value = empty( $this->subcat_ordering ) ? 'parent' : $this->subcat_ordering;
if( ! $actual_ordering )
{
return $setting_value;
}
switch( $setting_value ) {
case 'alpha':
case 'manual':
return $this->subcat_ordering;
case 'parent':
return $this->get_parent_subcat_ordering();
default:
debug_die('Unhandled sub-category ordering value was detected');
}
}
/**
* Get blog's category ordering value in case of root categories, parent Chapter subcat ordering otherwise
*
* @return string parent subcat ordering
*/
function get_parent_subcat_ordering()
{
if( empty( $this->parent_ID ) )
{ // Return the default blog setting
$this->load_Blog();
return $this->Blog->get_setting( 'category_ordering' );
}
$this->get_parent_Chapter();
return $this->parent_Chapter->get_subcat_ordering();
}
/**
* Insert object into DB based on previously recorded changes.
*
* @return boolean true on success
*/
function dbinsert()
{
global $DB, $localtimenow;
load_funcs( 'items/model/_item.funcs.php' );
if( $this->ID != 0 ) die( 'Existing object cannot be inserted!' );
// Start transaction because of urltitle validation
$DB->begin( 'SERIALIZABLE' );
// validate url title / slug
$this->set( 'urlname', urltitle_validate( $this->urlname, $this->name, $this->ID, false, $this->dbprefix.'urlname', $this->dbIDname, $this->dbtablename) );
$this->set_param( 'last_touched_ts', 'date', date( 'Y-m-d H:i:s', $localtimenow ) );
if( parent::dbinsert() )
{ // The chapter was inserted successful
$DB->commit();
return true;
}
// Could not insert the chapter object
$DB->rollback();
return false;
}
/**
* Update the DB based on previously recorded changes
*
* @return boolean true on success
*/
function dbupdate()
{
global $DB;
// Start transaction because of urltitle validation
$DB->begin( 'SERIALIZABLE' );
// validate url title / slug
if( empty($this->urlname) || isset($this->dbchanges['cat_urlname']) )
{ // Url title has changed or is empty
$this->set( 'urlname', urltitle_validate( $this->urlname, $this->name, $this->ID, false, $this->dbprefix.'urlname', $this->dbIDname, $this->dbtablename) );
}
if( count( $this->dbchanges ) > 0 && !isset( $this->dbchanges['last_touched_ts'] ) )
{ // Update last_touched_ts field only if it wasn't updated yet and the datemodified will be updated for sure.
global $localtimenow;
$this->set_param( 'last_touched_ts', 'date', date( 'Y-m-d H:i:s', $localtimenow ) );
}
if( parent::dbupdate() === false )
{ // The update was unsuccessful
$DB->rollback();
return false;
}
// The chapter was updated successful
$DB->commit();
// BLOCK CACHE INVALIDATION:
$chapter_Blog = $this->get_Blog();
BlockCache::invalidate_key( 'cont_coll_ID', $chapter_Blog->ID ); // Content has changed
BlockCache::invalidate_key( 'cat_ID', $this->ID ); // Chaper has changed
return true;
}
/**
* Get a member param by its name
*
* @param mixed Name of parameter
* @return mixed Value of parameter
*/
function get( $parname )
{
switch( $parname )
{
case 'subcat_ordering':
return $this->get_subcat_ordering( false );
}
return parent::get( $parname );
}
/**
* Get name of Chapter
*
* @param string Output format, see {@link format_to_output()}
* @return string
*/
function get_name( $format = 'htmlbody' )
{
return $this->dget( 'name', $format );
}
/**
* Check if this category has at least one post
*
* @return boolean
*/
function has_posts()
{
global $DB;
if( $this->ID == 0 )
{ // New category has no posts
return false;
}
if( !isset( $this->count_posts ) )
{
$SQL = new SQL( 'Check if category has posts' );
$SQL->SELECT( 'COUNT( postcat_post_ID )' );
$SQL->FROM( 'T_postcats' );
$SQL->WHERE( 'postcat_cat_ID = '.$DB->quote( $this->ID ) );
$count_posts = $DB->get_var( $SQL );
$this->count_posts = $count_posts;
}
return ( $this->count_posts > 0 );
}
/**
* Update field last_touched_ts
*/
function update_last_touched_date()
{
global $localtimenow;
$this->set_param( 'last_touched_ts', 'date', date( 'Y-m-d H:i:s', $localtimenow ) );
$this->dbupdate();
}
/**
* Returns a permalink link to the Category
*
* Note: If you only want the permalink URL, use {@link Item::get_permanent_url()}
*
* @param array
*/
function get_permanent_link( $params = array() )
{
// Make sure we are not missing any param:
$params = array_merge( array(
'text' => '#name', // possible special values: ...
'title' => '',
'class' => '',
'nofollow' => false,
), $params );
// Get item permanent URL:
$url = $this->get_permanent_url();
$text = $params['text'];
switch( $text )
{
case '#linkicon':
$text = get_icon( 'permalink' );
break;
case '#text':
$text = T_('Permalink');
break;
case '#linkicon+text':
$text = get_icon( 'permalink' ).T_('Permalink');
break;
case '#expandicon':
$text = get_icon( 'file_message' );
break;
case '#name':
$text = format_to_output( $this->get( 'name' ) );
break;
case '#expandicon+name':
$text = get_icon( 'expand' ).format_to_output( $this->get( 'name' ) );
break;
case '#open+arrow':
$text = T_('Open').' »';
break;
case '#view+arrow':
$text = T_('View').' »';
break;
}
$title = $params['title'];
if( $title == '#' )
{ // Use default title for link:
$title = T_('Permanent link to category');
}
$class = $params['class'];
// Build a permanent link to Item:
$r = '<a href="'.$url.'"'
.( empty( $title ) ? '' : ' title="'.format_to_output( $title, 'htmlattr' ).'"' )
.( empty( $class ) ? '' : ' class="'.format_to_output( $class, 'htmlattr' ).'"' )
.( $params['nofollow'] ? ' rel="nofollow"' : '' )
.'>'
.str_replace( '$name$', format_to_output( $this->get( 'name' ) ), $text )
.'</a>';
return $r;
}
/**
* Get last touched date (datetime) of Chapter
*
* @param string date/time format: leave empty to use locale default date format
* @param boolean true if you want GMT
*/
function get_last_touched_date( $format = '', $useGM = false )
{
if( empty( $format ) )
{
return mysql2date( locale_datefmt(), $this->last_touched_ts, $useGM );
}
return mysql2date( $format, $this->last_touched_ts, $useGM );
}
/**
* Get URL to edit a chapter if user has edit rights.
*
* @param array Params:
* - 'redirect_page': redirect to page: 'front', 'manual', 'list'
* - 'glue' : Glue string between url params
* @return string|FALSE URL
*/
function get_edit_url( $params = array() )
{
$params = array_merge( array(
'redirect_page' => '',
'glue' => '&',
), $params );
if( ! is_logged_in( false ) )
{ // User is not logged in
return false;
}
if( ! $this->ID )
{ // New chapter
return false;
}
if( ! check_user_perm( 'admin', 'restricted' ) ||
! check_user_perm( 'blog_cats', '', false, $this->blog_ID ) )
{ // User has no right to edit this chapter
return false;
}
global $admin_url;
$url = $admin_url.'?ctrl=chapters'.$params['glue']
.'action=edit'.$params['glue']
.'cat_ID='.$this->ID.$params['glue']
.'blog='.$this->blog_ID;
if( !empty( $params['redirect_page'] ) )
{
$url .= $params['glue'].'redirect_page='.$params['redirect_page'];
}
return $url;
}
/**
* Provide link to edit a chapter if user has edit rights
*
* @param array Params:
* - 'before': to display before link
* - 'after': to display after link
* - 'text': link text
* - 'title': link title
* - 'class': CSS class name
* - 'redirect_page': redirect to page: 'front', 'manual', 'list'
* - 'glue' : Glue string between url params
* @return string|FALSE Link tag
*/
function get_edit_link( $params = array() )
{
$edit_url = $this->get_edit_url( $params );
if( ! $edit_url )
{
return false;
}
// Make sure we are not missing any param:
$params = array_merge( array(
'before' => '',
'after' => '',
'text' => '#',
'title' => '#',
'class' => '',
'redirect_page' => '',
'glue' => '&',
), $params );
if( $params['text'] == '#' ) $params['text'] = get_icon( 'edit' ).' '.T_('Edit...');
if( $params['title'] == '#' ) $params['title'] = T_('Edit this chapter...');
$r = $params['before'];
$r .= '<a href="'.$edit_url;
$r .= '" title="'.$params['title'].'"';
if( !empty( $params['class'] ) ) $r .= ' class="'.$params['class'].'"';
$r .= '>'.$params['text'].'</a>';
$r .= $params['after'];
return $r;
}
/**
* Get name of this chapter as path of all parent chapters
*
* @param array Params
* @return string
*/
function get_path_name( $params = array() )
{
$params = array_merge( array(
'separator' => ' / ',
) );
$path_name = $this->get_name();
$parent_Chapter = $this->get_parent_Chapter();
while( $parent_Chapter )
{ // Append all parent chapters name:
$path_name = $parent_Chapter->get_name().$params['separator'].$path_name;
// Get next parent Chapter:
$parent_Chapter = $parent_Chapter->get_parent_Chapter();
}
return $path_name;
}
/**
* Set param value
*
* By default, all values will be considered strings
*
* @param string parameter name
* @param mixed parameter value
* @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 )
{
switch( $parname )
{
case 'parent_ID':
return $this->set_param( $parname, 'string', $parvalue, true );
case 'image_file_ID':
return $this->set_param( $parname, 'integer', $parvalue, true );
case 'ityp_ID':
if( $this->get( 'meta' ) )
{ // Don't allow default Item Type for meta category because it cannot has items:
$parvalue = NULL;
}
elseif( ( $parvalue === 0 || $parvalue === '0' )&&
$this->ID > 0 &&
( $cat_Blog = & $this->get_Blog() ) &&
$cat_Blog->get_default_cat_ID() == $this->ID )
{ // Force "No default type" of default category to "Same as collection default":
$parvalue = NULL;
}
return $this->set_param( $parname, 'integer', $parvalue, true );
case 'name':
case 'urlname':
case 'description':
default:
return $this->set_param( $parname, 'string', $parvalue, $make_null );
}
}
/**
* Add a child
*
* @param object Chapter
*/
function add_child_category( & $Chapter )
{
if( !isset( $this->children[ $Chapter->ID ] ) )
{ // Add only if it was not added yet:
$this->children[ $Chapter->ID ] = & $Chapter;
}
}
/**
* Get File of a first found image by positions
*
* @return object|NULL File
*/
function & get_image_File()
{
// Try to get a file by ID:
$FileCache = & get_FileCache();
if( ! ( $cat_image_File = & $FileCache->get_by_ID( $this->get( 'image_file_ID' ), false, false ) ) )
{ // This chapter has no image file or it is broken:
$r = NULL;
return $r;
}
if( ! $cat_image_File->is_image() )
{ // The file must be an image:
$r = NULL;
return $r;
}
return $cat_image_File;
}
/**
* Get URL of a first found image by positions
*
* @param array Parameters
* @return string|NULL Image URL or NULL if it doesn't exist
*/
function get_image_url( $params = array() )
{
$params = array_merge( array(
'size' => 'original',
), $params );
if( ! ( $image_File = & $this->get_image_File() ) )
{ // Wrong image file:
return NULL;
}
// Get image URL for requested size:
$img_attribs = $image_File->get_img_attribs( $params['size'] );
}
/**
* Get image tag of this chapter
*
* @param array Params
* @return string HTML code of <img /> tag or empty string if this chapter has no correct image file
*/
function get_image_tag( $params = array() )
{
$params = array_merge( array(
'before' => '', // HTML code before image tag
'before_classes'=> '', // Allow injecting additional classes into 'before'
'before_legend' => '', // HTML code before image legeng(info under image tag image desc is not empty)
'after_legend' => '', // HTML code after image legeng
'after' => '', // HTML code after image tag
'size' => 'crop-48x48', // Image thumbnail size
'sizes' => NULL, // simplified sizes= attribute for browser to select correct size from srcset=. Sample value: (max-width: 430px) 400px, (max-width: 670px) 640px, (max-width: 991px) 720px, (max-width: 1199px) 698px, 848px
'link_to' => '', // URL for a link ; '#category_url' for category URL ; 'original' for full image file url ; Empty for no link
'link_title' => $this->get( 'description' ), // Title of the link, can be text or #title# or #desc#
'link_rel' => '', // Value for attribute "rel", usefull for jQuery libraries selecting on rel='...', e-g: 'lightbox[cat'.$this->ID.']'
'class' => '', // Image class
'align' => '', // Image align
'alt' => $this->get( 'name' ), // Image alt
'desc' => '#', // Image description, used in legeng under image tag, '#' - use current description of the file
'size_x' => 1, // Use '2' to build 2x sized thumbnail that can be used for Retina display
'tag_size' => NULL, // Override "width" & "height" attributes on img tag. Allows to increase pixel density for retina/HDPI screens.
// Example: ( $tag_size = '160' ) => width="160" height="160"
// ( $tag_size = '160x320' ) => width="160" height="320"
// NULL - use size defined by the thumbnail
// 'none' - don't use attributes "width" & "height"
'placeholder' => '', // HTML to be displayed if no image; possible codes: #folder_icon
), $params );
if( ! empty( $params['before_classes'] ) )
{ // Inject additional classes into 'before':
$params['before'] = update_html_tag_attribs( $params['before'], array( 'class' => $params['before_classes'] ) );
}
// Try to get a file by ID:
$FileCache = & get_FileCache();
$cat_image_File = & $FileCache->get_by_ID( $this->get( 'image_file_ID' ), false, false );
if( ! $cat_image_File // This chapter has no image file or it is broken
|| ! $cat_image_File->is_image() ) // The file is NOT an image
{ // Display placeholder:
$placeholder_html = $params['placeholder'];
switch( $placeholder_html )
{
case '#folder_icon';
$placeholder_html = '<div class="evo_image_block evo_img_placeholder"><a href="$url$" class="evo_img_placeholder"><i class="fa fa-folder-o"></i></a></div>';
break;
}
return str_replace( '$url$', $this->get_permanent_url(), $placeholder_html );
}
if( $params['link_to'] == '#category_url' )
{ // We want to link to the category URL:
$params['link_to'] = $this->get_permanent_url();
}
return $cat_image_File->get_tag( $params['before'],
$params['before_legend'],
$params['after_legend'],
$params['after'],
$params['size'],
$params['link_to'],
$params['link_title'],
$params['link_rel'],
$params['class'],
$params['align'],
$params['alt'],
$params['desc'],
'',
$params['size_x'],
$params['tag_size'],
'',
true,
$params['sizes'] );
}
/**
* Get CSS property for background with image of this Item
*
* @param array Params
* @return string
*/
function get_background_image_css( $params = array() )
{
$params = array_merge( array(
'position' => '#cover_and_teaser_all',
'size' => 'fit-1280x720',
'size_2x' => 'fit-2560x1440',
), $params );
if( ! ( $image_File = & $this->get_image_File( $params ) ) )
{ // Don't provide css for wrong image file:
return '';
}
return $image_File->get_background_image_css( $params );
}
/**
* Get default Item Type of this Chapter
*
* @param boolean TRUE to return default Item Type object of collection when this category uses same it as collection default
* @return object|false|NULL Default Item Type,
* NULL - Same as collection default (only when $use_collection_item_type == false, otherwise real Item Type object what is used as default for collection),
* FALSE - No default type or Item Type is not found in DB or Item Type is not enabled for chapter's collection
*/
function & get_ItemType( $load_coll_default_item_type = false )
{
if( $this->get( 'ityp_ID' ) === NULL && ! $load_coll_default_item_type )
{ // Item Type is same as collection default,
// Return NULL because no request to get real Item Type object:
$r = NULL;
return $r;
}
if( $this->ItemType === NULL )
{ // Load Item Type into cache:
if( $this->get( 'ityp_ID' ) === NULL && $load_coll_default_item_type )
{ // Try to get real Item Type object of this category's collection:
if( ( $cat_Blog = & $this->get_Blog() ) &&
( $coll_ItemType = & $cat_Blog->get_default_ItemType() ) )
{ // Use real Item Type object:
$this->ItemType = $coll_ItemType;
}
else
{ // Impossible to get default Item Type by some unknown reason:
$this->ItemType = false;
}
}
elseif( ( $this->get( 'ityp_ID' ) > 0 ) &&
( $ItemTypeCache = & get_ItemTypeCache() ) &&
( $cat_ItemType = & $ItemTypeCache->get_by_ID( $this->get( 'ityp_ID' ), false, false ) ) &&
( $cat_ItemType->is_enabled( $this->get( 'blog_ID' ) ) ) )
{ // Default Item Type is found in DB and it is enabled for chapter's collection:
$this->ItemType = $cat_ItemType;
}
else
{ // No default type or Item Type is not found in DB or Item Type is not enabled for chapter's collection:
$this->ItemType = false;
}
}
return $this->ItemType;
}
}
?>