News:

Bored?  Looking to kill some time?  Want to chat with other SMF users?  Join us in IRC chat or Discord

Main Menu

loadPartialTemplate function Please?

Started by SoLoGHoST, November 08, 2015, 05:21:30 AM

Previous topic - Next topic

SoLoGHoST

Thing that has always bothered me in SMF, and is still bothering me in SMF 2.1.  You really need the ability to create partial templates, for functionality added to specific functions in SMF.  Integration Hooks can only do so much, and it's just not flexible enough.

The main problem is, SMF seems to control too much on this part.  The loadTemplate function is too damn strict and loads up entire HTML, than if you want to load a subtemplate, you are stuck with a function name inside of that template file.  This is the main problem here!

I want to add new functionality to SMF that will work in all Themes, but problem is, I have to code for entire theme files, for loadTemplate()

This should not be the case.  I should be able to integrate into a function called, loadPartialTemplate or something similiar, where it will grab only the file I specify to be loaded from the current theme, and into the part of the template automatically via Load.php (Source File).  However, in a source file, one can't simply do:

$context['my_partial_template'] = loadPartialTemplate('MyTemplate', 'MyFunction', $function_params_array);

Than you should be able to do something like this for the loadPartialTemplate function:
function loadPartialTemplate($template_name, $function, $parameters = array())
{
global $settings, $modSettings;

$contents = '';

if (!empty($template_name))
{
// Get the Theme Folder
if (!empty($settings['actual_theme_dir']) && $settings['actual_theme_dir'] != $settings['default_theme_dir'])
$theme_dir = $settings['actual_theme_dir'];
else
$theme_dir = $settings['default_theme_dir'];

$filename = $theme_dir . '/' . $template_name . '.partial.template.php';

if (file_exists($filename))
{
extract($GLOBALS);
ob_start();

include_once($filename);

if (!empty($function) && is_callable($function))
{
if (!empty($parameters) && is_array($parameters))
call_user_func_array($function, $parameters);
else
call_user_func($function);
}
$contents = ob_end_clean();
}
}
return $contents;
}


In the template file now, it would make sense to just echo out $context['my_partial_template']


In the Partial Template File, would look something like this in ./Themes/default/MyTemplate.partial.template.php


function MyFunction($arguments) {
    global $blah, $context, $txt, $modSettings;

    echo '<p>Hello World</p>';
}


Than $context['my_partial_template'] would be equal to <p>Hello World</p>

Could we please get something like this?  Because of the way you have SMF configured, it's impossible to do this within the Source file it seems, or maybe there's an error in my code somewhere.

In any case, I find myself fighting more and more with the SMF code, rather than working with it!  This is just a basic thought of possibly a greater functionality of Theming/Modding for SMF altogether.  Ofcourse, we'd want to handle this in a cleaner approach, but this is the basic concept that I think is important.

Kindred

maybe I am missing something, but I don't understand your use-case example...

however, if I understand what you are actually asking -- I don't think it is really possible without re-writing the entire SMF templating system
Слaва
Украинi

Please do not PM, IM or Email me with support questions.  You will get better and faster responses in the support boards.  Thank you.

"Loki is not evil, although he is certainly not a force for good. Loki is... complicated."

Suki

#2
function myFunction()
{
global $context;

loadTemplate('myTemplate');

$context['my_partial_template'] = template_myPartialTemplate($arguments);
}



function template_myPartialTemplate($arguments)
{

$return = 'hello world!';

return $return;
}


Real world example: 
https://github.com/MissAllSunday/ActivityBar/blob/master/Sources/ActivityBar.php#L91
https://github.com/MissAllSunday/ActivityBar/blob/master/Themes/default/ActivityBar.template.php#L29

There are a couple of procedural mods out there that also uses returned values from a template function. Actually, all HTML should be stored in template/views functions, it helps keeping logic completely separated from the presentation.


I'm sorry but not really knowing how to handle functions and their return values doesn't really count towards a bug, flaw, feature request or otherwise a limitation within SMF.

Edit, typos.
Disclaimer: unless otherwise stated, all my posts are personal and does not represent any views or opinions held by Simple Machines.

Kindred

Right, so I am incorrect and it is actually very simple to do...  and ^^^  would be why I am not a developer. :)
Слaва
Украинi

Please do not PM, IM or Email me with support questions.  You will get better and faster responses in the support boards.  Thank you.

"Loki is not evil, although he is certainly not a force for good. Loki is... complicated."

SoLoGHoST

#4
Quote from: Suki on November 08, 2015, 11:12:01 AM
I'm sorry but not really knowing how to handle functions and their return values doesn't really count towards a bug, flaw, feature request or otherwise a limitation within SMF.

Seriously?

My problem is that, for each additional theme that gets added, the function needs to be added to that template file in that theme in order for the mod to work.  My Feature Request is that we make it something that is related to the Customization (not the actual theme), but loads, kinda like hooks do for Source files, but, instead for themes.

The dreaded task of making your mod work in all themes, is not something that the Mod author should be responsible for, by adding template files to that theme.  Excluding the functionality of a Customization to SMF, simply because the template file is in that theme, but the function isn't, is not acceptable either.  It might make sense to separate the templating of Modifications from Themes altogether.

I can not simply loadTheme('MyTemplate') within a theme template that is already loaded.  I am only able to load a function within that template file that is already loaded, that does not exist within that custom theme.  This is the problem!

I will give you an example of this.

In wordpress, you can create plugins.  These plugins are not related to the Theme.  They have their own file that loads separate from the Themes functions.php file.  They have their own Backend Administration section that, also, loads separate from the theme.  There are filters, actions, meta, etc. that can be used to hook in whatever functionality that the plugin offers (kinda like SMF integration hooks, cept much more flexible), along with any templates/HTML that can be used within those filters, actions, etc..

Than 1 can simple call:

do_action('YourActionName');


And all the magic happens.  You can apply actions on top of already existing actions also.

What I am suggesting is nothing new, it has been done many times before, and allows much more flexibility and control (that is needed) than the integration hooks in SMF.

Sorry, my code example was not a good example of what I'm actually trying to get across in this topic.  I hope that it is clearer now?

SoLoGHoST

perhaps the title of this topic should be renamed to:  add_integration_template instead.  Which I believe would fulfill this feature request, if Theme templates were created with these functions in theme, starting with the default theme in SMF.

SoLoGHoST

#6
Quote from: Suki on November 08, 2015, 11:12:01 AM
Actually, all HTML should be stored in template/views functions, it helps keeping logic completely separated from the presentation.

I am very sure that I could present you with many Source files and functions in SMF that echo html directly within the source file itself.  I am not wanting to get into the reasons why SMF choose to do this.  Please do not reply back with a justifiable reason for this.

Kindred

You do realize that you do not have to add template files to every theme?   Add them to the default theme and every other theme will automatically use them
Слaва
Украинi

Please do not PM, IM or Email me with support questions.  You will get better and faster responses in the support boards.  Thank you.

"Loki is not evil, although he is certainly not a force for good. Loki is... complicated."

SoLoGHoST

Yes, I'm well aware of this Kindred.  However, if the Custom Theme has that template file in it, but not that function, the Mod will not work in SMF, for that theme.  This is the problem.

Not to mention the template function insertion point of another function.

Storing the variable $context['mytemplatefunction'] = call_other_function_inside_template($args);

Still leaves you with the needed echo of $context['mytemplatefunction'] somewhere within the template file itself.

Also, if a template file is already loaded, for example:  loadTemplate('Display');

You can't load another template file, so it's not possible!  I would need to load a function from a template file within an integration function that is called from Display.php, after loadTemplate('Display') has been called.  It will give error, because you can not load 2 different template files from within the same function that is loading 1 already, prior to the call to the integration hook.

Kindred

True...   That is why we encourage the use of hooks...

But also, 2.0 and 2.1 both attempt to install mod changes into all custom themes at the time of. Do installtion, so, if the theme has a template I'm it, 2.0 and 2.1 will add your new function into that template...    But there are sufficient existing hooks, especially in 2.1 that your suggestion should not Be necessary.
Слaва
Украинi

Please do not PM, IM or Email me with support questions.  You will get better and faster responses in the support boards.  Thank you.

"Loki is not evil, although he is certainly not a force for good. Loki is... complicated."

Bloc

Not that many themes ships with copies of different mod's templates - for the most part they reside only in the default theme.

But yes, its a problem as such - but more for theme authors that want to modify those templates. The solution is usually: don't.

SoLoGHoST

So, here's my situation.

I need to integrate a function from a hook that adds values to variables, that gets loaded in a template, and need to grab all global variables from that template file after everything has been set in the source file function, without editing the template file itself... in order to output html for a modification.

Is this possible with SMF?  No, not currently that I can see.

Is it possible with other Website solutions?  Yes, Umbraco, Wordpress, and others....

Suki

SoLoGHoST, I'm pretty sure whatever "problem" you have with using the SMF template system can be easily solved, perhaps instead of always having this "confrontational" attitude you could simple ask nicely, someone will reply, you will complete your mod already and everyone will be happily ever after...


So perhaps, and just perhaps, instead of passive-aggressive attacking and glorifying other (equally crappy template engine) why don't you just cut to the chase, tell us exactly what you want to achieve and be done with it?


Quote from: SoLoGHoST on November 08, 2015, 04:40:41 PM
So, here's my situation.

I need to integrate a function from a hook that gets loaded in a template, and grabs all global variables from that template file, without editing the template file itself.


That doesn't add much, need real code, real working code to fully understand what you want.

Every template in SMF gets called by a source file so chances are there is a hook in 2.1 that will do what you want  and I need to reiterate, template files aren't the best place for code logic and there should be a better way to handle this but of course you need to fully explain what you want to do.
Disclaimer: unless otherwise stated, all my posts are personal and does not represent any views or opinions held by Simple Machines.

SoLoGHoST

I edited the post to explain it better.  Hopefully, it explains what I am trying to do.  I wonder if integrate_pre_include integration function would help here?

Suki

No, like I said, need real code to work with.  I can't give you a generic example because it simply won't be what you need

Don't explain the logic of it or how you think it should be done, post whatever code you have and explain what your mod is suppose to do.
Disclaimer: unless otherwise stated, all my posts are personal and does not represent any views or opinions held by Simple Machines.

SoLoGHoST

For example, in Display.php

call_integration_hook('integrate_prepare_display_context', array(&$output, &$message));


I would like to load a template file to be echo'd out within this hook, but in a certain spot within template_single_post() function.  Is this possible?

Suki

Seriously, can you please post the code you are working with, please.

Try and avoid posting what you think it should be done or how it should be done, just post whatever code you have, thats it.
Disclaimer: unless otherwise stated, all my posts are personal and does not represent any views or opinions held by Simple Machines.

SoLoGHoST

Ok, give me a few to separate all of the unneccessay stuff in code.  And thanks

SoLoGHoST

#18
Ok, well, I am a moron!
After some digging now, am able to do this using ob_get_contents() argg, not ob_end_clean();
Anyways, still left with the variable injection into the template file.  Sorry for all of this.

I'm still faced with the issue of editing the template file however.  I will post up code BTW.

SoLoGHoST

#19
Here is the code that hooks into the prepareDisplayContext integration_function:

function prpro_integrate_prepare_display_context(&$output, &$message)
{
global $topic, $context, $options, $user_info, $settings, $txt, $scripturl, $boardurl, $modSettings, $ratings, $ratings_enabled;

$output = array_merge(array(
'rating' => loadRatingsInfo($message['id_msg'], !empty($message['ratings_enabled']) ? $message['ratings_enabled'] : 0, !empty($message['id_last_rating']) ? $message['id_last_rating'] : 0, $message['id_member'], !empty($context['topicinfo']['is_ratings']) ? $context['topicinfo']['is_ratings'] : 0),
'reached_ratings_limit' => !empty($modSettings['post_ratings_limit_count']) && (intval($message['total_ratings']) >= intval($modSettings['post_ratings_limit_count'])),
'can_postratings_rate' => allowedTo('postratings_rate') && !empty($message['ratings_enabled']) && (empty($modSettings['post_ratings_own_post_rating']) ? $user_info['id'] != $message['id_member'] : true),
'has_ratings' => !empty($message['total_ratings']),
'topic_id' => $topic,
'not_your_post' => empty($modSettings['post_ratings_own_post_rating']) ? $user_info['id'] != $message['id_member'] : true,
'can_enable_disable_postratings' => allowedTo('ratings_enable_post_any') || (allowedTo('ratings_enable_post_own') && $user_info['id'] == $message['id_member']),
'ratings_enabled' => !empty($message['ratings_enabled']),
'first_enabled' => (empty($modSettings['post_ratings_type']) && empty($modSettings['post_ratings_first_post'])) && $message['id_msg'] == $context['topicinfo']['id_first_msg'] ? false : true,
'topic_enabled' => $ratings_enabled && !empty($context['topicinfo']['is_ratings']),
'post_rating_stars' => GetPostRating('stars', $message['id_msg'], !empty($message['total_ratings']) ? $message['total_ratings'] : 0, !empty($message['rating']) ? $message['rating'] : 0),
'post_rating_num' => GetPostRating('text', $message['id_msg'], !empty($message['total_ratings']) ? $message['total_ratings'] : 0, !empty($message['rating']) ? $message['rating'] : 0),
'post_rating_totals' => !empty($message['total_ratings']) ? (int) $message['total_ratings'] : 0
), $output);

include_once($settings['default_theme_dir'] . '/PostRatingsPartials.template.php');

ob_start();
template_postratings_message_header_style($output);
$output['post_ratings_header_style'][$message['id_msg']] = ob_get_contents();
ob_end_clean();
}


Now in ./Themes/default/PostRatingsPartials.template.php I have this:


// Post Ratings Header Style Template Function
function template_postratings_message_header_style($message)
{
global $context, $settings, $options, $txt, $scripturl, $modSettings, $boardurl, $user_info;

$view_ratings = allowedTo('postratings_view_user');

if (!empty($modSettings['post_ratings_layout_style']))
{
// Header - is it enabled or not??
if ($message['ratings_enabled'] && $message['topic_enabled'] && $message['first_enabled'] && allowedTo('postratings_view'))
{
echo '
<div class="title_bar">
<h3 class="titlebg" style="font-weight: normal;">';

$view_ratings =  $view_ratings && !empty($message['ratings_enabled']) && $message['topic_enabled'];

if ($message['has_ratings'])
{
if (!empty($message['post_rating_totals']))
{
if (!empty($modSettings['post_ratings_show_quantity']))
echo '
<div class="floatright smalltext">', ($view_ratings ? '<a href="' . $scripturl . '?action=postratings;sa=view;board=' . $context['current_board'] . ';topic=' . $context['current_topic'] . ';msg=' . $message['id'] . ';' . $context['session_var'] . '=' . $context['session_id'] . '" onclick="return reqWin(this.href);">' : ''), $txt['postratings_count1'], ' <strong>', $message['post_rating_totals'], '</strong> ', ($message['post_rating_totals'] < 2 ? $txt['postratings_count2'] : $txt['postratings_count3']), ($view_ratings ? '</a>' : ''), '</div>';
else
if ($view_ratings)
echo '
<div class="floatright smalltext"><a href="', $scripturl, '?action=postratings;sa=view;board=', $context['current_board'], ';topic=', $context['current_topic'], ';msg=', $message['id'], ';', $context['session_var'], '=', $context['session_id'], '" onclick="return reqWin(this.href);">', $txt['post_ratings_view_ratings'], '</a></div>';
}

$textOut = 'post_ratings_text' . $message['post_rating_num'];

echo $message['post_rating_stars'] . '<table cellspacing="0" cellpadding="0" border="0" class="floatleft"><tr><td align="left" valign="middle">' . parse_bbc(stripslashes($modSettings[$textOut])) . '</td></tr></table>';
}
else
echo parse_bbc(stripslashes($modSettings['post_ratings_not_rated']));

echo '
</h3></div>';
}
}
}


And now in Display.template.php, all that is needed, is this, within the template_single_post function:


echo $message['post_ratings_header_style'][$message['id']];


Which greatly reduces the code inside the template and handles it inside my own template file PostRatingsPartials.template.php

The problem still exists that I need to add to the Display.template.php file in order for it to show, however.  If you know of a better way to do this without editing the Display.template.php file, that would be most appreciated.  If this is not possible any other, cleaner way, than I would be leaning towards a feature request for the ability to do this somehow (for mod developers).

marg edit: fixed minor issue with code tags

Advertisement: