News:

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

Main Menu

Display a div without editing the index.template.php

Started by Xarcell, May 22, 2010, 10:48:58 PM

Previous topic - Next topic

Xarcell

Sorry for posting so quickly, but could it also be posted this way?


function template_simplenav_main()
{
global $scripturl, $context;

$snlogged = '<li class="spacing slast"><a href="', $scripturl, '?action=logout;sesc=', $context['session_id'],'"><b>Logout</b></a></li>';
$snguest = '<li class="spacing slast"><a href="', $scripturl, '?action=logout;sesc=', $context['session_id'],'"><b>Login</b></a></li>';

if ($context['user']['is_logged'])
{
    return $snlogged;
     else
          return $snguest;
}

}

Orstio

Quote from: Xarcell on May 24, 2010, 07:44:19 PM
Quote from: Allusion on May 24, 2010, 07:26:24 PM
Quote from: Xarcell on May 24, 2010, 07:24:25 PM
I tried require once and got this error: Fatal error: require_once() [function.require]: Failed opening required '/Themes/default/SimpleNav.template.php' (include_path='.:/usr/local/php5/lib/php:/usr/local/lib/php') in /home/xxxxxx/xxxxxx.com/Sources/Load.php on line 1787

Well, is there a file named SimpleNav.template.php in the Themes/default/ directory of your forum?

Yep, I copy & pasted the file name into the snippet to ensure no misspelling. I also checked the directory to make sure it was there.

You need to global $boarddir before using it in the include/require statement.

Allusion

You're getting there. :)

Functions in PHP can only return one value. When you return a value from a function, execution exits the function immediately and any code in the function after the return doesn't get executed at all.

The second code is almost correct. else blocks in PHP need their own brace pairs, just like, and on the same level as, the if ones. if and else blocks don't need brace pairs if they contain only one statement (but it doesn't hurt to always use them, especially during development).

Also, you can mix HTML and text with PHP using , (commas) when echo-ing them, but for variable assignments, direct returns etc. you need to concatenate them with . (dots).

And finally, I used the correct href for the login page.

Try this:

function template_simplenav_main()
{
global $scripturl, $context;

if ($context['user']['is_logged'])
{
$snlogged = '
<li class="spacing slast"><a href="' . $scripturl . '?action=logout;sesc=' . $context['session_id'] . '"><b>Logout</b></a></li>';

return $snlogged;
}
else
{
$snguest = '
<li class="spacing slast"><a href="' . $scripturl . '?action=login"><b>Login</b></a></li>';

return $snguest;
}
}


Quote from: Orstio on May 24, 2010, 08:31:23 PM
You need to global $boarddir before using it in the include/require statement.

Good catch, Orstio.

Xarcell

#23
Ok, so I follow you so far. I'm still running into bumps in the road trying to code my template with using echo statements. An example of what I'm running into now is the ssi that I'm using in one of the tabs.

ex:
<li class="spacing"><a href="#url"><b>Top Boards</b></a>
<div class="holder">
<table width="100%" height="100%"><tr>
<td>
<dl>
<dt>Top Boards</dt>
<dd>'; ssi_topBoards(); echo '</dd>
</dl>
</td>
</tr></table>
</div>
</li>


How do I get around using ssi function with the echo?

Allusion

You can't use both SSI and SMF at the same time. I would:

1. copy the ssi_topBoards() function;
2. paste it into a new file (with <?php at the top and ?> at the bottom);
3. rename the function just in case;
4. save the file with a .php extension;
5. upload it to your SMF installation;
6. use require_once to include it, either just before including the template file or from inside the template file, at the start of the code (but after the global statements) in the template function that calls your custom "top boards" function.

If you have uploaded your custom file to the base SMF directory, you can use:

require_once($boarddir . '/your_file.php');


If it's in the Sources/ directory, you can include the file with:

require_once($sourcedir . '/your_file.php');


Again, you need to global $boarddir or $sourcedir before using it in an include/require statement.

Then you can call the function from your template file.

Yağız...

Quote from: Allusion on May 25, 2010, 05:33:47 PM
You can't use both SSI and SMF at the same time.
Who said that you can't?
global $boarddir;
require_once(
$boarddir '/SSI.php');
ssi_topBoards();

Xarcell

Quote from: Yağız... on May 25, 2010, 05:37:38 PM
Quote from: Allusion on May 25, 2010, 05:33:47 PM
You can't use both SSI and SMF at the same time.
Who said that you can't?
global $boarddir;
require_once(
$boarddir '/SSI.php');
ssi_topBoards();


Yes, that's how it's done, according to the manual here at this site.

My question is, how do I place it in the HTML without echoing anything.

echo '<dd>'; ssi_topBoards(); echo '</dd>';

Allusion

As with many SSI functions, you can specify an $output_method different from the default 'echo', for example 'array', when calling the function. Here's the function for ssi_topBoards in SMF 1.1.11's SSI.php:


function ssi_topBoards($num_top = 10, $output_method = 'echo')
{
<snip>

$boards = array();

<snip>

// If we shouldn't output or have nothing to output, just jump out.
if ($output_method != 'echo' || empty($boards))
return $boards;

<snip>
}

where <snip> indicates code that I left out for clarity.

This:

$top_boards = ssi_topBoards(10, 'array');

will get an array containing information about the top 10 boards from the function and assign it to $top_boards. You can then do something like:


$top_boards_html = '';   // Two single quotes, not a double quote.
foreach ($top_boards as $board)
{
$top_boards_html .= '
<tr>
<td>', $board['link'], $board['new'] ? ' <a href="' . $board['href'] . '"><img src="' . $settings['images_url'] . '/' . $context['user']['language'] . '/new.gif" alt="' . $txt[302] . '" border="0" /></a>' : '', '</td>
<td align="right">', $board['num_topics'], '</td>
<td align="right">', $board['num_posts'], '</td>
</tr>';
}

$result = '
<snip>

<dd>' . $top_boards_html . '</dd>

<snip>';


and then you can return the final $result as your custom function's return value which you then use in index.template.php or in your custom template.

Here again, <snip> means any other HTML you want.

Orstio

#28
Quote from: Yağız... on May 25, 2010, 05:37:38 PM
Quote from: Allusion on May 25, 2010, 05:33:47 PM
You can't use both SSI and SMF at the same time.
Who said that you can't?
global $boarddir;
require_once(
$boarddir '/SSI.php');
ssi_topBoards();


Have you tried this on a live forum?  Allusion was correct in suggesting to copy the function to a new file and including that file rather than using SSI.php.  You can't.  I said. :P

Xarcell

Oh, I thought you was saying it could. I thought it said in the manual that you could. I guess I was reading it wrong.

Alright, after seeing where this going, I don't think it's the best route to go. The best thing about my navbar is that it would be easy for someone to add custom tabs. Without using the echo, the task becomes too complicated.

I've tried to include the SimpleNav.template.php in the index.template.php, but that didn't work.

Any other ideas?

Yağız...

Quote from: Orstio on May 25, 2010, 11:07:22 PM
Quote from: Yağız... on May 25, 2010, 05:37:38 PM
Quote from: Allusion on May 25, 2010, 05:33:47 PM
You can't use both SSI and SMF at the same time.
Who said that you can't?
global $boarddir;
require_once(
$boarddir '/SSI.php');
ssi_topBoards();


Have you tried this on a live forum?  Allusion was correct in suggesting to copy the function to a new file and including that file rather than using SSI.php.  You can't.  I said. :P
Sure I did :) I always do that on my forums and I didn't have any problems with it.

Allusion

#31
Quote from: Xarcell on May 26, 2010, 03:31:35 AM
Alright, after seeing where this going, I don't think it's the best route to go. The best thing about my navbar is that it would be easy for someone to add custom tabs. Without using the echo, the task becomes too complicated.

Well, the way I outlined it is as far as it would have to go. What exactly do you find too complicated?

Have a look at the actual ssi_topBoards() function in SSI.php. If you copy/paste a renamed copy of that function in your own PHP file and include that file instead, the only extra step would be either to 1) use 'array' for the $output_method parameter and browse the result using foreach, as I outlined, or 2) modify the function code to output the result exactly the way you want, again as a return value rather than using echo.

Using your own copy of the function and your own PHP file has the advantage that you can modify them later without touching SSI.php itself.

[SiNaN]

Quote from: Yağız... on May 26, 2010, 04:00:39 AM
Quote from: Orstio on May 25, 2010, 11:07:22 PM
Quote from: Yağız... on May 25, 2010, 05:37:38 PM
Quote from: Allusion on May 25, 2010, 05:33:47 PM
You can't use both SSI and SMF at the same time.
Who said that you can't?
global $boarddir;
require_once(
$boarddir '/SSI.php');
ssi_topBoards();


Have you tried this on a live forum?  Allusion was correct in suggesting to copy the function to a new file and including that file rather than using SSI.php.  You can't.  I said. :P
Sure I did :) I always do that on my forums and I didn't have any problems with it.

It should be fine to include SSI.php in SMF. SSI.php makes sure not to load stuff again if SMF is already loaded. Then again, it may not be a very good idea to load 2000+ lines code just for a single function.
Former SMF Core Developer | My Mods | SimplePortal

Xarcell

#33
Quote from: Allusion on May 26, 2010, 04:16:50 AM
Quote from: Xarcell on May 26, 2010, 03:31:35 AM
Alright, after seeing where this going, I don't think it's the best route to go. The best thing about my navbar is that it would be easy for someone to add custom tabs. Without using the echo, the task becomes too complicated.

Well, the way I outlined it is as far as it would have to go. What exactly do you find too complicated?

Have a look at the actual ssi_topBoards() function in SSI.php. If you copy/paste a renamed copy of that function in your own PHP file and include that file instead, the only extra step would be either to 1) use 'array' for the $output_method parameter and browse the result using foreach, as I outlined, or 2) modify the function code to output the result exactly the way you want, again as a return value rather than using echo.

Using your own copy of the function and your own PHP file has the advantage that you can modify them later without touching SSI.php itself.

I need to give that more thought so that I can fully understand what your saying. I think I understand, but I won't really know until I try.

What I mean by too complicated, is adding things in and making adjustments to the code. For example, before i was asking how I would get the login/logout tabs to show based on if the user is already logged in or not. What i didn't mention was with the login tab, if you mouseover a pop-up shows with the login section. The code itself has more echos being used and it give sme a headache trying to figure out how I would code it without echos. Example:

if ($context['user']['is_logged'])
{
$snlogged = '
<li class="spacing slast"><a href="' . $scripturl . '?action=logout;sesc=' . $context['session_id'] . '"><b>Logout</b></a></li>';

return $snlogged;
}
else
{
$snguest = '
<li class="spacing"><a href="#url"><b>Login</b></a>
<div class="holder">
<table width="100%" height="100%"><tr>
<td>
<dl>
<dt>Login</dt>
<dd>       
               <script type="text/javascript" src="', $settings['default_theme_url'], '/scripts/sha1.js"></script>
<form id="guest_form" action="', $scripturl, '?action=login2" method="post" accept-charset="', $context['character_set'], '" ', empty($context['disable_login_hashing']) ? ' onsubmit="hashLoginPassword(this, \'' . $context['session_id'] . '\');"' : '', '>
<div class="info">', $txt['login_or_register'], '</div>
<input type="text" name="user" size="10" class="input_text" />
<input type="password" name="passwrd" size="10" class="input_password" />
<select name="cookielength">
<option value="60">', $txt['one_hour'], '</option>
<option value="1440">', $txt['one_day'], '</option>
<option value="10080">', $txt['one_week'], '</option>
<option value="43200">', $txt['one_month'], '</option>
<option value="-1" selected="selected">', $txt['forever'], '</option>
</select>
<input type="submit" value="', $txt['login'], '" class="button_submit" /><br /> <div class="info"> $txt['quick_login_dec'], '</div>


if (!empty($modSettings['enableOpenID']))
echo '
<br /><input type="text" name="openid_identifier" id="openid_url" size="25" class="input_text openid_login" />';

echo '
<input type="hidden" name="hash_passwrd" value="" />
</form>';

                                 echo '</dd>
</dl>
</td>
</tr></table>
</div>
</li>


It would just seem weird to make:

echo '
<input type="hidden" name="hash_passwrd" value="" />
</form>';


Into:
$blah = '
<input type="hidden" name="hash_passwrd" value="" />
</form>';
                                 return $blah;


That isn't correct is it?

So I can't help but wonder if it's going to be this complicated every time I or someone else wants to add a new tab with code in it. I guess it wouldn't be so bad if I wasn't such a noob, but I am. I'm just not confident is all...

Then again, you've helped me understand more with PHP than my "PHP for Dummies"  :P

So I'm still eager to try I reckon.


Allusion

If you're more comfortable with echo-ing stuff directly, perhaps you wouldn't mind calling the function from index.template.php of each theme directly? This would mean adding the function call to the index.template.php file of each theme, but the result doesn't seem to be much different otherwise.

I'll have to read the whole topic again in order to see what you want to do and how you want to do it. There's usually more than one way to skin a cat, and SMF is no different.

[SiNaN]

If your div is going to be after the content, you can use template layers. See how I have done it with my SimpleAds mod.
Former SMF Core Developer | My Mods | SimplePortal

Orstio

#36
Quote from: Yağız... on May 26, 2010, 04:00:39 AM
Quote from: Orstio on May 25, 2010, 11:07:22 PM
Quote from: Yağız... on May 25, 2010, 05:37:38 PM
Quote from: Allusion on May 25, 2010, 05:33:47 PM
You can't use both SSI and SMF at the same time.
Who said that you can't?
global $boarddir;
require_once(
$boarddir '/SSI.php');
ssi_topBoards();


Have you tried this on a live forum?  Allusion was correct in suggesting to copy the function to a new file and including that file rather than using SSI.php.  You can't.  I said. :P
Sure I did :) I always do that on my forums and I didn't have any problems with it.

I have never seen it work on a live site.  I have seen it work on a local installation of LAMP on Windows, but never live on an actual web page.

If you look at the code of SSI.php, you'll see that it should actually never work, and there's probably something wrong with your PHP configuration if it does.  It was written this way so that it can never run into an endless loop.  If this now works for some reason, it should be reported as a bug.

[SiNaN]

Former SMF Core Developer | My Mods | SimplePortal

Norv

Orstio, what do you mean?
SSI functions can be used from inside SMF (even though there are opinions discouraging this, since it was meant to offer an API to be used rather by external code). The only thing that it's not run, when included from inside SMF, is the initialization code - the code outside functions, which indeed is not needed since SMF already did all it's supposed to do. But calling functions from the file works just fine.
Or is there something else you mean?
To-do lists are for deferral. The more things you write down the later they're done... until you have 100s of lists of things you don't do.

File a security report | Developers' Blog | Bug Tracker


Also known as Norv on D* | Norv N. on G+ | Norv on Github

bloc

Quote from: [SiNaN] on May 26, 2010, 09:10:03 AM
Why would it run into an endless loop?
lol, I am curious as to why too..as TinyPortal loads in SSI.php quite effortless on SMF 2.0 RC3. :) It uses it for the SSI function blocktype.

And agreed with Sinan, using layers would be best here, but I did not suggest it because its bit more involved. then again..loading in ALL SSI, seems a bit much as you only will use one function. Better then to actually copy the function into a template file, add the layer in Load.php and let the copied function do its normal "echo" part + any other stuff you want. Adding it to that context value - which really is meant for static content that never change and across themes - seems a bit off.

Advertisement: