<?php
/**
* This file implements Template functions.
*
* This file is part of the evoCore framework - {@link http://evocore.net/}
* See also {@link https://github.com/b2evolution/b2evolution}.
*
* @license GNU GPL v2 - {@link http://b2evolution.net/about/gnu-gpl-license}
*
* @copyright (c)2003-2020 by Francois Planque - {@link http://fplanque.com/}
*
* @package evocore
*/
if( !defined('EVO_MAIN_INIT') ) die( 'Please, do not access this page directly.' );
/**
* Render template content code depending on current locale
*
* @param string Template code
* @param array Parameters (by reference)
* @param array Objects
* @return string|boolean Rendered template or FALSE on wrong request
*/
function render_template_code( $code, & $params, $objects = array(), & $used_template_tags = NULL )
{
$TemplateCache = & get_TemplateCache();
if( $Template = & $TemplateCache->get_localized_by_code( $code, false, false ) )
{ // Render variables in available Template:
return render_template( $Template->template_code, $params, $objects, $used_template_tags );
}
return false;
}
/**
* Render template content
*
* @param string Template
* @param array Parameters (by reference)
* @param array Objects
* @return string Rendered template
*/
function render_template( $template, & $params, $objects = array(), & $used_template_tags = NULL )
{
$current_pos = 0;
$r = '';
// New
preg_match_all( '/\[((?:(?:Cat|Coll|Comment|File|Form|Item|Link|Plugin|Tag|User|echo|set|param):)?([a-z0-9_]+))\|?((?:.|\n|\r|\t)*?)\]/i', $template, $matches, PREG_OFFSET_CAPTURE );
foreach( $matches[0] as $i => $match )
{
// Output everything until new tag:
$r .= substr( $template, $current_pos, $match[1] - $current_pos );
$current_pos = $match[1] + strlen( $match[0] );
// New tag to handle:
$tag = $matches[1][$i][0];
// Params specified for the tag:
$tag_param_strings = empty( $matches[3][$i][0] ) ? NULL : $matches[3][$i][0];
if( substr( $tag, 0, 4 ) == 'set:' || substr( $tag, 0, 6 ) == 'param:' )
{ // Set new or default param value in the $params[] array used for the whole template (will affect all future template tags)
// Override/Set new param OR Initialize default value?
$override_param = ( substr( $tag, 0, 4 ) == 'set:' );
$param_name = substr( $tag, $override_param ? 4 : 6 );
$param_val = substr( $tag_param_strings, strpos( $tag_param_strings, '=' ) + 1 );
$param_strings = $param_name.'='.$param_val;
$param_strings = explode( '|', $param_strings );
foreach( $param_strings as $param_string )
{
if( empty( $param_string ) || ctype_space( $param_string ) )
{ // Nothing here, ignore:
continue;
}
$param_name = substr( $param_string, 0, strpos( $param_string, '=' ) );
if( empty( $param_name ) )
{ // Does not contain a param name, ignore:
continue;
}
if( strpos( $param_name, '//' ) !== false )
{ // We found a comment that we should remove:
$param_name = preg_replace( '~(.*)//.*$~im','$1', $param_name );
}
// Trim off whitespace:
$param_name = trim( $param_name );
$param_val = substr( $param_string, strpos( $param_string, '=' ) + 1 );
if( $override_param || ! isset( $params[ $param_name ] ) )
{ // Set new param or default param:
// we MUST do this here and in & $params[] so that it sticks. This cannot be done in the callback or $this_tag_params[]
$params[ $param_name ] = $param_val;
}
}
}
else
{ // Process a normal template tag:
// Decode PARAMS like |name=value|name=value]
$this_tag_params = get_template_tag_params_from_string( $tag_param_strings, $params );
if( is_array( $used_template_tags ) )
{
$used_template_tags[] = $tag;
}
$r .= render_template_callback( $tag, $this_tag_params, $objects );
}
}
// Print remaining template code:
$r .= substr( $template, $current_pos );
return $r;
}
/**
* Get params of tempalte tag from provided string
*
* @param string Params in string format
* @param array Default params
* @return array Params in array format
*/
function get_template_tag_params_from_string( $tag_param_strings, $default_params = array() )
{
$this_tag_params = $default_params;
if( empty( $tag_param_strings ) )
{
return $this_tag_params;
}
$tag_param_strings = explode( '|', $tag_param_strings );
// Process each param individually:
foreach( $tag_param_strings as $tag_param_string )
{
if( empty( $tag_param_string ) || ctype_space( $tag_param_string) )
{
continue;
}
$tag_param_name = substr( $tag_param_string, 0, strpos( $tag_param_string, '=' ) );
if( strpos( $tag_param_name, '//' ) !== false )
{ // We found a comment that we should remove:
$tag_param_name = preg_replace( '~(.*)//.*$~im','$1', $tag_param_name );
}
// Trim off whitespace:
$tag_param_name = trim( $tag_param_name );
if( $tag_param_name === '' )
{ // Skip empty param:
continue;
}
$tag_param_val = substr( $tag_param_string, strpos( $tag_param_string, '=' ) + 1 );
if( preg_match('/\$([a-z_]+)\$/i', $tag_param_val, $tag_param_val_matches ) )
{ // We have a variable to replace: // TODO: allow multiple variable replace
$found_param_name = $tag_param_val_matches[1];
if( isset( $default_params[$found_param_name] ) )
{ // We have an original param of that name:
$tag_param_val = $default_params[$found_param_name];
}
}
// TODO: need to escape " and > from $tag_param_val, otherwise they will end up breaking something
$this_tag_params[$tag_param_name] = $tag_param_val;
}
return $this_tag_params;
}
/**
* Callback function to replace variables in template
*
* @param string Variable to be replaced
* @param array Additional parameters (by reference)
* @param array Objects
* @return string Replacement string
*/
function render_template_callback( $var, $params, $objects = array() )
{
// Get scope and var name:
preg_match( '#^(([a-z]+):)?(.+)$#i', $var, $match_var );
$scope = ( empty( $match_var[2] ) ? 'Item': $match_var[2] );
$var = $scope.':'.$match_var[3];
switch( $scope )
{
case 'Cat':
global $Chapter;
$rendered_Chapter = ( !isset( $objects['Chapter'] ) ? $Chapter : $objects['Chapter'] );
if( empty( $rendered_Chapter ) || ! ( $rendered_Chapter instanceof Chapter ) )
{
return get_rendering_error( '['.$var.']: Object Chapter/Category is not defined at this moment.', 'span' );
}
break;
case 'Coll':
global $Blog;
$rendered_Blog = ( !isset( $objects['Collection'] ) ? $Blog : $objects['Collection'] );
if( empty( $rendered_Blog ) || ! ( $rendered_Blog instanceof Blog ) )
{
return get_rendering_error( '['.$var.']: Object Collection/Blog is not defined at this moment.', 'span' );
}
break;
case 'Comment':
global $Comment;
$rendered_Comment = ( !isset( $objects['Comment'] ) ? $Comment : $objects['Comment'] );
if( empty( $rendered_Comment ) || ! ( $rendered_Comment instanceof Comment ) )
{
return get_rendering_error( '['.$var.']: Object Comment is not defined at this moment.', 'span' );
}
break;
case 'File':
global $File;
$rendered_File = ( !isset( $objects['File'] ) ? $File : $objects['File'] );
if( empty( $rendered_File ) || ! ( $rendered_File instanceof File ) )
{
return get_rendering_error( '['.$var.']: Object File is not defined at this moment.', 'span' );
}
break;
case 'Form':
global $Form;
$rendered_Form = ( !isset( $objects['Form'] ) ? $Form : $objects['Form'] );
if( empty( $rendered_Form ) || ! ( $rendered_Form instanceof Form ) )
{
return get_rendering_error( '['.$var.']: Object Form is not defined at this moment.', 'span' );
}
break;
case 'Item':
global $Item;
$rendered_Item = ( !isset( $objects['Item'] ) ? $Item : $objects['Item'] );
if( empty( $rendered_Item ))
{
return get_rendering_error( '['.$var.']: Object Item is not defined at this moment.', 'span' );
}
if( ! ( $rendered_Item instanceof Item ) )
{
return get_rendering_error( 'Item object has class <code>'.get_class($rendered_Item).'</code> instead of expected <code>Item</code>.', 'span' );
}
break;
case 'Link':
// do nothing
break;
case 'Plugin':
global $Plugins;
$rendered_Plugin = & $Plugins->get_by_code( $match_var[3] );
if( empty( $rendered_Plugin ) )
{
return get_rendering_error( 'Plugin <code>'.$match_var[3].'</code> is not installed.', 'span' );
}
$var = $scope;
break;
case 'Tag':
$tag = ( !isset( $objects['tag'] ) ? $tag : $objects['tag'] );
if( empty( $tag ))
{
return get_rendering_error( '['.$var.']: Tag is not defined at this moment.', 'span' );
}
break;
case 'echo':
$param_name = substr( $var, 5 );
if( ! isset( $params[ $param_name ] ) )
{ // Param is not found:
return get_rendering_error( 'Param <code>'.$param_name.'</code> is not passed.', 'span' );
}
elseif( ! is_scalar( $params[ $param_name ] ) )
{ // Param is not scalar and cannot be printed on screen:
return get_rendering_error( 'Param <code>'.$param_name.'</code> is not scalar.', 'span' );
}
break;
case 'User':
global $User;
$rendered_User = ( !isset( $objects['User'] ) ? $User : $objects['User'] );
if( empty( $rendered_User ) || ! ( $rendered_User instanceof User ) )
{
return get_rendering_error( '['.$var.']: Object User is not defined at this moment.', 'span' );
}
break;
default:
return get_rendering_error( '['.$var.']: Scope "'.$scope.':" is not recognized.', 'span' );
}
$match_found = true;
ob_start();
switch( $var )
{
// Chapter / Category:
case 'Cat:background_image_css':
echo $rendered_Chapter->get_background_image_css( $params );
break;
case 'Cat:description':
echo $rendered_Chapter->dget( 'description' );
break;
case 'Cat:image':
echo $rendered_Chapter->get_image_tag( array_merge( array(
'before_classes' => '', // Allow injecting additional classes into 'before'
'size' => 'crop-256x256',
'link_to' => '#category_url',
'placeholder' => '#folder_icon',
), $params ) );
break;
case 'Cat:image_url':
echo $rendered_Chapter->get_image_url( $params );
break;
case 'Cat:name':
echo $rendered_Chapter->dget( 'name' );
break;
case 'Cat:permalink':
echo $rendered_Chapter->get_permanent_link( array_merge( array(
'text' => '#name',
'title' => '',
), $params ) );
break;
// Collection:
case 'Coll:shortname':
echo $rendered_Blog->dget( 'shortname' );
break;
// Comment:
case 'Comment:author':
echo $rendered_Comment->get_author( array_merge( array(
'link_text' => 'auto', // select login or nice name automatically
), $params ) );
break;
case 'Comment:creation_time':
$temp_params = array_merge( array(
'format' => '#short_date_time',
'useGM' => false,
), $params );
echo $rendered_Comment->get_creation_time( $temp_params['format'], $temp_params['useGM'] );
break;
case 'Comment:content':
$temp_params = array_merge( array(
'format' => 'htmlbody',
'ban_urls' => false,
'show_attachments' => false,
), $params );
echo $rendered_Comment->content( $temp_params['format'], $temp_params['ban_urls'], $temp_params['show_attachments'], $temp_params );
break;
case 'Comment:excerpt':
echo $rendered_Comment->get_excerpt( $params );
break;
case 'Comment:permalink':
$rendered_Comment->permanent_link( array_merge( array(
'text' => '#item#',
'title' => '', // No tooltip by default
), $params ) );
break;
// File:
case 'File:description':
echo $rendered_File->get_description( $params );
break;
case 'File:file_size':
echo $rendered_File->get_size_formatted();
break;
case 'File:icon':
echo $rendered_File->get_icon();
break;
case 'File:type':
echo $rendered_File->get_type();
break;
case 'File:url':
echo $rendered_File->get_url();
break;
case 'File:file_link':
echo $rendered_File->get_file_link( $params );
break;
// Form:
case 'Form:country':
global $Settings;
$country = param( 'country', 'integer', 0 );
$temp_params = array(
'name' => 'country',
'value' => $country,
'label' => T_('Country'),
'hide_label' => false,
'note' => '',
'bottom_note' => '',
'class' => '',
'style' => '',
'required' => isset( $params['reg1_required'] ) ? in_array( 'country', array_map( 'trim', explode( ',', $params['reg1_required'] ) ) ) : false,
);
// Only params specified in $temp_params above will be passed to prevent unknown params transformed into input attributes!
$temp_params = array_merge( $temp_params, array_intersect_key( $params, $temp_params ) );
$CountryCache = & get_CountryCache();
$rendered_Form->select_country( $temp_params['name'], $temp_params['value'], $CountryCache, $temp_params['label'], $temp_params );
break;
case 'Form:email':
global $dummy_fields;
$email = utf8_strtolower( param( $dummy_fields['email'], 'string', '' ) );
if( isset( $objects['register_user_data']['email'] ) )
{
$email = $objects['register_user_data']['email'];
}
$temp_params = array(
'name' => $dummy_fields['email'],
'value' => $email,
'label' => T_('Email'),
'hide_label' => false,
'note' => '',
'bottom_note' => T_('We respect your privacy. Your email will remain strictly confidential.'),
'placeholder' => $params['register_use_placeholders'] ? T_('Email address') : '',
'size' => 50,
'maxlength' => 255,
'class' => 'input_text wide_input',
'style' => '',
'required' => isset( $params['reg1_required'] ) ? in_array( 'email', array_map( 'trim', explode( ',', $params['reg1_required'] ) ) ) : false,
);
// Only params specified in $temp_params above will be passed to prevent unknown params transformed into input attributes!
$temp_params = array_merge( $temp_params, array_intersect_key( $params, $temp_params ) );
$rendered_Form->email_input( $temp_params['name'], $temp_params['value'], $temp_params['size'], $temp_params['label'], $temp_params );
break;
case 'Form:firstname':
global $Settings;
$firstname = param( 'firstname', 'string', '' );
$temp_params = array(
'name' => 'firstname',
'value' => $firstname,
'label' => T_('First name'),
'hide_label' => false,
'note' => T_('Your real first name'),
'bottom_note' => '',
'placeholder' => '',
'size' => 18,
'maxlength' => 50,
'class' => 'input_text',
'style' => '',
'required' => isset( $params['reg1_required'] ) ? in_array( 'firstname', array_map( 'trim', explode( ',', $params['reg1_required'] ) ) ) : false,
);
// Only params specified in $temp_params above will be passed to prevent unknown params transformed into input attributes!
$temp_params = array_merge( $temp_params, array_intersect_key( $params, $temp_params ) );
$rendered_Form->text_input( $temp_params['name'], $temp_params['value'], $temp_params['size'], $temp_params['label'], $temp_params['note'], $temp_params );
break;
case 'Form:gender':
global $Settings;
$gender = param( 'gender', 'string', false );
$temp_params = array(
'name' => 'gender',
'value' => $gender,
'label' => T_('I am'),
'hide_label' => false,
'note' => '',
'bottom_note' => '',
'class' => '',
'style' => '',
'required' => isset( $params['reg1_required'] ) ? in_array( 'gender', array_map( 'trim', explode( ',', $params['reg1_required'] ) ) ) : false,
);
// Only params specified in $temp_params above will be passed to prevent unknown params transformed into input attributes!
$temp_params = array_merge( $temp_params, array_intersect_key( $params, $temp_params ) );
$rendered_Form->radio_input( $temp_params['name'], $temp_params['value'], array(
array( 'value' => 'M', 'label' => T_('A man') ),
array( 'value' => 'F', 'label' => T_('A woman') ),
array( 'value' => 'O', 'label' => T_('Other') ),
), $temp_params['label'], $temp_params );
break;
case 'Form:lastname':
global $Settings;
$lastname = param( 'lastname', 'string', '' );
$temp_params = array(
'name' => 'lastname',
'value' => $lastname,
'label' => T_('Last name'),
'hide_label' => false,
'note' => T_('Your real last name'),
'bottom_note' => '',
'placeholder' => '',
'size' => 18,
'maxlength' => 50,
'class' => 'input_text',
'style' => '',
'required' => isset( $params['reg1_required'] ) ? in_array( 'lastname', array_map( 'trim', explode( ',', $params['reg1_required'] ) ) ) : false,
);
// Only params specified in $temp_params above will be passed to prevent unknown params transformed into input attributes!
$temp_params = array_merge( $temp_params, array_intersect_key( $params, $temp_params ) );
$rendered_Form->text_input( $temp_params['name'], $temp_params['value'], $temp_params['size'], $temp_params['label'], $temp_params['note'], $temp_params );
break;
case 'Form:locale':
global $Settings, $current_locale;
$temp_params = array(
'name' => 'locale',
'value' => $current_locale,
'label' => T_('Locale'),
'hide_label' => false,
'note' => T_('Preferred language'),
'bottom_note' => '',
'class' => '',
'style' => '',
'required' => isset( $params['reg1_required'] ) ? in_array( 'locale', array_map( 'trim', explode( ',', $params['reg1_required'] ) ) ) : false,
);
// Only params specified in $temp_params above will be passed to prevent unknown params transformed into input attributes!
$temp_params = array_merge( $temp_params, array_intersect_key( $params, $temp_params ) );
$rendered_Form->select_input( $temp_params['name'], $temp_params['value'], 'locale_options_return', $temp_params['label'], $temp_params );
break;
case 'Form:login':
global $dummy_fields;
$login = param( $dummy_fields['login'], 'string', '' );
if( isset( $objects['register_user_data']['login'] ) )
{
$login = $objects['register_user_data']['login'];
}
$temp_params = array( // Here, we make sure not to modify $params
'name' => $dummy_fields['login'],
'value' => $login,
'label' => /* TRANS: noun */ T_('Login'),
'hide_label' => false,
'note' => $params['register_use_placeholders'] ? '' : T_('Choose a username').'.',
'bottom_note' => '',
'placeholder' => $params['register_use_placeholders'] ? T_('Choose a username') : '',
'size' => 22,
'maxlength' => 20,
'class' => 'input_text',
'style' => 'width:'.( $params['register_field_width'] - 2 ).'px',
'required' => isset( $params['reg1_required'] ) ? in_array( 'login', array_map( 'trim', explode( ',', $params['reg1_required'] ) ) ) : false,
'input_suffix' => ' <span id="login_status"></span><span class="help-inline"><div id="login_status_msg" class="red"></div></span>',
);
// Only params specified in $temp_params above will be passed to prevent unknown params transformed into input attributes!
$temp_params = array_merge( $temp_params, array_intersect_key( $params, $temp_params ) );
$rendered_Form->text_input( $temp_params['name'], $temp_params['value'], $temp_params['size'], $temp_params['label'], $temp_params['note'], $temp_params );
break;
case 'Form:password':
global $dummy_fields;
$temp_params = array(
'name' => $dummy_fields['pass1'],
'value' => '',
'label' => T_('Password'),
'hide_label' => false,
'note' => $params['register_use_placeholders'] ? '' : T_('Choose a password').'.',
'placeholder' => $params['register_use_placeholders'] ? T_('Choose a password') : '',
'bottom_note' => '',
'size' => 18,
'maxlength' => 70,
'class' => 'input_text',
'style' => 'width:'.$params['register_field_width'].'px',
'required' => isset( $params['reg1_required'] ) ? in_array( 'password', array_map( 'trim', explode( ',', $params['reg1_required'] ) ) ) : false,
'autocomplete' => 'off',
);
// Only params specified in $temp_params above will be passed to prevent unknown params transformed into input attributes!
$temp_params = array_merge( $temp_params, array_intersect_key( $params, $temp_params ) );
$rendered_Form->password_input( $temp_params['name'], $temp_params['value'], $temp_params['size'], $temp_params['label'], $temp_params );
$temp_params = array(
'name_confirm' => $dummy_fields['pass2'],
'value_confirm' => '',
'label_confirm' => '',
'hide_label_confirm' => false,
'note_confirm' => ( $params['register_use_placeholders'] ? '' : T_('Please type your password again').'.' ).'<div id="pass2_status" class="red"></div>',
'bottom_note_confirm' => '',
'placeholder_confirm' => $params['register_use_placeholders'] ? T_('Please type your password again') : '',
'size_confirm' => 18,
'maxlength_confirm' => 70,
'class_confirm' => 'input_text',
'style_confirm' => 'width:'.$params['register_field_width'].'px',
'required_confirm' => isset( $params['reg1_required'] ) ? in_array( 'password', array_map( 'trim', explode( ',', $params['reg1_required'] ) ) ) : false,
'autocomplete_confirm' => 'off',
);
// Only params specified in $temp_params above will be passed to prevent unknown params transformed into input attributes!
$temp_params = array_merge( $temp_params, array_intersect_key( $params, $temp_params ) );
$confirm_params = array();
foreach( $temp_params as $key => $value )
{
if( substr( $key, -8 ) === '_confirm' )
{
$key = substr( $key, 0, strlen( $key ) - 8 );
}
$confirm_params[$key] = $value;
}
$rendered_Form->password_input( $confirm_params['name'], $confirm_params['value'], $confirm_params['size'], $confirm_params['label'], $confirm_params );
break;
case 'Form:search_author':
$search_author = param( 'search_author', 'string', NULL );
$temp_params = array( // Here, we make sure not to modify $params
'name' => 'search_author',
'value' => $search_author,
'label' => '',
'hide_label' => true,
'note' => '',
'bottom_note' => '',
'placeholder' => T_('Any author'),
'size' => '',
'maxlength' => '',
'class' => 'input_text'.is_logged_in() ? '' : ' autocomplete_login',
'style' => '',
'required' => false,
'input_suffix' => '',
);
// Only params specified in $temp_params above will be passed to prevent unknown params transformed into input attributes!
$temp_params = array_merge( $temp_params, array_intersect_key( $params, $temp_params ) );
$rendered_Form->text_input( $temp_params['name'], $temp_params['value'], $temp_params['size'], $temp_params['label'], $temp_params['note'], $temp_params );
break;
case 'Form:search_content_age':
$search_content_age = param( 'search_content_age', 'string' );
$content_age_options = array(
'' => T_('Any time'),
'hour' => T_('Last hour'),
'day' => T_('Less than a day'),
'week' => T_('Less than a week'),
'30d' => T_('Last 30 days'),
'90d' => T_('Last 90 days'),
'year' => T_('Last year'),
);
$temp_params = array(
'name' => 'search_content_age',
'value' => $search_content_age,
'label' => T_('Content age'),
'hide_label' => true,
'note' => '',
'bottom_note' => '',
'class' => '',
'style' => '',
'required' => false,
);
// Only params specified in $temp_params above will be passed to prevent unknown params transformed into input attributes!
$temp_params = array_merge( $temp_params, array_intersect_key( $params, $temp_params ) );
$rendered_Form->select_input_array( $temp_params['name'], $temp_params['value'], $content_age_options, $temp_params['label'], $temp_params['note'], $temp_params );
break;
case 'Form:search_content_type':
global $Blog;
if( ! $Blog )
{
return get_rendering_error( '['.$var.']: Object Blog is not defined at this moment.', 'span' );
}
$search_type = param( 'search_type', 'string', NULL );
$content_type_options = array();
if( $Blog->get_setting( 'search_include_posts' ) )
{
$content_type_options['item'] = T_('Posts');
}
if( $Blog->get_setting( 'search_include_cmnts' ) )
{
$content_type_options['comment'] = T_('Comments');
}
if( $Blog->get_setting( 'search_include_metas' ) &&
check_user_perm( 'meta_comment', 'view', false, $Blog->ID ) )
{
$content_type_options['meta'] = T_('Internal comments');
}
if( $Blog->get_setting( 'search_include_files' ) )
{
$content_type_options['file'] = T_('Files');
}
if( $Blog->get_setting( 'search_include_cats' ) )
{
$content_type_options['category'] = T_('Categories');
}
if( $Blog->get_setting( 'search_include_tags' ) )
{
$content_type_options['tag'] = T_('Tags');
}
if( count( $content_type_options ) > 1 )
{
$content_type_options = array( '' => T_('All') ) + $content_type_options;
$temp_params = array(
'name' => 'search_type',
'value' => $search_type,
'label' => T_('Content type'),
'hide_label' => true,
'note' => '',
'bottom_note' => '',
'class' => '',
'style' => '',
'required' => false,
);
// Only params specified in $temp_params above will be passed to prevent unknown params transformed into input attributes!
$temp_params = array_merge( $temp_params, array_intersect_key( $params, $temp_params ) );
$rendered_Form->select_input_array( $temp_params['name'], $temp_params['value'], $content_type_options, $temp_params['label'], $temp_params['note'], $temp_params );
}
else
{ // Do not display anything
return;
}
break;
case 'Form:search_input':
$search_term = param('s', 'string', '');
$temp_params = array( // Here, we make sure not to modify $params
'name' => 's',
'value' => $search_term,
'label' => '',
'hide_label' => true,
'note' => '',
'placeholder' => '',
'size' => 25,
'maxlength' => 100,
'class' => 'input_text',
'style' => '',
'required' => false,
'input_suffix' => '',
);
// Only params specified in $temp_params above will be passed to prevent unknown params transformed into input attributes!
$temp_params = array_merge( $temp_params, array_intersect_key( $params, $temp_params ) );
$rendered_Form->text_input( $temp_params['name'], $temp_params['value'], $temp_params['size'], $temp_params['label'], $temp_params['note'], $temp_params );
break;
case 'Form:submit':
$temp_params = array(
'name' => 'submit',
'value' => T_('Submit'),
'class' => 'btn btn-primary',
'style' => '',
);
// Only params specified in $temp_params above will be passed to prevent unknown params transformed into input attributes!
$temp_params = array_merge( $temp_params, array_intersect_key( $params, $temp_params ) );
$rendered_Form->submit_input( $temp_params );
break;
// Item:
case 'Item:author':
$rendered_Item->author( array_merge( array(
'link_text' => 'auto', // select login or nice name automatically
), $params ) );
break;
case 'Item:background_image_css':
echo $rendered_Item->get_background_image_css( $params );
break;
case 'Item:cat_name':
if( $item_main_Chapter = & $rendered_Item->get_main_Chapter() )
{
echo $item_main_Chapter->dget( 'name' );
}
break;
case 'Item:categories':
$rendered_Item->categories( array_merge( array(
'before' => '', // For some reason the core has ' ' as default, which is not good for templates
'after' => '', // For some reason the core has ' ' as default, which is not good for templates
), $params ) );
break;
case 'Item:content_extension':
echo $rendered_Item->content_extension( $params );
break;
case 'Item:content_teaser':
echo $rendered_Item->content_teaser( $params );
break;
case 'Item:contents_last_updated':
case 'Item:last_updated':
$temp_params = array_merge( array( // Here, we make sure not to modify $params
'format' => '#short_date_time',
), $params );
echo $rendered_Item->get_contents_last_updated_ts( $temp_params['format'] );
break;
case 'Item:creation_time':
$temp_params = array_merge( array( // Here, we make sure not to modify $params
'format' => '#short_date_time',
), $params );
echo $rendered_Item->get_creation_time( $temp_params['format'] );
break;
case 'Item:custom':
$temp_params = array_merge( array( // Here, we make sure not to modify $params
'field' => '',
), $params );
$rendered_Item->custom( $temp_params );
break;
case 'Item:custom_fields':
echo $rendered_Item->get_custom_fields( $params );
break;
case 'Item:edit_link':
$rendered_Item->edit_link( $params );
break;
case 'Item:excerpt':
$rendered_Item->excerpt( array_merge( array(
'before' => '',
'after' => '',
'excerpt_before_more' => ' <span class="evo_post__excerpt_more_link">',
'excerpt_after_more' => '</span>',
'excerpt_more_text' => '#more+arrow',
), $params ) );
break;
case 'Item:feedback_link':
echo $rendered_Item->get_feedback_link( array_merge( array(
'show_in_single_mode' => true,
), $params ) );
break;
case 'Item:files':
echo $rendered_Item->get_files( $params );
break;
case 'Item:flag_icon':
echo $rendered_Item->get_flag( $params );
break;
case 'Item:footer':
echo $rendered_Item->footer( array_merge( array( // Here, we make sure not to modify $params
'block_start' => '<div class="evo_post_footer">',
'block_end' => '</div>',
), $params ) );
break;
case 'Item:history_link':
echo $rendered_Item->get_history_link( array_merge( array(
'link_text' => T_('View change history'),
), $params ) );
break;
case 'Item:id':
echo $rendered_Item->ID;
break;
case 'Item:image_url':
echo $rendered_Item->get_image_url( $params );
break;
case 'Item:images':
echo $rendered_Item->get_images( array_merge( array(
'restrict_to_image_position' => 'teaser,teaserperm,teaserlink,aftermore', // 'teaser'|'teaserperm'|'teaserlink'|'aftermore'|'inline'|'cover'|'background',
// '#teaser_all' => 'teaser,teaserperm,teaserlink',
// '#cover_and_teaser_all' => 'cover,background,teaser,teaserperm,teaserlink'
'limit' => 1000, // Max # of images displayed
'before' => '<div>',
'before_image' => '<figure class="evo_image_block">',
'before_image_classes' => '', // Allow injecting additional classes into 'before image'
'before_image_legend' => '<div class="evo_image_legend">',
'after_image_legend' => '</div>',
'after_image' => '</figure>',
'after' => '</div>',
'image_size' => 'fit-720x500',
'image_size_x' => 1, // Use '2' to build 2x sized thumbnail that can be used for Retina display
'image_sizes' => NULL, // Simplified "sizes=" attribute for browser to select correct size from "srcset=".
// Must be set DIFFERENTLY depending on WIDGET/CONTAINER/SKIN LAYOUT. Each time we must estimate the size the image will have on screen.
// Sample value: (max-width: 430px) 400px, (max-width: 670px) 640px, (max-width: 991px) 720px, (max-width: 1199px) 698px, 848px
'image_link_to' => 'original', // Can be 'original' (image), 'single' (this post), an be URL, can be empty
// Note: Widget MAY have set the following for same CAT navigation:
// 'post_navigation' => 'same_category', // Stay in the same category if Item is cross-posted
// 'nav_target' => $params['chapter_ID'], // for use with 'same_category' : set the category ID as nav target
// Note: Widget MAY have set the following for same COLL navigation:
// 'target_blog' => 'auto', // Stay in current collection if it is allowed for the Item
), $params ) );
break;
case 'Item:issue_date':
$rendered_Item->issue_date( $params );
break;
case 'Item:issue_time':
$rendered_Item->issue_time( $params );
break;
case 'Item:last_touched':
$temp_params = array_merge( array( // Here, we make sure not to modify $params
'format' => '#short_date_time',
), $params );
echo $rendered_Item->get_last_touched_ts( $temp_params['format'] );
break;
case 'Item:lastedit_user':
$rendered_Item->lastedit_user( array_merge( array(
'link_text' => 'auto', // select login or nice name automatically
), $params ) );
break;
case 'Item:location':
$temp_params = array_merge( array( // Here, we make sure not to modify $params
'before' => '<div class="evo_post_location"><strong>'.T_('Location').': </strong>',
'after' => '</div>',
'separator' => ', ',
), $params );
echo $rendered_Item->get_location( $temp_params['before'], $temp_params['after'], $temp_params['separator'] );
break;
case 'Item:mod_date':
$temp_params = array_merge( array( // Here, we make sure not to modify $params
'format' => '#short_date_time',
), $params );
echo $rendered_Item->get_mod_date( $temp_params['format'] );
break;
case 'Item:more_link':
// Display "more" link to "After more" or follow-up anchor
// WARNING: does not work if no "after more" part
// If you want a "go from excerpt to full post, use "Item:permalink"
echo $rendered_Item->get_more_link( array_merge( array(
'before' => '<p class="evo_post_more_link">',
'after' => '</p>',
), $params ) );
break;
case 'Item:page_links':
echo $rendered_Item->get_page_links( array_merge( array(
'separator' => '· ',
), $params ) );
break;
case 'Item:permalink':
case 'Item:permanent_link':
$rendered_Item->permanent_link( array_merge( array(
'text' => '#title',
'title' => '', // No tooltip by default
// Note: Widget MAY have set the following for same CAT navigation:
// 'post_navigation' => 'same_category', // Stay in the same category if Item is cross-posted
// 'nav_target' => $params['chapter_ID'], // for use with 'same_category' : set the category ID as nav target
// Note: Widget MAY have set the following for same COLL navigation:
// 'target_blog' => 'auto', // Stay in current collection if it is allowed for the Item
), $params ) );
break;
case 'Item:permanent_url':
$temp_params = array_merge( array(
'target_blog' => '',
'post_navigation' => '',
'nav_target' => NULL,
), $params );
echo $rendered_Item->get_item_url( $temp_params['target_blog'], $temp_params['post_navigation'], $temp_params['nav_target'] );
break;
case 'Item:propose_change_link':
$rendered_Item->propose_change_link( array_merge( array(
'text' => T_('Propose a change'),
), $params ) );
break;
case 'Item:read_status':
$rendered_Item->display_unread_status( array_merge( array(
'style' => 'text',
'before' => '<span class="evo_post_read_status">',
'after' => '</span>'
), $params ) );
break;
case 'Item:refresh_contents_last_updated_link':
echo $rendered_Item->get_refresh_contents_last_updated_link( $params );
break;
case 'Item:tags':
$rendered_Item->tags( array_merge( array(
'before' => '', // For some reason the core has '<div>... ' as default, which is not good for templates
'after' => '', // For some reason the core has '</div>' as default, which is not good for templates
), $params ) );
break;
case 'Item:title':
echo $rendered_Item->dget( 'title' );
break;
case 'Item:type':
echo $rendered_Item->get_type_setting( 'name' );
break;
case 'Item:url_link':
$rendered_Item->url_link( $params );
break;
case 'Item:visibility_status':
if( $rendered_Item->status != 'published' )
{
$temp_params = array_merge( array(
'status_template' => '<div class="evo_status evo_status__$status$ badge" data-toggle="tooltip" data-placement="top" title="$tooltip_title$">$status_title$</div>',
), $params );
// Override param 'template' to avoid conflict in params in the status function,
// because here param 'template' contains a code of quick template:
$temp_params['template'] = $temp_params['status_template'];
echo $rendered_Item->get_format_status( $temp_params );
}
break;
// Link:
case 'Link:disp':
$temp_params = array_merge( array(
'text' => '',
'class' => '',
'max_url_length' => NULL,
), $params );
if( empty( $temp_params['disp'] ) )
{
display_rendering_error( '['.$var.']: Missing required param "disp".', 'span' );
break;
}
switch( $temp_params['disp'] )
{
case 'login':
$source = param( 'source', 'string', 'register form' );
$redirect_to = param( 'redirect_to', 'url', '' );
$return_to = param( 'return_to', 'url', '' );
// We are not using
$temp_params = array_merge( array(
'source' => $source,
'redirect_to' => $redirect_to,
'return_to' => $return_to,
'force_normal_login' => false,
'blog_ID' => NULL,
'blog_page' => 'loginurl',
), $temp_params );
$disp_url = get_login_url( $temp_params['source'], $temp_params['redirect_to'], $temp_params['force_normal_login'],
$temp_params['blog_ID'], $temp_params['blog_page'] );
break;
default:
$temp_params = array_merge( array(
'params' => '',
), $temp_params );
$disp_url = get_dispctrl_url( $temp_params['disp'], $temp_params['params'] );
}
if( $disp_url )
{
echo get_link_tag( $disp_url, $temp_params['text'], $temp_params['class'], $temp_params['max_url_length'] );
}
else
{
display_rendering_error( '['.$var.']: disp "'.$temp_params['disp'].'" is not recognized.', 'span' );
}
break;
case 'Plugin':
$rendered_Plugin->SkinTag( $params );
break;
// Tag:
case 'Tag:name':
echo $tag;
break;
case 'Tag:permalink':
global $Blog;
$rendered_Blog = ( !isset( $objects['Collection'] ) ? $Blog : $objects['Collection'] );
if( empty( $rendered_Blog ) || ! ( $rendered_Blog instanceof Blog ) )
{
return get_rendering_error( '['.$var.']: Object Collection/Blog is not defined at this moment.', 'span' );
}
$temp_params = array(
'class' => '',
'style' => '',
'rel' => NULL,
'text' => NULL,
'title' => '',
);
// Only params specified in $temp_params above will be passed to prevent unknown params transformed into input attributes!
$temp_params = array_merge( $temp_params, array_intersect_key( $params, $temp_params ) );
echo $rendered_Blog->get_tag_link( $tag, $temp_params['text'], $temp_params );
break;
// User:
case 'User:custom':
$temp_params = array_merge( array( // Here, we make sure not to modify $params
'field' => NULL,
'before' => '',
'before_item' => '',
'after_item' => '',
'after' => '',
'separator' => '',
'limit' => NULL,
), $params );
$userfield_values = $rendered_User->userfield_values_by_code( $temp_params['field'], true );
if( is_array( $userfield_values ) )
{ // We expect $userfield_values to be an Array:
if( isset( $temp_params['limit'] ) )
{
$userfield_values = array_slice( $userfield_values, 0, ( int ) $temp_params['limit'] );
}
if( ! empty( $temp_params['before_item'] ) || ! empty( $temp_params['after_item'] ) )
{
$temp_values = array();
foreach( $userfield_values as $userfield_value )
{
$temp_values[] = $temp_params['before_item'].$userfield_value.$temp_params['after_item'];
}
$userfield_values = $temp_values;
}
echo format_to_output( $temp_params['before'].implode( $temp_params['separator'], $userfield_values ).$temp_params['after'] );
}
else
{
debug_die( '$userfield_values is not an array!' );
}
break;
case 'User:email':
$temp_params = array_merge( array( // Here, we make sure not to modify $params
'format' => 'htmlbody',
), $params );
$rendered_User->email( $temp_params['format'] );
break;
case 'User:first_name':
$temp_params = array_merge( array( // Here, we make sure not to modify $params
'format' => 'htmlbody',
), $params );
$rendered_User->first_name( $temp_params['format'] );
break;
case 'User:fullname':
echo $rendered_User->get( 'fullname' );
break;
case 'User:id':
echo $rendered_User->ID;
break;
case 'User:last_name':
$temp_params = array_merge( array( // Here, we make sure not to modify $params
'format' => 'htmlbody',
), $params );
$rendered_User->last_name( $temp_params['format'] );
break;
case 'User:login':
$temp_params = array_merge( array( // Here, we make sure not to modify $params
'format' => 'htmlbody',
), $params );
echo $rendered_User->login( $temp_params['format'] );
break;
case 'User:nick_name':
$temp_params = array_merge( array( // Here, we make sure not to modify $params
'format' => 'htmlbody',
), $params );
$rendered_User->nick_name( $temp_params['format'] );
break;
case 'User:picture':
$temp_params = array_merge( array( // Here, we make sure not to modify $params
'size' => 'crop-top-64x64',
'class' => 'avatar',
'align' => '',
'zoomable' => false,
'avatar_overlay_text' => '',
'lightbox_group' => '',
'tag_size' => NULL,
'protocol' => '',
), $params );
echo $rendered_User->get_avatar_imgtag( $temp_params['size'], $temp_params['class'], $temp_params['align'], $temp_params['zoomable'],
$temp_params['avatar_overlay_text'], $temp_params['lightbox_group'], $temp_params['tag_size'], $temp_params['protocol'] );
break;
case 'User:preferred_name':
$temp_params = array_merge( array( // Here, we make sure not to modify $params
'format' => 'htmlbody',
), $params );
$rendered_User->preferred_name( $temp_params['format'] );
break;
// Others
default:
switch( $scope )
{
case 'echo':
// Print param var value, No need check this because all done above:
echo $params[ $param_name ];
break;
default:
// Unknown template var:
$match_found = false;
}
}
$r = ob_get_clean();
if( $match_found )
{
return $r;
}
else
{ // Display error for not recognized variable:
return get_rendering_error( '['.$var.'] is not recognized.', 'span' );
}
}
/**
* Validate Template code for uniqueness. This will add a numeric suffix if the specified template code is already in use.
*
* @param string Template code to validate
* @param integer ID of template
* @param string The name of the template code column
* @param string The name of the template ID column
* @param string The name of the template table to use
* @return string Unique template code
*/
function unique_template_code( $code, $ID = 0, $db_code_fieldname = 'tpl_code', $db_ID_fieldname = 'tpl_ID', $db_table = 'T_templates' )
{
global $DB, $Messages;
load_funcs( 'locales/_charset.funcs.php' );
// Convert code:
$code = strtolower( replace_special_chars( $code, NULL, false, '_' ) );
$base = preg_replace( '/_[0-9]+$/', '', $code );
// CHECK FOR UNIQUENESS:
// Find all occurrences of code-number in the DB:
$SQL = new SQL( 'Find all occurrences of template code "'.$base.'..."' );
$SQL->SELECT( $db_code_fieldname.', '.$db_ID_fieldname );
$SQL->FROM( $db_table );
$SQL->WHERE( $db_code_fieldname." REGEXP '^".$base."(_[0-9]+)?$'" );
$exact_match = false;
$highest_number = 0;
$use_existing_number = NULL;
foreach( $DB->get_results( $SQL->get(), ARRAY_A ) as $row )
{
$existing_code = $row[$db_code_fieldname];
if( ( $existing_code == $code ) && ( $row[$db_ID_fieldname] != $ID ) )
{ // Specified code already in use by another template, we'll have to change the number.
$exact_match = true;
}
if( preg_match( '/_([0-9]+)$/', $existing_code, $matches ) )
{ // This template code already has a number, we extract it:
$existing_number = (int)$matches[1];
if( ! isset( $use_existing_number ) && $row[$db_ID_fieldname] == $ID )
{ // if there is a numbered entry for the current ID, use this:
$use_existing_number = $existing_number;
}
if( $existing_number > $highest_number )
{ // This is the new high
$highest_number = $existing_number;
}
}
}
if( $exact_match )
{ // We got an exact (existing) match, we need to change the number:
$number = $use_existing_number ? $use_existing_number : ( $highest_number + 1 );
$code = $base.'_'.$number;
}
return $code;
}
/**
* Get list of context available to templates
*/
function get_template_contexts( $format = 'keys', $exclude = array() )
{
$template_contexts = array(
'custom1' => sprintf( T_('Custom %d'), 1 ),
'custom2' => sprintf( T_('Custom %d'), 2 ),
'custom3' => sprintf( T_('Custom %d'), 3 ),
'content_list_master' => T_('Content List Master'),
'content_list_item' => T_('Content List Item'),
'content_list_category' => T_('Content List Category'),
'content_block' => T_('Content Block'),
'item_details' => T_('Item Details'),
'item_content' => T_('Item Content'),
'registration_master' => T_('Registration Master'),
'registration' => T_('Registration'),
'search_form' => T_('Search Form'),
'search_result' => T_('Search Result')
);
if( !empty( $exclude ) )
{
$template_contexts = array_diff_key( $template_contexts, array_fill_keys( $exclude, NULL ) );
}
switch( $format )
{
case 'keys':
$template_contexts = array_keys( $template_contexts );
break;
case 'raw':
default:
// Do nothing
}
return $template_contexts;
}
?>