Simple Machines Website-Forum Integration

April 09, 2007, 06:51:32 PM Posted by Thantos on April 09, 2007, 06:51:32 PM in Simple Machines Website-Forum Integration | 41 Comments
We get asked quite a bit about which CMS we use here at Simple Machines.  The answer is that we don't!  We use the SSI.php file that is included with SMF.  However we wrap SSI.php in another file called integrate.php in order to simply the entire process.

The goals when setting up the integration was:

  • Make full use of SMF's layer and template system.
  • Consolidate redundant code into a central file.
  • Make each file easy to create and update.
  • Allow full flexibility while doing the above.
Each file is broken up into 4 main parts

  • Setup variables
  • Bringing in integrate.php
  • A source function
  • A template function
The integrate.php file can handle many variables — the current version has 10 —  but most pages use two main variables.  These variables mainly set the default values so it doesn't need to override them later.

Bringing in integrate.php is simply a matter of using a require_once() with the path to the file.

The source function can do anything a normal SMF source function can do.  So it may query the database to get some data, do some calculations, redirect to another page, whatever is needed.  Just like in SMF it is important to keep your source type of actions — collecting and organizing data, doing calculations, doing massive queries, etc — from your display.  However not every file actually needs a source function, for example our About page just outputs text, so a setup variable was setup in order to turn that off.

The template function is what actually displays whatever it is we want to display.  It is called just like a SMF template function is called.

integrate.php
The integrate.php file is where the majority of the complex code is located, even then its not that complex.  So let me break it down for you.

<?php
global $siteurl;
$siteurl 'http://www.simplemachines.org';
$context['siteurl'] = $siteurl;

Here we just want to setup a variable that stores where our website is located.  Useful for when you need to output a URL.


if (basename($_SERVER['PHP_SELF']) == 'integrate.php')
{
header('Location: ' . $siteurl);
die;
}

The integrate.php file doesn't actually display anything useful if you navigate to it.  In fact it would cause some errors since the source and template functions aren't defined.  As such we just want to redirect people away from the file.


$ssi_theme = 10;
$context['outside_forum'] = true;
$ssi_maintenance_off = true;
require('ABSOLUTE PATH/community/SSI.php');

Here we setup a few variables for SSI.php itself.  The ssi_theme variable sets the actual theme to use while the $ssi_maintenance_off means that even if the forum is in maintenance mode the site will still work.  The $context['outside_forum'] is used by the templates that serve both the website and the forum in order to change output depending on location.


if (!empty($redirect))
redirectexit(str_replace('{SITEURL}', $siteurl, $redirect));

We have a couple of files that we keep around for legacy purposes, but that are covered in other files.  So we just redirect the user to those files.


// Is this page restricted?
if (!empty($pagePermissions))
isAllowedTo($pagePermissions);

This allows use to restrict access to a particular page by permission.  I don't think I've used it yet, but it's nice to know the functionality is there if I want to use it.


if (!empty($pageIsIndex) && empty($user_info[$pageIsIndex]))
redirectexit($siteurl);

We have some pages that are for the team only and this provides an easy way to limit access to those pages.


// Ok we are outside of the forum so load up some more stuff.
loadTemplate('SiteTools');

There are some functions that we only need when outside of the forum, so we put them into their own template file and load it when we need to.


$callback = isset($callback) && $callback === false ? false : (!empty($callback) ? $callback : 'file_source');

This sets the name of the source function  The first thing it checks for is if the variable was set to false, if that is true that means the file doesn't need a source function.  Otherwise it looks to see if the callback function name was given and if so uses that, if not it uses the default name, which most files use.


$context['sub_template'] = !empty($template) ? $template : 'file_template';

Just like the source function except in this case there is no option to not set a template function.


if (!empty($section))
$context['section'] = $section;

$context['section'] sets the active part of the site wide menu.  If no value is specified the menu function itself sets a default.


if (!empty($menulink))
$context['menulink'] = $menulink;

On pages with a side menu, this sets the active menu item.  If none is set then it doesn't select an active link.


if (!empty($sectionheader))
$context['sectionheader'] = $sectionheader;

The section header is the text that is above the menu bar and below the user bar.


$pagetxtIndex = isset($pagetxtIndex) ? $pagetxtIndex : (!empty($menulink) ? $menulink : '');

One of our goals is to have our entire site using a language file which might one day be translated.  So this provides a way of selecting the set of strings for this particular page.  Normally the menulink is enough, but this provides a way to override it (for example pages that share the same menu link).


if (!empty($section) && !empty($pagetxtIndex) && isset($sitetxt[$section][$pagetxtIndex]))
{
$pagetxt = $sitetxt[$section][$pagetxtIndex];
}

Our text strings are stored in a multiple dimension array.  In order to make using them easier we map $pagetxt to a particular $sitetxt sub array.  But we only do this if the needed information is provided.


$context['page_title'] = !empty($title) ? $title : (!empty($pagetxt) && !empty($pagetxt['title']) ? $pagetxt['title'] : 'Simple Machines LLC');

This simply sets the page title.  This actually allows two easy ways of setting the page title:  give $title a value or have a title index in the pagetxt variable.  The "Simple Machines LLC" is just there as a backup, so we'll always have a page title.


if (empty($noSideBar))
$context['template_layers'][] = 'menubar';

This allows us to not include the menu bar — like the home page.  The menu bar itself is just another layer that is included.  This makes the page itself really clean and also helps ensure consistency.


if ($callback !== false)
call_user_func($callback);

Unless we already specified we don't have a source function we call it here and get to the good stuff.


obExit();
?>

obExit is responsible for calling the templates in the correct order and it also serves as an ending point to the script.  Also obExit provides a some functionality that is important to do in SMF 2.0.

Some examples
Ok now that I've hit you with the hard stuff lets take a look at two pages that use it.  The first is index.php for our home page.

<?php

$noSideBar 
true;
$section 'index';
$pagetxtIndex 'home';

This is all of our setup variables.  We turn off the side bar, set the section and pagetxt index.


require_once('integrate.php');

This starts the whole process.


function file_source()
{
global $context, $db_prefix, $smfFunc;

$request = $smfFunc['db_query']('', "
SELECT
m.smileys_enabled, m.poster_time, m.id_msg, m.subject, m.body, t.id_topic, t.id_board,
b.name AS bname, t.num_replies, m.id_member, mem.real_name AS poster_name
FROM {$db_prefix}topics AS t, {$db_prefix}messages AS m, {$db_prefix}members AS mem, {$db_prefix}boards AS b
WHERE t.id_board = 1
AND t.is_sticky = 1
AND b.id_board = 1
AND m.id_msg = t.id_first_msg
AND mem.id_member = m.id_member
ORDER BY t.id_topic DESC
LIMIT 4", __FILE__, __LINE__);

while ($row = $smfFunc['db_fetch_assoc']($request))
{
$bodylen = 200;
// Limit the length of the message, if the option is set.
if (strlen(str_replace('<br />', "\n", $row['body'])) > $bodylen)
$row['body'] = htmlspecialchars(substr(str_replace('<br />', "\n", un_htmlspecialchars($row['body'])), 0, $bodylen-3) . '...', ENT_QUOTES);

$row['body'] = parse_bbc($row['body'], $row['smileys_enabled']);

censorText($row['body']);
censorText($row['subject']);

$context['smfinfo'][] = array(
'title' => $row['subject'],
'link' => $scripturl . '?topic=' . $row['id_topic'] . '.0',
'description' => $row['body'],
'author' => !empty($row['id_member']) ? $scripturl . '?action=profile;u=' . $row['id_member'] : '',
'category' => $row['bname'],
'comments' => $scripturl . '?action=post;topic=' . $row['id_topic'] . '.0',
'pubDate' => gmdate('D, d M Y H:i:s T', $row['poster_time']),
'guid' => $row['id_msg']
);
}

$smfFunc['db_free_result']($request);


if (!$user_info['is_team'] && !$user_info['is_charter'])
{
$context['welcome_title'] = $pagetxt['welcome']['public']['title'];
$context['welcome_text'] = $pagetxt['welcome']['public']['text'];
}
elseif ($user_info['is_team'])
{
$context['welcome_title'] = $pagetxt['welcome']['team']['title'];
$context['welcome_text'] = $pagetxt['welcome']['team']['text'];
}
elseif ($user_info['is_charter'])
{
$context['welcome_title'] = $pagetxt['welcome']['charter']['title'];
$context['welcome_text'] = $pagetxt['welcome']['charter']['text'];
}


// the main header
$context['sectionheader'] = '<img src="' . $context['siteurl'] . '/site_images/header24.png" />';
}

This is the source function.  Get gets the last 4 topics from the News board that are stickied and gives a short preview of them.  The next set of code is simply setting up some text depending on which of the three main groups we are targeting (team, charter members, and regular members).


function template_file_template()
{
global $context, $siteurl, $sitetxt, $txt, $pagetxt;

echo '
<div id="secondarybody" style="margin-left: 0;">
<div id="quicknav">
<a href="/download/" title="', $pagetxt['download_title'], '"><img src="site_images/download.png" style="margin-top: 0;" alt="', $pagetxt['download_title'], '" /><br />', $pagetxt['download'], '</a><br />
<a href="http://custom.simplemachines.org/mods" title="', $pagetxt['custom_title'], '"><img src="site_images/custom.png" alt="', $pagetxt['download_title'], '" /><br />', $pagetxt['custom'], '</a><br />
<a href="/about/features.php" title="', $pagetxt['features_title'], '"><img src="site_images/features.png" alt="', $pagetxt['download_title'], '" /><br />', $pagetxt['features'], '</a><br />
<a href="/support/" title="', $pagetxt['support_title'], '"><img src="site_images/support.png" alt="', $pagetxt['download_title'], '" /><br />', $pagetxt['support'], '</a>
</div>
<div id="lower">
<h3>', $pagetxt['h2'], '</h3>
<p>', $pagetxt['p1'], '</p><br />
<div id="splash_left">
<div id="splash"></div>
</div>
<div id="lower_bottom">
<div id="newsheaders">
<h3>', $pagetxt['h3'], '</h3>';

foreach($context['smfinfo'] as $info)
echo '
<dl>
<dt><a href="', $info['link'], '">', $info['title'], '</a></dt>
<dd>', $info['description'], '</dd>
</dl>';

echo '
</div>
<div id="memberbox" class="clearfix">
<div id="loginbox">
<h3>User</h3>';

if ($context['user']['is_logged'])
{
echo '
<h4>', sprintf($pagetxt['welcome_user'], $context['user']['name']), '</h4>
<ul>
<li>';
// Show how many messages there are
if ($context['user']['unread_messages'] == '0')
{
echo $pagetxt['no_new'];
}
elseif($context['user']['unread_messages'] == '1')
{
echo sprintf($pagetxt['one_new'], $context['user']['unread_messages']);
}
else
{
echo sprintf($pagetxt['many_new'], $context['user']['unread_messages']);
}
echo '
</li>
<li>', $pagetxt['go_profile'], '</li>
<li>', $pagetxt['unread'], '</li>
</ul>';
}
else
{
echo '
<h4>', $pagetxt['login'], '</h4>
<form action="http://www.simplemachines.org/community/index.php?action=login2" method="post">
<label for="user">', $txt['username'], ':</label>
<input type="text" id="user" name="user" size="9" value="" />
<label for="passwrd">', $txt['password'], ':</label>
<input type="password" name="passwrd" id="passwrd" size="9" />
<input type="hidden" name="cookielength" value="-1" />
<input type="submit" value="', $txt['login'], '" />
</form>';
}


echo ' </div>
<div id="search">
<h3>Search</h3> ';
theme_searchbox(false);
echo'
</div>
</div>
</div>
</div>
</div>';
}

?>

This is the template function.  You should notice it looks a lot like a normal SMF template function.

The next file is the about page index.
<?php

$section 
'about';
$menulink 'about';

$sectionheader 'About Simple Machines';
$title 'Who are we?';

$callback false;

Again all of our setup variables.  In this case we are manually setting the title.  This page is all HTML, so there is no need for a source function, so we turn it off.


require_once('../integrate.php');

By request of our server admin we are now using relative paths to get to integrate.php.


function template_file_template()
{
global $siteurl, $context;

echo '
<div class="snav">
<h6>Navigation</h6>
<ul class="snav">
<li  id="active" class="first"><a href="index.php">Who are we?</a></li>
<li><a href="values.php">Core Values</a></li>
<li><a href="whyfree.php">Free: it\'s better!</a></li>
<li><a href="opensource.php">Simple Machines and Open Source</a></li>
</ul>
</div>
<h3>Who are we?</h3>
<img class="img-floatright" src="../site_images/yabbse.png" alt="YabbSE" />
<h4>Past</h4>
<p>SMF can trace its roots all the way back to a perl powered message board, YaBB. After awhile, there became a demand for a php coded version of YaBB. So that is where YaBBSE comes into play. While YaBBSE was getting bigger and bigger, there were certain aspects of it that just needed improvement and reworking. The decision was made that it was best to separate from YaBBSE because it was a lot different from YaBB and it was best to start from scratch. At this point, SMF started being developed. On September 29th, 2003, the first beta of SMF was released to charter members, SMF 1.0 Beta 1. While this was a huge milestone for SMF, only charter members had access to use it. But on March 10, 2004, SMF made its public debut with the first public SMF release available to everyone.</p>

<h4>Present</h4>

<p>The people behind SMF are a diverse group of individuals who in their free time, put their efforts together to help make SMF what it is today, and help SMF take strides into the future. Many different uses of skills are expressed within several teams, including a design team, modification team, development team, documentation team, support team, and a language team. Each team works together to help SMF grow and reach its full potential. We are people, just like you, who put our efforts into SMF, driven by passion we have for the software. For a listing of all the team members who have helped put together the latest release of SMF, see the <a href="http://www.simplemachines.org/about/team.php">team page</a>.</p>

<h4>Future</h4>
<p>SMF strives to get better and better. Active discussions amongst the team are being made to discuss the future of SMF. In the future, you can expect SMF to be even more user-friendly, offer better and quicker support, and much more. This is just the beginning for SMF, expect the building blocks of SMF and the community to be expanded, but to keep to the original goal: Simple, elegant, powerful, and free.</p>

<div class="snav">
<h6>Navigation</h6>
<ul class="snav">
<li id="active" class="first"><a href="index.php">Who are we?</a></li>
<li><a href="values.php">Core Values</a></li>
<li><a href="whyfree.php">Free: it\'s better!</a></li>
<li><a href="opensource.php">Simple Machines and Open Source</a></li>
</ul>
</div>';
}

?>

This page hasn't been changed to use $pagetxt but hopefully one day ;)


I hope this rather lengthy post will help you all understand how we have it setup and hopefully will help in doing the same on your site if you wish.

Comments


Daniel15 on April 10, 2007, 09:04:11 AM said
Very nice post, Thantos! A lengthy post, but some great reading. You've given me some ideas on how to restructure my site's (rather ugly) code. :D


QuoteThis allows use to restrict access to a particular page by permission. 
Now there's an awesome idea :)

Quote$request = $smfFunc['db_query']('', "
Just as a note for anyone looking at the code posted, $smfFunc['db_query'] is SMF 2.0's equivalent to db_query(). Similarly, $smfFunc['db_fetch_assoc'] is SMF 2.0's mysql_fetch_assoc(). It's done like this in SMF 2.0 due to the multi-database support (the $smfFunc functions are basically wrappers for the proper database functions - If you're using MySQL, $smfFunc['db_fetch_assoc'] calls mysql_fetch_assoc. Likewise, if you're using SQLite, it calls SQLite's equivalent. Quite a smart idea, and works really well :))

webs86 on April 24, 2007, 04:58:42 PM said
hi! this version of integrate.php file work correctly with SMF 1.1.2 or it requires SMF 2.0 version?

because I have an error with smf 1.1.2 and integrate.php.
at this line
$request =  $smfFunc['db_query']('', "

i returned this error:
Fatal error: Function name must be a string in C:\Program Files\xampp\htdocs\picosafra\index.php on line XX


Thanks

Daniel15 on April 25, 2007, 01:24:16 AM said
Quote from: webs86 on April 24, 2007, 04:58:42 PM
hi! this version of integrate.php file work correctly with SMF 1.1.2 or it requires SMF 2.0 version?

because I have an error with smf 1.1.2 and integrate.php.
at this line
$request =  $smfFunc['db_query']('', "

i returned this error:
Fatal error: Function name must be a string in C:\Program Files\xampp\htdocs\picosafra\index.php on line XX


Thanks

Please read my post above ;)
$request $smfFunc['db_query'](''"
needs to be changed to
$request db_query("

The same for $smfFunc['db_fetch_assoc'](; it needs to be changed to mysql_fetch_assoc(

ladynada on April 25, 2007, 01:35:05 AM said
although totally not sophisticated like your code, I also used SMF code to make the ultiportal portal.  its working fine for me.  I will have to look into your code now for some hacks to make ultiportal better.

:)

nada

cyberox on May 29, 2007, 05:35:32 PM said
Does anyone have a working sample zip file for this?
I've followed each step; but still cannot integrate custom pages into smf.

Daniel15 on May 30, 2007, 02:14:00 AM said
Quote from: cyberox on May 29, 2007, 05:35:32 PM
Does anyone have a working sample zip file for this?
I've followed each step; but still cannot integrate custom pages into smf.
To add a page "into" SMF, try this code in a seperate PHP file:

<?php
error_reporting
(E_ALL);

// Theme we're going to use
$ssi_theme 4;
// Layers we're going to use
$ssi_layers = array('main');
// Enable GZip compression (saves bandwidth)
$ssi_gzip true;

require(
'SSI.php');

echo 
'See? SMF is cool :)';

ssi_shutdown();
?>


You'll need to change the $ssi_theme = 4 line to the correct theme ID.

lwjuan on June 07, 2007, 10:02:11 PM said
I do not know about php scripting.. So is it i have to create a new php file and copy the above content and edit some and upload to the server then it'll work?

Thantos on June 08, 2007, 12:53:17 AM said
To be honest, if you don't understand programming/scripting then my files will most likely be more then you need.

Daniel15 on June 08, 2007, 05:27:44 AM said
Quote from: lwjuan on June 07, 2007, 10:02:11 PM
I do not know about php scripting.. So is it i have to create a new php file and copy the above content and edit some and upload to the server then it'll work?
As Thantos said, his post is mainly aimed towards PHP developers...
I'd suggest to use my code above (or rather, a slightly modified version of it):

<?php
error_reporting
(E_ALL);

// Theme we're going to use
$ssi_theme 4;
// Layers we're going to use
$ssi_layers = array('main');
// Enable GZip compression (saves bandwidth)
$ssi_gzip true;

require(
'SSI.php');

?>

Put your HTML content here!
<?php

ssi_shutdown
();
?>



I guess the easiest way is to create two new files: header.php, and footer.php.

header.php:

<?php
error_reporting
(E_ALL);

// Theme we're going to use
$ssi_theme 4;
// Layers we're going to use
$ssi_layers = array('main');
// Enable GZip compression (saves bandwidth)
$ssi_gzip true;

require(
'SSI.php');

?>



footer.php:

<?php
ssi_shutdown
();
?>



Then, in a new PHP file (name it whatever you want):

<?php require('header.php'); ?>

Your HTML stuff would go here!<br />
etc etc etc.

<?php require('footer.php'); ?>


This is not really the best way, but it's the easiest way for non-programmers to achieve a good result :)

maurizio35 on July 08, 2007, 09:30:08 AM said
Hey Daniel15, thanks for the code, I really appreciated it, but I have 2 simple questions for you about the code.

Do you know what I should do to make this page accessible to members only? (require a login?)

And how can I write the username and email address of the user to somewhere in that page? (what codes I should use?)

Regards,
Maurizio.

dextrous on July 08, 2007, 09:03:24 PM said
Quote
// Layers we're going to use
$ssi_layers = array('main');
Hmm, themes I understand. What are layers?

Daniel15 on July 09, 2007, 12:37:00 AM said
QuoteDo you know what I should do to make this page accessible to members only? (require a login?)
If you want the SMF login box when a guest tries to access the page, put this at the very top of the page:

is_not_guest('Error: You must log in to access this section!');


If you just want to check whether they're a guest or not (and not show the login box), you'd do something like this:

<?php
if ($context['user']['is_guest'])
echo 'Error: You must be logged in to access this section!';
else
{
// The stuff that members can see here
}
?>



QuoteAnd how can I write the username and email address of the user to somewhere in that page?
Their username is in $context['user']['name'], and the email address should be in $context['user']['email'] (although I did not check). To use these in an echo statement, do something like:

<?php
echo '
bla bla bla...<br /><br />

Your username: '
$context['user']['name'], '<br />
Your email address: '
$context['user']['email'], '<br />

bla bla bla...
....'
;
?>



To see all the $context['user'][...] values you can use:

<?php
echo '<pre>'print_r($context['user'], true), '</pre>';


QuoteHmm, themes I understand. What are layers?
Essentially, layers are two sub-templates: A top one (above), and a bottom one (below). The "above" layer is displayed above your content, whilst the "below" layer is displayed below it. For example, the "main" layer has "template_main_above" and "template_main_below" as its two sub-templates.

By default, a SMF theme will have a single layer, the "main" layer. This is the template_main_above and template_main_below functions in index.template.php So, your document flow will be like this:
- template_main_above (the "above" bit of the main layer)
- [ Your content ]
- template_main_below (the "below" bit of the main layer)

You may add additional layers, and they will appear in the order specified. For example, if you have two layers called "html" and "body", the document flow will be like this:
- template_html_above
- template_body_above
- [ Content ]
- template_body_below
- template_html_below

Hope I explained it well :). If not, I'll try and post sometihng that's easier to understand :P

Edit: Some definitions:

Sub-template: A single function (template_*) inside a template file.
Template: A single template file (eg. index.template.php, Display.template.php) comprised of multiple sub-templates
Theme: A directory consisting of a collection of templates
Layer: Two sub-templates, an "above" one and a "below" one

Karuhun on July 31, 2007, 01:48:34 AM said
Great tutorials, thanks to Thantos and Daniel15 :)

Daniel15 on July 31, 2007, 02:26:14 AM said
No problem... Glad to see we helped you :D

Dragooon on July 31, 2007, 02:27:00 AM said
Ahh I loved it!
It helped me to get 5 latest news from my news board :P

Miles Marshall on August 23, 2007, 11:33:32 AM said
I want to make a homepage, About me etc.. using custom SSI could someone point me in the right direction? I want to start off with the "About me page' Like smf has on here all tied together neatly I created a

header.php
<?php
error_reporting
(E_ALL);

// Theme we're going to use
$ssi_theme 1;
// Layers we're going to use
$ssi_layers = array('main');
// Enable GZip compression (saves bandwidth)
$ssi_gzip true;

require(
'SSI.php');


footer.php
<?php
ssi_shutdown
();
?>


well then my page of course home.php when I navigate to the page I get errors
http://geekinc.info/home.php

Coldfx on August 23, 2007, 03:25:49 PM said
Quote from: Miles™ on August 23, 2007, 11:33:32 AM
I want to make a homepage, About me etc.. using custom SSI could someone point me in the right direction? I want to start off with the "About me page' Like smf has on here all tied together neatly I created a

header.php
<?php
error_reporting
(E_ALL);

// Theme we're going to use
$ssi_theme 1;
// Layers we're going to use
$ssi_layers = array('main');
// Enable GZip compression (saves bandwidth)
$ssi_gzip true;

require(
'SSI.php');


footer.php
<?php
ssi_shutdown
();
?>


well then my page of course home.php when I navigate to the page I get errors
http://geekinc.info/home.php


<?php

$ssi_gzip 
true;
$ssi_ban true;
ob_start();

require(
'SSI.php');

$context['page_title'] = 'Title Here';

template_main_above();

echo
'Content Here';

template_main_below();

?>



That's what I use.

Miles Marshall on August 23, 2007, 03:49:29 PM said
So ok lets start over, Tell me how I  would make a custom page from scratch

Miles Marshall on August 23, 2007, 06:59:45 PM said
I just want to make new pages, Like a home page and what not the right way

SleePy on August 23, 2007, 09:19:12 PM said
Miles,
While discussion on this is nice, You should ask for support about doing this in the coding discussion boards instead.

Miles Marshall on August 23, 2007, 09:37:04 PM said
Sorry I was just replying to were the rest of the people replied to

diningin on September 05, 2007, 05:09:01 AM said
nice post

Flying Drupalist on September 16, 2007, 01:34:25 AM said
Hi, I'm attempting to use the code in http://www.simplemachines.org/community/index.php?topic=163770.0 to integrate mediawiki with my forum.

Here's what I added to the monobook theme.


<?php

$ssi_gzip 
true;
$ssi_ban true;

$ssi_theme 16;
ob_start();

require(
"/home/miraploy/www/SSI.php"); 

$context['page_title'] = 'Title Here';

template_main_above();

/**
 * MonoBook nouveau
 *
 * Translated from gwicke's previous TAL template version to remove
 * dependency on PHPTAL.
 *
 * @todo document
 * @addtogroup Skins
 */

if( !defined'MEDIAWIKI' ) )
die( -);

/** */
require_once('includes/SkinTemplate.php');

/**
 * Inherit main code from SkinTemplate, set the CSS and template filter.
 * @todo document
 * @addtogroup Skins
 */
class SkinMonoBook extends SkinTemplate {
/** Using monobook. */
function initPage( &$out ) {
SkinTemplate::initPage$out );
$this->skinname  'monobook';
$this->stylename 'monobook';
$this->template  'MonoBookTemplate';
}
}

/**
 * @todo document
 * @addtogroup Skins
 */
class MonoBookTemplate extends QuickTemplate {
/**
 * Template filter callback for MonoBook skin.
 * Takes an associative array of data set from a SkinTemplate-based
 * class, and a wrapper for MediaWiki's localization database, and
 * outputs a formatted page.
 *
 * @access private
 */
function execute() {
global $wgUser;
$skin $wgUser->getSkin();

// Suppress warnings to prevent notices about missing indexes in $this->data
wfSuppressWarnings();

?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="<?php $this->text('xhtmldefaultnamespace'?>" <?php 
foreach(
$this->data['xhtmlnamespaces'] as $tag => $ns) {
?>
xmlns:<?php echo "{$tag}=\"{$ns}\" ";
?>
xml:lang="<?php $this->text('lang'?>" lang="<?php $this->text('lang'?>" dir="<?php $this->text('dir'?>">
<head>
<meta http-equiv="Content-Type" content="<?php $this->text('mimetype'?>; charset=<?php $this->text('charset'?>" />
<?php $this->html('headlinks'?>
<title><?php $this->text('pagetitle'?></title>
<style type="text/css" media="screen,projection">/*<![CDATA[*/ @import "<?php $this->text('stylepath'?>/<?php $this->text('stylename'?>/main.css?<?php echo $GLOBALS['wgStyleVersion'?>"; /*]]>*/</style>
<link rel="stylesheet" type="text/css" <?php if(empty($this->data['printable']) ) { ?>media="print"<?php ?> href="<?php $this->text('stylepath'?>/common/commonPrint.css?<?php echo $GLOBALS['wgStyleVersion'?>" />
<link rel="stylesheet" type="text/css" media="handheld" href="<?php $this->text('stylepath'?>/<?php $this->text('stylename'?>/handheld.css?<?php echo $GLOBALS['wgStyleVersion'?>" />
<!--[if lt IE 5.5000]><style type="text/css">@import "<?php $this->text('stylepath'?>/<?php $this->text('stylename'?>/IE50Fixes.css?<?php echo $GLOBALS['wgStyleVersion'?>";</style><![endif]-->
<!--[if IE 5.5000]><style type="text/css">@import "<?php $this->text('stylepath'?>/<?php $this->text('stylename'?>/IE55Fixes.css?<?php echo $GLOBALS['wgStyleVersion'?>";</style><![endif]-->
<!--[if IE 6]><style type="text/css">@import "<?php $this->text('stylepath'?>/<?php $this->text('stylename'?>/IE60Fixes.css?<?php echo $GLOBALS['wgStyleVersion'?>";</style><![endif]-->
<!--[if IE 7]><style type="text/css">@import "<?php $this->text('stylepath'?>/<?php $this->text('stylename'?>/IE70Fixes.css?<?php echo $GLOBALS['wgStyleVersion'?>";</style><![endif]-->
<!--[if lt IE 7]><script type="<?php $this->text('jsmimetype'?>" src="<?php $this->text('stylepath'?>/common/IEFixes.js?<?php echo $GLOBALS['wgStyleVersion'?>"></script>
<meta http-equiv="imagetoolbar" content="no" /><![endif]-->

<?php print Skin::makeGlobalVariablesScript$this->data ); ?>
               
<script type="<?php $this->text('jsmimetype'?>" src="<?php $this->text('stylepath' ?>/common/wikibits.js?<?php echo $GLOBALS['wgStyleVersion'?>"><!-- wikibits js --></script>
<?php if($this->data['jsvarurl'  ]) { ?>
<script type="<?php $this->text('jsmimetype'?>" src="<?php $this->text('jsvarurl'  ?>"><!-- site js --></script>
<?php ?>
<?php if($this->data['pagecss'   ]) { ?>
<style type="text/css"><?php $this->html('pagecss'   ?></style>
<?php }
if($this->data['usercss'   ]) { ?>

<style type="text/css"><?php $this->html('usercss'   ?></style>
<?php }
if($this->data['userjs'    ]) { ?>

<script type="<?php $this->text('jsmimetype'?>" src="<?php $this->text('userjs' ?>"></script>
<?php }
if($this->data['userjsprev']) { ?>

<script type="<?php $this->text('jsmimetype'?>"><?php $this->html('userjsprev'?></script>
<?php }
if($this->data['trackbackhtml']) print $this->data['trackbackhtml']; ?>

<!-- Head Scripts -->
<?php $this->html('headscripts'?>
</head>
<body <?php if($this->data['body_ondblclick']) { ?>ondblclick="<?php $this->text('body_ondblclick'?>"<?php ?>
<?php if($this->data['body_onload'    ]) { ?>onload="<?php     $this->text('body_onload')     ?>"<?php ?>
class="mediawiki <?php $this->text('nsclass'?> <?php $this->text('dir'?> <?php $this->text('pageclass'?>">
<div id="globalWrapper">
<div id="column-content">
<div id="content">
<a name="top" id="top"></a>
<?php if($this->data['sitenotice']) { ?><div id="siteNotice"><?php $this->html('sitenotice'?></div><?php ?>
<h1 class="firstHeading"><?php $this->data['displaytitle']!=""?$this->html('title'):$this->text('title'?></h1>
<div id="bodyContent">
<h3 id="siteSub"><?php $this->msg('tagline'?></h3>
<div id="contentSub"><?php $this->html('subtitle'?></div>
<?php if($this->data['undelete']) { ?><div id="contentSub2"><?php     $this->html('undelete'?></div><?php ?>
<?php if($this->data['newtalk'] ) { ?><div class="usermessage"><?php $this->html('newtalk')  ?></div><?php ?>
<?php if($this->data['showjumplinks']) { ?><div id="jump-to-nav"><?php $this->msg('jumpto'?> <a href="#column-one"><?php $this->msg('jumptonavigation'?></a>, <a href="#searchInput"><?php $this->msg('jumptosearch'?></a></div><?php ?>
<!-- start content -->
<?php $this->html('bodytext'?>
<?php if($this->data['catlinks']) { ?><div id="catlinks"><?php       $this->html('catlinks'?></div><?php ?>
<!-- end content -->
<div class="visualClear"></div>
</div>
</div>
</div>
<div id="column-one">
<div id="p-cactions" class="portlet">
<h5><?php $this->msg('views'?></h5>
<div class="pBody">
<ul>
<?php foreach($this->data['content_actions'] as $key => $tab) { ?>
<li id="ca-<?php echo Sanitizer::escapeId($key?>"<?php
  if($tab['class']) { ?>
class="<?php echo htmlspecialchars($tab['class']) ?>"<?php }
 ?>
><a href="<?php echo htmlspecialchars($tab['href']) ?>"<?php echo $skin->tooltipAndAccesskey('ca-'.$key?>><?php
 echo htmlspecialchars($tab['text']) ?>
</a></li>
<?php  } ?>
</ul>
</div>
</div>
<div class="portlet" id="p-personal">
<h5><?php $this->msg('personaltools'?></h5>
<div class="pBody">
<ul>
<?php  foreach($this->data['personal_urls'] as $key => $item) { ?>
<li id="pt-<?php echo Sanitizer::escapeId($key?>"<?php
if ($item['active']) { ?>
class="active"<?php ?>><a href="<?php
echo htmlspecialchars($item['href']) ?>
"<?php echo $skin->tooltipAndAccesskey('pt-'.$key?><?php
if(!empty($item['class'])) { ?>
class="<?php
echo htmlspecialchars($item['class']) ?>
"<?php ?>><?php
echo htmlspecialchars($item['text']) ?>
</a></li>
<?php ?>
</ul>
</div>
</div>
<div class="portlet" id="p-logo">
<a style="background-image: url(<?php $this->text('logopath'?>);" <?php
?>
href="<?php echo htmlspecialchars($this->data['nav_urls']['mainpage']['href'])?>"<?php
echo $skin->tooltipAndAccesskey('n-mainpage'?>
></a>
</div>
<script type="<?php $this->text('jsmimetype'?>"> if (window.isMSIE55) fixalpha(); </script>
<?php foreach ($this->data['sidebar'] as $bar => $cont) { ?>
<div class='portlet' id='p-<?php echo Sanitizer::escapeId($bar?>'<?php echo $skin->tooltip('p-'.$bar?>>
<h5><?php $out wfMsg$bar ); if (wfEmptyMsg($bar$out)) echo $bar; else echo $out?></h5>
<div class='pBody'>
<ul>
<?php  foreach($cont as $key => $val) { ?>
<li id="<?php echo Sanitizer::escapeId($val['id']) ?>"<?php
if ( $val['active'] ) { ?>
class="active" <?php }
?>
><a href="<?php echo htmlspecialchars($val['href']) ?>"<?php echo $skin->tooltipAndAccesskey($val['id']) ?>><?php echo htmlspecialchars($val['text']) ?></a></li>
<?php ?>
</ul>
</div>
</div>
<?php ?>
<div id="p-search" class="portlet">
<h5><label for="searchInput"><?php $this->msg('search'?></label></h5>
<div id="searchBody" class="pBody">
<form action="<?php $this->text('searchaction'?>" id="searchform"><div>
<input id="searchInput" name="search" type="text"<?php echo $skin->tooltipAndAccesskey('search');
if( isset( $this->data['search'] ) ) {
?>
value="<?php $this->text('search'?>"<?php ?> />
<input type='submit' name="go" class="searchButton" id="searchGoButton" value="<?php $this->msg('searcharticle'?>" />&nbsp;
<input type='submit' name="fulltext" class="searchButton" id="mw-searchButton" value="<?php $this->msg('searchbutton'?>" />
</div></form>
</div>
</div>
<div class="portlet" id="p-tb">
<h5><?php $this->msg('toolbox'?></h5>
<div class="pBody">
<ul>
<?php
if($this->data['notspecialpage']) { ?>

<li id="t-whatlinkshere"><a href="<?php
echo htmlspecialchars($this->data['nav_urls']['whatlinkshere']['href'])
?>
"<?php echo $skin->tooltipAndAccesskey('t-whatlinkshere'?>><?php $this->msg('whatlinkshere'?></a></li>
<?php
if( $this->data['nav_urls']['recentchangeslinked'] ) { ?>

<li id="t-recentchangeslinked"><a href="<?php
echo htmlspecialchars($this->data['nav_urls']['recentchangeslinked']['href'])
?>
"<?php echo $skin->tooltipAndAccesskey('t-recentchangeslinked'?>><?php $this->msg('recentchangeslinked'?></a></li>
<?php  }
}
if(isset($this->data['nav_urls']['trackbacklink'])) { ?>

<li id="t-trackbacklink"><a href="<?php
echo htmlspecialchars($this->data['nav_urls']['trackbacklink']['href'])
?>
"<?php echo $skin->tooltipAndAccesskey('t-trackbacklink'?>><?php $this->msg('trackbacklink'?></a></li>
<?php  }
if($this->data['feeds']) { ?>

<li id="feedlinks"><?php foreach($this->data['feeds'] as $key => $feed) {
?>
<span id="feed-<?php echo Sanitizer::escapeId($key?>"><a href="<?php
echo htmlspecialchars($feed['href']) ?>
"<?php echo $skin->tooltipAndAccesskey('feed-'.$key?>><?php echo htmlspecialchars($feed['text'])?></a>&nbsp;</span>
<?php ?></li><?php
}

foreach( array('contributions''blockip''emailuser''upload''specialpages') as $special ) {

if($this->data['nav_urls'][$special]) {
?>
<li id="t-<?php echo $special ?>"><a href="<?php echo htmlspecialchars($this->data['nav_urls'][$special]['href'])
?>
"<?php echo $skin->tooltipAndAccesskey('t-'.$special?>><?php $this->msg($special?></a></li>
<?php }
}

if(!empty($this->data['nav_urls']['print']['href'])) { ?>

<li id="t-print"><a href="<?php echo htmlspecialchars($this->data['nav_urls']['print']['href'])
?>
"<?php echo $skin->tooltipAndAccesskey('t-print'?>><?php $this->msg('printableversion'?></a></li><?php
}

if(!empty($this->data['nav_urls']['permalink']['href'])) { ?>

<li id="t-permalink"><a href="<?php echo htmlspecialchars($this->data['nav_urls']['permalink']['href'])
?>
"<?php echo $skin->tooltipAndAccesskey('t-permalink'?>><?php $this->msg('permalink'?></a></li><?php
} elseif ($this->data['nav_urls']['permalink']['href'] === '') { ?>

<li id="t-ispermalink"<?php echo $skin->tooltip('t-ispermalink'?>><?php $this->msg('permalink'?></li><?php
}

wfRunHooks'MonoBookTemplateToolboxEnd', array( &$this ) );
?>

</ul>
</div>
</div>
<?php
if( $this->data['language_urls'] ) { ?>

<div id="p-lang" class="portlet">
<h5><?php $this->msg('otherlanguages'?></h5>
<div class="pBody">
<ul>
<?php foreach($this->data['language_urls'] as $langlink) { ?>
<li class="<?php echo htmlspecialchars($langlink['class'])?>"><?php
?>
<a href="<?php echo htmlspecialchars($langlink['href']) ?>"><?php echo $langlink['text'?></a></li>
<?php ?>
</ul>
</div>
</div>
<?php ?>
</div><!-- end of the left (by default at least) column -->
<div class="visualClear"></div>
<div id="footer">
<?php
if($this->data['poweredbyico']) { ?>

<div id="f-poweredbyico"><?php $this->html('poweredbyico'?></div>
<?php  }
if($this->data['copyrightico']) { ?>

<div id="f-copyrightico"><?php $this->html('copyrightico'?></div>
<?php }

// Generate additional footer links
?>

<ul id="f-list">
<?php
$footerlinks = array(
'lastmod''viewcount''numberofwatchingusers''credits''copyright',
'privacy''about''disclaimer''tagline',
);
foreach( $footerlinks as $aLink ) {
if( isset( $this->data[$aLink] ) && $this->data[$aLink] ) {
?>
<li id="<?php echo$aLink?>"><?php $this->html($aLink?></li>
<?php  }
}
?>

</ul>
</div>

<?php $this->html('bottomscripts'); /* JS call to runBodyOnloadHook */ ?>
</div>
<?php $this->html('reporttime'?>
<?php if ( $this->data['debug'] ): ?>
<!-- Debug output:
<?php $this->text'debug' ); ?>

-->
<?php endif; ?>
</body></html>
<?php
wfRestoreWarnings();
// end of execute() method
// end of class
template_main_below();
?>


Now that doesn't work, ofc. I can think of several pitfalls off of the top of my head. But can somebody point me in the right direction? Thanks.

brianjw on November 10, 2007, 04:56:56 PM said
Thanks for the code! :)

makarkin on December 28, 2007, 03:25:49 AM said
Hi dear. I need Integration SMF into CUBECART. Can you help me ? I think a lot of people need this. I can give some money !

Thank you very much and have a nice day!, Vitaly

brianjw on December 28, 2007, 09:37:39 AM said
They are just distributing the code they're using here. I don't think is the section to ask requests for integrations. Maybe Help Wanted?

Gary on December 28, 2007, 10:41:41 PM said
Indeed help wanted would be a better choice

mtindor on January 05, 2008, 02:45:56 PM said
Daniel,

I put the code below into 'test.php'.   I see it gives the header and footer as espected.  However, it takes 3+ times longer to load that code than it takes to load the real forum index (with all of the content).   What would be causing the page to take so much longer to load with those simple few lines of code?

Mike


Quote from: Daniel15 on May 30, 2007, 02:14:00 AM
To add a page "into" SMF, try this code in a seperate PHP file:

<?php
error_reporting
(E_ALL);

// Theme we're going to use
$ssi_theme 4;
// Layers we're going to use
$ssi_layers = array('main');
// Enable GZip compression (saves bandwidth)
$ssi_gzip true;

require(
'SSI.php');

echo 
'See? SMF is cool :)';

ssi_shutdown();
?>


You'll need to change the $ssi_theme = 4 line to the correct theme ID.

HecKel on January 20, 2008, 01:40:51 PM said
Hi!

Sorry about the bump, I only notice this now :(

Can you put this "tutorial" in http://docs.simplemachines.org/ ? I think a lot of people need this, and there is easier to find ;)

Btw, great job!

bassbass on June 14, 2008, 12:46:34 AM said
excuse my ignorance, i am not sure if i understand this correctly.  am i to combine all the codes in the first post in one file and call it "integrate.php", then change the code to reference to my website and server?  i guess i need an answer to this question first before i go to the next questions.  i can't wait to implement this into my forum, great feature.  Thanks.

bassbass on June 16, 2008, 07:06:46 PM said
Hi again, my intentions are not to bump this up, but wanted to know if anyone is using this Website-Forum Integration, also if anyone cam recommend someone that can set it up for me.  Thanks.

Deaks on June 16, 2008, 09:26:40 PM said
http://www.simplemachines.org/community/ssi_examples.php

try this, on my website

http://runicdesigns.info I use 1.1.5 for customers, and used the above page that helped me alot :) first time using the ssi feature :)

bassbass on June 16, 2008, 09:47:26 PM said
thanks RunicWarrior, i am not sure what to do with the ssi...i used it on a test forum sometime ago, not sure what i was after, but i did get it to display the same as the link you posted http://www.simplemachines.org/community/ssi_examples.php, wasn't sure what it did but did really get into it.  i guess my question is, is there a step by step as to how to install it and integrate it with my current forum?  of course I'll install a test forum and play with it until i fully understand it, perhaps i am asking a bit too much for some one to hold my hand through the initial setup.


Deaks on June 16, 2008, 09:54:05 PM said
To use SSI.php in your page add at the very top of your page before the <html> tag on line 1:
<?php require("SSI.php"); ?>

changing the address to suit your needs compared to where your forum is located :)

then depending on what you want added depends on the code so for example if you want your forum stats to show on the page you would add

<?php ssi_boardStats(); ?>

where you want the to show ...

bassbass on June 16, 2008, 11:13:49 PM said
thanks for that RunicWarrior, I'll play with it and see how far i can get.  thanks again,

Bass

Apllicmz on August 03, 2008, 01:07:59 PM said
good
work

but i see here ..

Each file is broken up into 4 main parts

    * Setup variables not see
    * Bringing in integrate.php  i see yes
    * A source function not see
    * A template function not see

Thantos on August 03, 2008, 01:13:11 PM said
Setup variables are all the variables being defined prior to integrate.php being included.

The source function is file_source() and the template function is template_file_template()

Apllicmz on August 04, 2008, 01:32:28 AM said
did see what i need...

How can puty like that picture



tedhogan on December 12, 2008, 11:38:04 AM said
I'm not sure what's wrong, but I get this error when I try to run the sample script:

Unable to load the 'main_above' template.


It works when I have the $ssl_layers assignment commented out. I am using the default theme ($ssi_theme = 1)



-----------------------
<?php
error_reporting(E_ALL);

// Theme we're going to use
$ssi_theme = 4;
// Layers we're going to use
$ssi_layers = array('main');
// Enable GZip compression (saves bandwidth)
$ssi_gzip = true;

require('SSI.php');

echo 'See? SMF is cool :)';

ssi_shutdown();
?>


-------------------------






Can someone please point me in the right direction?


Thanks,
Ted

brianjw on December 12, 2008, 05:29:01 PM said
Are you using SMF 2.0? If so, that is why.

Gary on December 12, 2008, 09:35:29 PM said
Indeed. In 2.0 you would change:

$ssi_layers = array('main');

to:

$ssi_layers = array('html,body');
Advertisement: