Fullscreen
(Cached)
Refresh Print

Hello World

'Hello World' Tutorial for TikiWiki Developers

Table of contents



Introduction

Luis Argerich (the founder of TikiWiki) wrote:
One of my goals behind Tiki was to make it very easy to any kind of programmer to be able to contribute, if you make a "genius" framework using object oriented code (external link), MVC (external link) and other gadgets you need "genius" programmers. If a new PHP coder can't contribute without learning all sorts of things something is wrong with the framework specially for a community-driven project.

I always thought that adding one PHP file and one template file and putting your code in the PHP and your design in the template was the simplest way to add features to Tiki. Furthermore features can cooperate sharing the database but are completely independent, you remove the code and nothing happens to the rest of Tiki. It is true that the code inside each feature can be not very clear but it is code that is highly cohesive because it does just one thing.

I believe in functionality through simplicity, if you start simple you can always evolve if that is good for the project, and if you ever need it. If you start like the NASA (external link) you can realize too late that you made some ridiculous choices and there is no way back.



mose on the devel mailing list wrote:
> is there any internal development documentation of TikiWiki project. I
> think some architecture description, described database schema and it's
> relations, internal rules, object relations.
>
> I found only documentation for adding new feature, but I think it must
> be something more, because of huge number of developers working on this
> project.
>
> Is internal documentation something available on demand or it simply
> doesn't exist?


It just doesn't exist. And here are the reasons:

The initial design of TikiWiki by Luis Argerich was especially focused on having code with very small abstractions. His purpose, as far as I can imagine, was to make the coding easy so to get a wider population of contributors, and an easy 'hackability'. Then, the source code was initially simple enough and didn't require more documentation that the db structure and the existing source code. There is very few and simple relations in the database, they usually are explicit enough. Many files were using code duplication rather than code abstraction.

That made a ground for a large number of contributions, then code has been evolving organically from the existing basis. Quite fast on some aspects. Maintaining a code documentation was an effort that nobody felt necessary. Well, personally, I never needed it even in early times.

Technically speaking, the TikiWiki development is quite far from the corporate habits. Low-design, fast evolution cycles, organic selection over time of features, it's actually like if we were talking about the wiki-way, but in the coding field (validation of code is posterior to its commit and not prior, like in a wiki).

Of course such outfit brings drawbacks from the industry-oriented point of view that deals with time in much more a mechanical way than what our organic evolution proposes.

But I think that's what attracted many users and contributors of TikiWiki, and disgusted others.


Marc Laporte (project admin) wrote:
TikiWiki has an all-in-one approach to features. Think of it as a suite of applications like Open Office. Tiki has more built-in features than any other open source Web app (if you know of one, please let me know). Some people are concerned about all the features and that "it can't work" or "it's not the way to do it". Since Tiki has a different model than the "conventional wisdom", I feel it's important to explain how it works and why it works.

Please see: http://www.marclaporte.com/TikiSucks (external link)

Alain Désilets wrote:


Glossary

Things are sometimes named a bit differently than in other Web Applications. Please see:
http://tikiwiki.org/Glossary (external link)

Who does what?

TikiWiki CMS/Groupware is a vast project. It's tricky for new people to know how the TikiWiki Community is organized, to find the right person to contact and to start to contribute. What may I expect from others within TikiWiki Community, and what do others expect from me? Who does what? Who should I talk to? How does it work? This page is intended to help.

Important: everyone is a volunteer. Things get done because someone, like you decides to take the time to make it better.

Please see:
http://tikiwiki.org/WhoWhat (external link)

Smarty/PHP

TikiWiki uses the Smarty template engine (external link). Its purpose is to separate the presentation layer from the programming layer.
The PHP (external link) interfaces with the database, does the computation…and assigns the Smarty variables. The Smarty templates use these variables to generate the actual HTML.

For instance:

<?php // Smarty use sample
$user='admin';
$smarty->assign('user', $user);
?>

This PHP assigns the Smarty variable $user.
This variable will be used in a template like that

<h1>{$user}</h1>

This will display

<h1>admin</h1>


In a Smarty template, you can loop over array of data and do some simple computation. To preserve separation and optimization, no PHP code must be inserted in a template.

The 'Hello World' page

How to display "hello world" in the central column of a TikiWiki page:

Create a php file in the TikiWiki root directory (where tiki-install.php is).
hello_world.php:

<?php // hello_world displayed in a TikiWiki center column
include_once('tiki-setup.php');
$smarty->assign('mid', 'hello_world.tpl');
$smarty->display('tiki.tpl');
?>

Create a template located in the sub directory templates/ (http://www.domain.com/templates/) or in templates/styles/your_style/
hello_world.tpl:

<p>Hello World</p>


To test it, type the URL in your browser : http://my.domain.com/hello_world.php (external link) (where http://my.domain.com (external link) links to your TikiWiki root).


Notice the use of include_once(‘tiki-setup.php’) in the php code. This include initializes the context to be able to use smarty. Later we will see it is doing more.
tiki.tpl is the TikiWiki global template file. It is the only(almost) template that contains a complete html page. A simplified working tiki.tpl file would be:

{* top *}
{include file="header.tpl"}
{* middle *}
    {* left column *}
         {section name=ix loop=$left_modules}
            {$left_modules[ix].data}
         {/section}
    {* middle column *}
            {include file=$mid} 
    {* right column *}
        {section name=ix loop=$right_modules}
              {$right_modules[ix].data}
        {/section}
{* bottom*}
{include file="footer.tpl"}

You can see the top section header.tpl, the bottom section footer.tpl and the 3 columns. The left column displays all the left modules through a loop. Idem for the right column. The central part is an include of the $mid file. (Notice: in TikiWiki 1.10, it is simply {$mid} and not {include file=$mid} )
In our hello_world example, the $mid part is the template hello_world.tpl and will display the string “hello world”.

The templates hello_world.tpl can be created in the sub-directory templates/ or the sub-directory templates/styles/your_style/ (where your_style is the name of the theme you are currently using (A theme name is the css file name without extension). If it exists, the template in your current theme directory overrides the one in the default directory. The avantage of putting your templates in your local theme directory is to better identify what you have changed from the original TikiWiki. (Notice: if you are using CVS and are handy with cvs conflict resolution, it may be better to directly modify the templates in the default directory to be able to update/merge the tikwiki modification with yours)

The $left_modules and $right_modules smarty variables are set up in tiki-modules.php. You will see later in the module section how the modules are set.

tiki-setup.php


This include does everything you need to have a TikiWiki page. It does a lot more that initializing smarty. By including this file in your php, you:
  • establish the connection with the database.
  • read all the system preferences, user preferences, permissions from the database.
  • check if the user is logged via a cookie.
  • computes all the modules (in TikiWiki1.9). In TikiWiki 1.10 this is done in $smarty->display
  • check up for some security points

A couple of interesting variables are also set there
  • user (user login)
  • group (default group name)
  • language
  • all preferences
  • ….
All these variables are set for php and for smarty.

To see your username in the hello world program, modify your template:

<p>Hello World, Dear {$user}</p>


How to debug and to see the smarty variables

If you want to see all the smarty variables that are set, you can use the smarty function {debug} in your templates. Smarty will display a popup window.

{debug}
<p>Hello World</p>



You can also use the php function echo or print_r to see some php variable for debugging.
And you can use the function debug_backtrace to see the php trace.

<?php 
function test() {
   echo "<pre>";
   print_r(debug_backtrace());
   echo "</pre>";
}
include_once('tiki-setup.php');
echo "<pre>user:$user</pre>";
test();
$smarty->assign('mid', 'hello_world.tpl');
$smarty->display('tiki.tpl');


To execute some queries in the php

TikiWiki uses the ADODB (external link) database abstraction library. A good description about how to code the queries can be found at http://TikiWiki.org/tiki-index.php?page=DbAbstractionDev (external link)

A typical list routine without permission check.
In lib/contribution/contributionlib.php

// List a subset of contribution
// $offset = will return the objects from there to $offset + $maxRecords (if 0 = from the beginning)	
// $maxRecords = max number to return if = -1 returns all the objects
// $sort_mode = order criterium
// $find = string to search
function list_contributions($offset=0, $maxRecords=-1, $sort_mode='name_asc', $find='') {
	$bindvars = array();
	$mid = '';
	if ($find) {
		$mid .= " where (`name` like ?)";
		$bindvars[] = "%$find%";
	} 
	$query = "select * from `tiki_contributions` $mid order by ".$this->convert_sortmode($sort_mode);
	$result = $this->query($query, $bindvars, $maxRecords, $offset);

	$ret = array();
	while ($res = $result->fetchRow()) {
		$ret[] = $res;
	}
	$retval = array();
	$retval['data'] = $ret;
	if ($maxRecords > 0) {
		$query_cant = "select count(*) from `tiki_contributions` $mid";
		$retval['cant'] = $this->getOne($query_cant, $bindvars);
	} else {
		$retval['cant'] = count($ret);
	}
	return $retval;		
}

First, you have to notice that all table names and column names must be back quoted.
The $sort_mode is the concatenation of the column name, the underscore and asc or desc. It can be any column.

In the main php, tiki-contribution.php, you will have

include_once('lib/contribution/contributionlib.php');
$contributions = $contributionlib->list_contributions();
$smarty->assign('contributions', $contributions['data']);


and in the template templates/tiki-contribution.tpl, you will have

{cycle values="even,odd" print=false}
{section name=ix loop=$contributions}
<tr>
	<td class="{cycle advance=false}">{$contributions["ix"].name|escape}</td>
	<td class="{cycle}">{$contributions["ix"].hits}</td>
</tr>
{/section}


Notice: There is not yet good method to check the perms in this kind of routine. You have to get all the objects and checked them.

To introduce a new feature or a new preference

In 2.0 lib/setup/prefs.php has been introduced. Add your preference to this file, no database hacking is necessary. For pre-2.0 times and other (fundamental) DB changes the procedure below is still valid.

For instance, you want to create a new feature called contribution
First you have to create an entry in the database

INSERT IGNORE INTO tiki_preferences(name,value) VALUES ('feature_contribution', 'n');

Each database update must be done in db/tiki.sql and db/tiki_1.xto1_y.sql. The first sql does the complete database creation, the second is the upgrade script. The second one can be rerun as many times as needed ((with the mysqldump option –f to ignore error).. The update of each script for each database supported by TikiWiki is done by the script db/convertscripts/convertsqls.sh (Available in 1.10). So each time you have to update the database scheme, you have to modify 2 files and run a script.
The script can be run by

cd db/convertscripts
./convertsqls.sh <virtualhost/root>

virtualhost/root can be localhost/tiki1.9 for instance

After you have to insert the check box into the features administration page.
In templates/tiki-admin-include-features.tpl, you have to insert these lines :
In TikiWiki1.10

<tr>
   <td>
<input type="checkbox" name="feature_contribution"{if $prefs.feature_contribution eq 'y'} checked="checked"{/if}/>
   </td>
   <td class="form">
{if $prefs.feature_help eq 'y'}<a href="{$prefs.helpurl}Contribution" target="tikihelp" class="tikihelp" title="{tr}Contribution{/tr}">{/if}
{tr}Contribution{/tr}
{if $prefs.feature_help eq 'y'}</a>{/if}
   </td>
   <td colspan="3">&nbsp;</td>
</tr>

In TikiWiki1.9

<tr>
   <td>
<input type="checkbox" name="feature_contribution"{if $feature_contribution eq 'y'} checked="checked"{/if}/>
   </td>
   <td class="form">
{if $feature_help eq 'y'}<a href="{$helpurl}Contribution" target="tikihelp" class="tikihelp" title="{tr}Contribution{/tr}">{/if}
{tr}Contribution{/tr}
{if $feature_help eq 'y'}</a>{/if}
   </td>
   <td colspan="3">&nbsp;</td>
</tr>

just before these lines if you want it in the first table.



</table>
{* ---------- Administration features ------------ *}


In tiki-admin_include_features.php, you have to insert the line "feature_contribution",
in the $features_toggles table definition

$features_toggles = array(
"feature_contribution",
….
);
foreach ($features_toggles as $toggle) {
 	simple_set_toggle ($toggle);
 }

The loop on features_toggles will to the wanted step:
- update the database
- update the smarty variable and the php variable
Notice: Not all the admin pages are using simple_set_toggle ($toggle);even if it is the best practice.

You have nothing else to do, tiki-setup.php will automatically read and assign the php variable and the smarty variable $prefs in TikiWiki 1.10 (so you can use $prefs.feature_contribution) or $feature_contribution in TikiWiki1.9 in any TikiWiki page.

Feature and preference are set the same way.

You can have the list of features/preferences in the sql table tiki_preferences.
Notice: all the preferences are not necessarily there. Some old preferences have not been set in this table and are test through isset($this_preference).This is bad habit: it is better to always include your preference as described previously in the database and not to test if it is set with the isset function

INSERT IGNORE INTO tiki_preferences(name,value) VALUES ('my_preference', 'my_value');


To update the database schema

DatabaseSchemaUpgrade

To get/set a user preference

To get the value of a user preference, you can use in a function :

global $tikilib, $someuser;
$foo = $tikilib->get_user_preference($someuser, $pref_name, $default_pref_value);

$someuser is the user name.
$pref_name can be ‘theme’, ‘allowMsgs’…
The default for $default_pref_value is ‘’
The effect of the above code is to populate the global array variable $user_preferencessomeuser, which is also returned in the variable foo.
Notice: “global $tikilib, $someuser;” is not necessary if you add these lines in the same file that the include tiki-setup.php (the hello_world.php) but are needed in you add these lines in a function.
Notice: To access the prefs of the current user (user), it is not necessary to use the above. These are always available as variables. In version 1.10, they are available in the $prefs array.

To set a user preference

global $tikilib, $someuser;
$tikilib->set_user_preference($someuser, $pref_name, $pref_value);


Notice: we don’t include lib/tikilib.php because it is always included in tiki-setup.php. Meanwhile, the other libraries must be included like this:

global $categlib; include_once('lib/categories/categlib.php');

Notice the use of global. Global is necessary because your library can have been included in another function that is out of scope of your new function.

You can have a list of user preferences in the sql table tiki_user_preferences. Same remark than for tiki_preferences, the list can be incomplete.

To create a menu or to introduce a menu option

TikiWiki has a couple of ways to introduce menus
- one by creating the menu and the menu options through sql (1)
- one by using the tiki API (2)
- one by using the templating / module feature (3)
- one based on phplayers (4)

There is not really a best method to create a menu. It depends. If your menu can be dynamically updated, you will not use the template. If your menu is fixed, perhaps a template is the best.
The phplayers method is not described here as there is no current API. (phplayers menu are interesting because they can have more than 2 levels (Means an option in an option in a section)

INSERT INTO tiki_menus (menuId,name,description,type) VALUES ('100', ‘My menu','My very own  menu','d');
INSERT INTO tiki_menu_options (menuId,type,name,url,position,section,perm,groupname) VALUES (‘100’,'o','My option','tiki-my_option.php',10,'','','');
INSERT INTO tiki_menu_options (menuId,type,name,url,position,section,perm,groupname) VALUES (‘100’,'o','My other option','tiki-my_other_option.php',15,'','','');

A menu affects 2 tables. One for the menu by itself, and the other one for the menu options. In the previous example, we created a menu ‘My menu’ with 2 options.
A menu type can be
- d (dynamic collapsed)
- e (dynamic extended)
- f (fixed)
an option type can be:
- s (section)
- r (sorted section)
- o (option)
- - (separator)

The section parameter corresponds the feature. If the feature is not activated, the option will not show up.
The groupname parameter is a filter on the group.

Notice: the menuId 42 is reserved for the application menu (the default TikiWiki menu).
Trick: we usually don’t give consecutive number to menu options to be able later to add additional options easier.
If an option can be see with 2 perms, you need to add 2 options with the same position and different perm. Idem if it can be see in 2 sections or 2 groups.
Some documentation can be found at http://doc.TikiWiki.org/tiki-index.php?page=Custom+Menus. (external link)
Notice: there is some bugs about the expand/collapse javascript in tw1.9.2.

To insert this menu in a column, you need to create a user menu that uses it (admin->modules->create a new user menu) and then assign this user menu (admin->modules->assign new module)


global $menulib; include_once(‘lib/menubuilder/menulib.php’);
$menulib->replace_menu($menuId, $name, $description, $type);
foreach (… optionmenu…) {
$menulib->replace_menu_option($menuId, $optionId, $name, $url, $type, $position, $section, $perm, $groupname);
}

The parameter values are the same than described previously.
Notice: you can notice the use of global $menulib. This is very useful when you use this part of code in a function. The include can have been done somewhere else, and the global gives you the opportunity to catch the variable $menulib.

If you don’t know the $menuId you want to use, you need to

$menulib->replace_menu(0, $name, $description, $type);
$query = 'select max(`menuId`) from `tiki_menus`';
$menuId = $tikilib->getOne($query);
foreach (… optionmenu…) {
   $menulib->replace_menu_option($menuId, $optionId, $name, $url, $type, $position, $section, $perm, $groupname);
}


Next, you have to create a user menu and assign it

global $modlib; include_once ('lib/modules/modlib.php');
$modlib->replace_user_module($name, $title, "{menu id=$menuId}");
$modlib->assign_module($name, $title, $position, $order, 0, $rows , serialize($groups), $params, $type);

$position is ‘l’ (left column) or ‘r’ (right column)
If you assign 2 modules with the same order in the same column, they will appear both in a random order.
$groups is an array of groups (ex: array("Registered", "Anonymous"))
$params is the value you put in the param field in admin->modules->assign module. (ex: “max=10”)
$type is ‘D’ to assign to everybody.
You can also create a menu with a template module. A good example is templates/modules/mod-application_menu.tpl. This menu is the old tikwiki menu that has been replaced by a database menu to be able to use the mods.

You only need to create a new template in templates/modules/ with a filename beginning with mod-. This new module will automatically appear in the admin->modules scrolling list.

To introduce a new permission

If you want to create a new permission, you need to add it in the database like this:

INSERT INTO users_permissions (permName, permDesc, level, type) 
    VALUES ('tiki_p_whatever', 'Perm definition', 'level', 'feature');

This must be added in db/tiki.sql and db/tiki_1.xto1.y.sql.
Where level can be editors, registered, admin … and feature is the group of perms (wiki, cms, blog..)
You can create a new group of perms there. There is no other requirement for a group of perms.
The perm will be read and set to a php variable and a smarty variable in tiki-setup.php

In a php, the perm is used like this:

if ($tiki_p_whatever == 'y')

Don’t forget to compare to a value a current error is to write only

if ($tiki_p_whatever)//wrong code

We usually name a perm with a name beginning by tiki_p_

To check a permission

All permissions can be overwritten at a category or object level. The rule to check if you have the tiki_p_perm on an object is:
- check if the object has special perm. If yes, test if one of the group user has the perm tiki_p_perm otherwise returns false.
- check if the object has a category with special perm. If yes, test if one of the group user has the perm tiki_p_perm otherwise returns false.
- if none above, use the tiki_p_perm value

A function is dedicated to do the job

include_once('tiki-setup.php');
include_once('lib/tikilib.php');
$perm = $tikilib->user_has_perm_on_object($user, $object_id, $object_type, $tiki_p_perm);

where user is the login name, $object_id is the object id (can be the page name or the article_id or …), $object_type is the object type (can be ‘wiki page’, ‘article’….). You can use an array of perms instead of tiki_p_perm if needed.

Example

if (!$tikilib->user_has_perm_on_object($user, $pageName, 'wiki_page', 'tiki_p_view') {
	$smarty->assign('msg', tra('Permission denied you cannot read this page'));
	$smarty->display('error.tpl');
	die;
}


Example

if (!$tikilib->user_has_perm_on_object($user, $quiz_id, 'quiz', array('tiki_p_take_quiz','tiki_p_view_quiz_stats')){
	$smarty->assign('msg', tra('Permission denied you cannot access this quiz'));
	$smarty->display('error.tpl');
	die;
}


Notice: This function is very convenient but it is quite a bit slow even if there are a couple of cache to optimize it. There is only one example in the TikiWiki code that integrates the perm checking in the sql query.

To reassign all the permissions a user has on an object
There is actually no integrated function to do the job. This snippet reassigns the perm variables.

global $userlib; include_once('lib/userslib.php');

global $feature_categories;
if ($userlib->object_has_one_permission($objectId, $objectType)) {
	$perms = $userlib->get_permissions(0, -1, 'permName_desc', '', $objectType);
	foreach ($perms['data'] as $perm) {
		$permName = $perm["permName"];
		if ($userlib->object_has_permission($user, $objectId, $objectType, $permName)) {
			$permName = 'y';
		} else {
			$permName = 'n';
		}
	}
} elseif ($feature_categories == ‘y’) {
	global $categlib; include_once('lib/categories/categlib.php');
$perms_array = $categlib->get_object_categories_perms($user, $objectType, $objectId); 
   	if ($perms_array) {
    		foreach ($perms_array as $permName => $value) {
    			$permName = $value;
		}
    	}
  }

$objectId is the object identifier: Ex: the page name for a wiki page, the article_id for an article.
$ObjectType is one of ‘wiki page’, ‘article’, ‘forum’, ‘post’, ‘blog’, ‘faq’, ‘image gallery’, ‘file gallery’, ‘comment’, ‘tracker’, ‘survey’, ‘quiz’ …

To wiki parse a textarea

Imagine you have a textarea and you want this textarea to accept wiki format.
To parse the textarea, you will have to call

$tikilib->parse_data($text)
Usually if you have a choice like “it is html”, you need to add an additional parameter
$tikilib->parse($test, $is_html)

PS: some tikwiki1.9 have bugs around the is_html parameter. There are patched by replacing $test with htmlspecialchars($test);

If you want to add some quicktags to the textarea

include_once ('lib/quicktags/quicktagslib.php');
$quicktags = $quicktagslib->list_quicktags(0,-1,'taglabel_desc','','wiki');
$smarty->assign_by_ref('quicktags', $quicktags["data"]);
$smarty->assign('quicktagscant', $quicktags["cant"]);


In the templates in order to use the quicktags, you have to add in the template where you want the quicktags to appear:

{include file="tiki-edit_help_tool.tpl"}


PS: only one quicktag zone per page is allowed

If you want to add the resize buttoms, you have to add in the php:

include_once("textareasize.php");


And in your tpl, you have to add something like this:

<form  … id='editpageform'>
{include file="textareasize.tpl" area_name='editwiki' formId='editpageform'}
<textarea id='editwiki' … rows="{$rows}" cols="{$cols}">{$pagedata|escape}</textarea>
<input type="hidden" name="rows" value="{$rows}"/>
<input type="hidden" name="cols" value="{$cols}"/>
</form>


Categories

How to make your feature use categories.
docs need to be written


Theme control center

How to make your feature be able to take on a different theme (depending on context)
docs need to be written


TikiWiki has 2 search features. One that is based on the mysql fulltext search feature and the other one that is TikiWiki feature. (see http://doc.TikiWiki.org/tiki-index.php?page=Search+Admin (external link) for more details)
First you have to add a fulltext index in the database.
For instance, you have a table

CREATE TABLE contribution (
title varchar(80) default NULL,
body text
) TYPE=MyISAM;

If you want to be able to search on the title and the body field, you will need to add a fulltext index
CREATE TABLE contribution (
title varchar(80) default NULL,
body text,
hits int(8) default NULL,
lastModif int(14) default NULL,
FULLTEXT KEY ft (title ,body)
) TYPE=MyISAM;
Mysql will automatically takes care of the indexation in real time.
You can put as many fields as you want

Notice: if a field is in a wiki format and if you want to index what you see, you will need to have another field that contains the parsed field. Even in this case, you can have some difference (for instance if your field contains a last module format, only the result at indexation time will be indexed). Usually, in TikiWiki we index the field not parsed as.. in IMHO no choice is perfect.

Second, you have to add the search function in lib/searchlib.php


function find_contributions($words = '', $offset = 0, $maxRecords = -1, $fulltext = false) {
static $search_contributions = array(
			'from' => '`tiki_contributions` c,
			'name' => 'c. `title`',
			'data' => 'c. `body`',
			'hits' => 'c. `hits`',
			'lastModif' => 'c. `lastModif`',
			'href' => 'tiki-view_contribution.php?contributionId=%d',
			'id' => array('c. `contributionId`'),
			'pageName' => 'c. `title`',
			'search' => array('c.`title`', 'c.`body`'),

			'permName' => 'tiki_p_view_contribution',
			'objectType' => 'contribution',
			'objectKey' => 'c.`title`',
		);

		return $this->_find($contributions, $words, $offset, $maxRecords, $fulltext);
	}

‘name’ is the column that contains the name of the object
‘search’ must be the list of fields of the mysql fulltext index.

Third, you need to add a call to the function in templates/modules/mod-search_box.tpl

{if $feature_contribution eq 'y'}
    <option value="contributions">{tr}Contributions{/tr}</option>
 {/if}

Also in templates/tiki-searchresults.tpl

{if $feature_contribution eq 'y'}
 <a class="linkbut" href="tiki-searchresults.php?highlight={$words}&amp;where=contributions">{tr}Contributions{/tr}</a>
{/if}
….
 <form class="forms" method="get" action="tiki-searchresults.php">
…..
  {if $feature_articles eq 'y'}
       <option value="contributions">{tr}Contributions{/tr}</option>
    {/if}
</form>
And in tiki-searchresults.php
If ($where == 'contributions' &&  $feature_contribution != 'y') {
$smarty->assign('msg', tra("This feature is disabled").": feature_contribution");
	$smarty->display("error.tpl");
	die;
}


And you need to add the search on this object in the global search. In lib/searchlib.php, you need to update the function find_pages

function find_pages($words = '', $offset = 0, $maxRecords = -1, $fulltext = false) {
….
	if ($feature_contribution == 'y') {
		$rv = $this->find_contributions($words, $offset, $maxRecords, $fulltext);
		foreach ($rv['data'] as $a) {
			$a['type'] = tra('Contribution);
			array_push($data, $a);
		}
		$cant += $rv['cant'];
	}
}


If you data are a little more sophisticated, you can do some join in the search. This is the faqs example

function find_faqs($words = '', $offset = 0, $maxRecords = -1, $fulltext = false) {
		static $search_faqs = array(
			'from' => '`tiki_faqs` f , `tiki_faq_questions` q',
			'name' => 'f. `title`',
			'data' => 'f. `description`',
			'hits' => 'f. `hits`',
			'lastModif' => 'f. `created`',
			'href' => 'tiki-view_faq.php?faqId=%d',
			'id' => array('f. `faqId`'),
			'pageName' => 'CONCAT(f. `title`, ": ", q. `question`)',
			'search' => array('q. `question`', 'q. `answer`'),
			'filter' => 'q. `faqId` = f. `faqId`',
			'permName' => 'tiki_p_view_faqs',
			'objectType' => 'faq',
			'objectKey' => 'f.`title`',

		);

		return $this->_find($search_faqs, $words, $offset, $maxRecords, $fulltext);
	}

NO additional perm checking is needed. The function does the perm checking.

To add a confirmation step

Notice: We consider here only the “Protect against CSRF with a ticket:” feature in admin->login. The “Protect against CSRF with a confirmation step:” was supposed to disappear.


if ($_REQUEST["action"] == 'delete') {
	$area = 'delete_object';
	if ($feature_ticketlib2 != 'y' or (isset($_POST['daconfirm']) and isset($_SESSION["ticket_$area"]))) {
		key_check($area);
		…..delete …
	} else {
		key_get($area);
	}
}

This works only if the delete parameters are passed directly in the url. Key_get losts the parameters passed through a form input. In this case, you have to copy the parameters with the limit of url size (it is why usually the multiple delete has no confirmation step

Here is an example from the multiple remove in admin->users

if ($_REQUEST["submit_mult"] == "remove_users") {
		$area = 'batchdeluser';
		if ($feature_ticketlib2 == 'n' or (isset($_POST['daconfirm']) and isset($_SESSION["ticket_$area"]))) {
			key_check($area);
			foreach ($_REQUEST["checked"] as $deleteuser) {
				$userlib->remove_user($deleteuser);
				$tikifeedback[] = array('num'=>0,'mes'=>sprintf(tra("%s <b>%s</b> successfully deleted."),tra("user"),$deleteuser));
			}
		} elseif ( $feature_ticketlib2 == 'y') {
			$ch = "";
			foreach ($_REQUEST['checked'] as $c) {
				$ch .= "&amp;checked[]=".urlencode($c);
			}
			key_get($area, "", "tiki-adminusers.php?submit_mult=remove_users".$ch);
		} else {
			key_get($area);
		}

  • To protect your application against sea surf(CSRF - XSS)
Each TikiWiki page must include a protection against sea surfing.
For instance tiki-action_object.php

<?php
require_once('tiki-setup.php');
if ($_REQUEST['action_object’]) {
	check_ticket('action_object');
	// execute your action
}
ask_ticket('action_objet');
$smarty->assign('mid', 'tiki-action_object.tpl');
$smarty->display('tiki.tpl');
?>


To create a new module

Modules are the boxes typically found on right & left sides of portal-style sites. They are great to re-use content. In TikiWiki, contrary to similar web applications, modules are typically built-in (bundled) in TikiWiki. You can pick from the list or you can create your own.

To create a new module, the minimum thing you need to do is to create a template file under the templates/modules/ (or templates/styles/your_style/modules/) with a filename beginning with mod- and a .tpl extension.
Example, a contribution module will be
templates/modules/mod-contribution.tpl

{tikimodule title="{tr}Contribution{/tr}" name="contribution flip=$module_params.flip decorations=$module_params.decorations}
  <div align="center">
    My contribution
  </div>
{/tikimodule}

Notice the use of the smarty function tikimodule that will set up the box, the title and the box preferences.

If you need to set up some variables, you need to create a php file
modules/mod-contribution.php

<?php
$smarty->assign('my_contribution_text', 'hello world’);
?>


The template that uses this variable will look like

{tikimodule title="{tr}Contribution{/tr}" name="contribution flip=$module_params.flip decorations=$module_params.decorations}
  <div style="text-align: center">
    {$my_contribution_text}
  </div>
{/tikimodule}

Notice: This is a simplified version. This simple program allows only to have one occurrence of the module (there is only one variable $my_contribution_text. And in 1.9, the modules are computed at the beginning in tiki-setup.php that don’t allow to use variable set in the main program.

If you want to use the parameters that are set up in the admin->modules-> param module line or in the MODULE plugin, you can use

<?php
$smarty->assign('max', $module_params['max']);
?>

where max is either a param of MODULE or a param inserted in the admin->modules->param line.

To create a new plugin

Plugins are an extension to basic wiki syntax. Despite the name, in TikiWiki, contrary to similar web applications, plugins are typically built-in (bundled) in TikiWiki. You can pick from the list or you can create your own.

To create a new plugin, you need to create a file in lib/wiki-plugins/ with a filename beginning with wikiplugin- and an extension .php.
Example
lib/wiki-plugins/wikiplugin-helloworld.php

<?php
//the help function is needed for tw <= 2.0, obsolete for tw>=3.0
function wikiplugin_helloworld_help() {
return tra("To return the text hello world title name").":<br /> ~np~{HELLOWORLD(title=M|Mme|Melle)}name{HELLOWORLD}~/np~ ";
}

//the info function is needed for tw >= 3.0
function wikiplugin_helloworld_info() {
	return array(
		'name' => tra('Helloworld'),
		'documentation' => 'Hello World',
		'description' => tra('Test.'),
		'prefs' => array( 'wikiplugin_helloworld', 'feature_myfeature'),//each plugin can have an admin setting(pref) to enable them
		'body' => tra('explain what the body of the plugin means'),
		'validate' =>true,//add this line if each insertion of plugins needs to be validate by an admin
		'params' => array(
			'title' => array(
				'required' => false,
				'name' => tra('Title'),
				'description' => tra('Describe what title is'),
				),
			),
		);
	}
}

function wikiplugin_helloworld($data, $params) {
     extract ($params, EXTR_SKIP);
     return " ~np~Hello World $title $data!~/np~ ";
}
?>


In a wiki page uses

{HELLOWORLD(title=Mr)}Tiki{HELLOWORLD}

The display will be

Hello World Mr Tiki!


A plugin consists of 2 functions . A help function in tw<= 2.0 , a info funciton in tw >=3.0 and a process function. The name of the functions must be formatted. They begin with wikiplugin_, then the name of the plugin in lower case, then _help for the help function.

In tw <= 2.0, If there is an help function, the help will automatically appear in the wiki help.
The help function returns a string that must be wiki parse-able. You can format how you want the description of the plugin - it needs only to be parseable. Usually, we express the different values of a parameter if the values are limited to a list of values separated by |. In the example, the parameter Title can have the value Mr or Mme or Melle.
In tw >=3.0, If there is an info funciton, the info will automatically appear in the wiki help and prefill the input form.

The process function has 2 parameters, the text inside the tags data and the list of parameters param. The list of parameters are usually extracted with the php extract function. Be careful to use the function EXTR_SKIP for security reason. In our example, the variable $type is set just after the extract call to the value Mr.
Each plugin return is parsed again. So you can add wiki syntax in the plugin return. If you do not want the return to be parsed, you have to enclose the rerunr into ~np~ ... ~/np~

If you have more than one parameter, the wikiplugin use will be

{HELLOWORLD(title=Mr, name=tiki)}Tiki{HELLOWORLD}

the extract function in the php code will set for you all the parameters and you will be able to use $name in the same way you use $title in the php code.

If you want to be clean - of course - you have to test the param has been set

...
function wikiplugin_helloworld($data, $params) {
     extract ($params, EXTR_SKIP);
     if (empty($title))
          return tra("Missing parameter title");
     return "Hello World $title $data!";
....


Now if you want to do more pretty display with smarty, you will use such a code

<?php
.... the help stuff
function wikiplugin_helloworld($data, $params) {
     global $smarty;
     extract ($params, EXTR_SKIP);
     if (empty($name)) return tra('Missing paramter name');
     $smarty->assign_by_ref('name', $name);
     $ret = $smarty->fetch('wiki-plugins/wikiplugin_helloworld.tpl');
     return ' ~np~'.$ret.'~/np~ ';
}
?>

and your tpl file templates/wiki-plugins/wikiplugin_helloworld.tpl

<b>Hello World</b> ($name}


If you want to have a more full fledged plugin, you may want to add an info function

...
function wikiplugin_helloworld_info() {
  return array(
        'name' => tra('HelloWorld'),
        'description' => tra('Greets person'),
        'prefs' => array( 'wikiplugin_helloworld' ),
        'params' => array(
                'name' => 'the name of the person to greet"
                ),
        );
}


the prefs entry will require an appropriate addition in two locations:

in lib/setup/prefs.php

...
'wikiplugin_helloworld' => 'y',


In db/features.csv : (xxxx to be replaced with the latest id in the list +1)

...
xxx,"HelloWorld",913,,"wikiplugin_helloworld","flag", ,"tiki_p_admin",,,,,," "


These two elements shall enable the control of the feature from the admin panel.


Plugin help UI


Please see: PluginUI


Webservice Plugin


Please see: Webservices


A select all checkbox

You have a table and each line is identified by an id
Put if not the table in a form.
You may adapt $objects, $ix to your need
<form>
.....
<table>
.......
{section name=ix loop=$objects}
....
	<input type="checkbox" name="checked[]" value="{$objects[ix].id|escape}" 
	{if $smarty.request.checked and in_array($objects[ix].id,$smarty.request.checked)}checked="checked"{/if} />
....
{/section}
	<xxxxx type="text/javascript"> /* <![CDATA[ */
	document.write('<tr><td colspan="...">
	<input type="checkbox" id="clickall"
 	yyyyy="switchCheckboxes(this.form,\'checked[]\',this.checked)"/>');
	document.write('<label for="clickall">{tr}select all{/tr}</label>
	</td></tr>');
	/* ]]> */</xxxxx>
...
</table>
<div>
{tr}Perform action with checked:{/tr} 
<input type="image" name="delsel" src='pics/icons/cross.png' alt={tr}delete{/tr}' title='{tr}delete{/tr}' />
</div>
</form>

replace xxxx with script and yyyy with onclick

In php you test
if (isset($_REQUEST['delsel_x']) && isset($_REQUEST['checked'])) {
	....
	foreach($_REQUEST['checked'] as $id) {
	...
	}
}


To do something specific in a template (ex.: tiki.tpl) conditional to the current item being in a category. Ex.: different header picture.


This is an example how to display in the top page something specific to the categories of the current object
This function is not completly functionnal. It needs that object set a php variable $objectId or $objectid or $objId and $objecType or $section. But if you need you can easily add a $objectId = $forumId for instance in the .php
Tikiwiki>=3.0 this function has been introduced in tikiwiki code and is called if the feature admin->category->'Categories used in tpl' has been set

{if !isset($objectCategoryIds)}
{php}
global $smarty, $section, $objId, $objectId, $objectid, $objectType, $cat_objid, $cat_type, $objectCategoryIds;
global $tikilib; include_once('lib/tikilib.php');
global $categlib; include_once('lib/categories/categlib.php');
if (empty($objectType)) {
    if (!empty($cat_type))
        $objectType = $cat_type;
    elseif (!empty($section))
         $objectType = $section;
    if ($objectType == 'wiki')
         $objectType = 'wiki page';
    elseif ($objectType == 'cms')
         $objectType = 'article';
    elseif ($objectType == 'file_galleries')
         $objectType = 'file gallery';
    elseif ($objectType == 'trackers')
         $objectType = 'tracker';
    elseif ($objectType == 'forums')
         $objectType = 'forum';
}
if (!empty($objectType) && empty($objectId)) {
    if (!empty($objId))
        $objectId = $objId;
    elseif (!empty($objectid))
        $objectId = $objectid;
    elseif (!empty($cat_objid))
        $objectId = $cat_objid;
    elseif (!empty($_REQUEST['galleryId']) && $objectType == 'file gallery')
       $objectId = $_REQUEST['galleryId'];
   elseif (!empty($_REQUEST['trackerId']) && $objectType == 'tracker')
       $objectId = $_REQUEST['trackerd'];
   elseif (!empty($_REQUEST['forumId']) && $objectType == 'forum')
       $objectId = $_REQUEST['forumd'];
   elseif (!empty($_REQUEST['page']) && $objectType == 'wiki page')
       $objectId = $_REQUEST['page'];
}
if (!empty($objectId) && !empty($objectType)) {
    $objectCategoryIds = $categlib->get_object_categories($objectType,$objectId);
    $smarty->assign('objectCategoryIds', $objectCategoryIds);
}
{/php}
{/if}

{*OTHER_TPL {if empty($objectCategoryIds)}{php}global $smarty, $objectCategoryIds;if (!empty($objectCategoryIds)) $smarty->assign('objectCategoryIds', $objectCategoryIds);{/php}{/if} *}

{if (empty($objectCategoryIds) or empty($objectCategoryIds[0]))}
        ......
{elseif $objectCategoryIds[0] eq '13'}
       ......
{/if}

If you are not using the last part in the same template, to uncomment the {*OTHER_TPL *}

Smarty variable you can use in a tpl

{$user}
{$default_group}
{$section}
{$page}
{$prefs} for tikiwiki>=2.0

Escape in smarty

  • In an option we need to escape all textual values like this
<option value={$name|escape}>{$name|escape}</option>

  • In an url, we need to escape all the textual values like this
<a href="xx.php?name={$name|escape:'url'}>{$name|escape}</a>


tikiwiki >=1.10
If you want to write in a template a link to the same page but with an additional parameter or replace the value of the parameter, you can use
<a href="{$smarty.server.PHP_SELF}?{query archive="y"}">LINK</a>


Useful functions to write a script

First begin your script with
include_once('tiki-setup.php');


Then some useful functions - only the minimum of params are given - see the libraries fiels for more option
// create a new group
global $userlib; include_once('lib/userslib.php');
$userlib->add_group($groupName, $description);
(in tw <= 1.9, you need a 3rd param $homePageName that can be '')
//and include them
$userslib->group_inclusion($groupName, $includeGroupName); (where $groupName='Registered' and $includeGroupName='Anonymous' for example)

// create a new user
global $userlib; include_once('lib/userslib.php');
$userlib->add_user($userName, $password, $email);

// create a new forum
global $commentslib; include_once('lib/commentslib.php');
$forumId = $commentslib->replace_forum(0, $forumName, $description);
(in tw <=1.9, the list of parameters is longer
 replace_forum(0, $forumName='', $description='', 'n', 120, 'admin', '', 'n', 'n', 2592000, 'n', 259200, 10, 'lastPost_desc', '', '', 'y', 'y', 'n', 'y', 'y', 'n', 'n', '', 110, '', '', '', 'n', 'n', '', 'n', 'n', 'y', 'y', 'n', 'n', 'n', 'n', 'all_posted', '', '', 'n', 'att_no', 'db', '', 1000000, 0)

// create a new calendar
global $calendarlib; include_once ('lib/calendar/calendarlib.php');
$calendarId = $calendarlib->set_calendar(0, $creatorUser, $calendarName, $description);
(in tw <=1.9, one more parameter is needed
$calendarId = $calendarlib->set_calendar(0, $creatorUser, $calendarName, $description, array('custompriorities'=>'n'));

// assign a user to a group
global $userlib; include_once('lib/userslib.php');
$userlib->assign_user_to_group($userName, $groupName);

// assign perm to an object
global $userlib; include_once('lib/userslib.php');
$userlib->assign_object_permission($groupName, $objectId, $objectType, $permName);
with couple like ($forumId, 'forum'), ($calendarId, 'calendar') and with permName like 'tiki_p_view'



Credits

The documentation is licensed under a Creative Commons Attribution-ShareAlike License.
Author: sylvie g (external link)
Sponsors: Gerhard Brehm, Marc Laporte



Contributors to this page: sylvie2073 points  , philippeback98 points  , mstef18 points  , luci1182 points  , orionrobots37 points  , Jyhem204 points  , nyloth571 points  , gmartin79 points  , mose2298 points  , deprez , mlaporte86 points  , mathsinger15 points  and marclaporte21258 points  .
Page last modified on Friday 01 May, 2009 18:19:10 UTC by sylvie2073 points .

To register

To have an account at this site, please register at Tikiwiki.org (external link), and then use that user name and password to log in here.

This site gets user information from Tikiwiki.org with the InterTiki feature.

Last Comments

  1. more information from sylvie
  2. can not reproduce
  3. i could repeat it
  4. fixed in 2.4 thanks!
  5. seems to work for me

Search a Wiki Page

Exact match

Search Tracker Items Subject

Keywords

The following is a list of keywords that should serve as hubs for navigation within the Tiki development and should correspond to documentation keywords.

Each feature in Tiki has a wiki page which regroups all the bugs, requests for enhancements, etc. It is somewhat a form of wiki-based project management. You can also express your interest in a feature by adding it to your profile. You can also try out the Dynamic filter.

Accessibility (WAI – 508)
Action log 2.x
Administration
Ajax 2.x
Alert 3.x
Articles & Submissions
Backlinks
Backup
Banner
Blog
Bookmark
Browser Compatibility
Cache
Calendar
Category
Charts
Chat
Comment
Communication Center
Compression (gzip)
Consistency
Contacts Address book
Contact us
Content template
Contribution 2.x
Cookie
Copyright
Custom Home (and Group Home Page)
Database independence
Database MySQL
Date and Time
Debugger Console
Directory (of hyperlinks)
Documentation link from Tiki to doc.tikiwiki.org (Help System)
DogFood
Drawing
Dynamic Content
Dynamic Variable
Ephemeride
External Authentication
FAQ
Featured links
File Gallery
Forum
Friendship Network (Community)
Game
Gmap Google maps
Group
Help System
Hotword
HTML Page
i18n (Multilingual, l10n, Babelfish)
Image Gallery
Import-Export
Install
Integrator
Interaction
Inter-User Messages
InterTiki
JS Calendar
Karma
Live Support
Lost edit protection
Magic 3.x
Mail-in
Map with Mapserver
Menu
Meta Tag
Missing features
MindMap 3.x
Mobile Tiki and Voice Tiki
Mods
Module
Mootools 2.x
Multimedia 2.x
MultiTiki
MyTiki
Newsletter
Newsreader
Notepad
OS independence (Non-Linux, Windows/IIS, Mac, BSD)
PDF
Performance Speed / Load
Permission
Poll
Profile Manager
Quicktags
Quiz
Rating
Registration
RSS
Score
Search engine optimization (SEO)
Search
Security
Semantic links
Shoutbox
Site Identity
Slideshow
Smarty Template
Smiley
Spam protection (Anti-bot CATPCHA)
Spellcheck
Spreadsheet
Staging and Approval
Stats
Survey
System log
Tags 2.x
Task
Tell a Friend + Social Bookmarking 2.x
TikiTests 2.x
Theme
Trackers
Trackers (Mirror)
TRIM
User Administration
User Files
User Menu
Watch
WebHelp
Webmail and Groupmail
WebServices 3.x
Wiki 3D
Wiki History, page rename, etc
Wiki plugins extends basic syntax
Wiki syntax text area, parser, etc
Wiki structure (book and table of content)
Workflow (Galaxia Workflow engine)
Workspace
WYSIWYCA
WYSIWYG 2.x
XMLRPC