(Cached)
Hello World
Table of contents
- Introduction
- Glossary
- Who does what?
- Smarty/PHP
- The 'Hello World' page
- tiki-setup.php
- How to debug and to see the smarty variables
- To execute some queries in the php
- To introduce a new feature or a new preference
- To update the database schema
- To get/set a user preference
- To create a menu or to introduce a menu option
- Menu created by sql
- Menu created with a smarty template
- To introduce a new permission
- To check a permission
- To wiki parse a textarea
- Categories
- Theme control center
- Search
- To add a new object in a mysql search
- To add a confirmation step
- To create a new module
- To create a new plugin
- A select all checkbox
- To do something specific in a template (ex.: tiki.tpl) conditional to the current item being in a category. Ex.: different header picture.
- Smarty variable you can use in a tpl
- Escape in smarty
- Self link in templates
- Useful functions to write a script
- Related links
- Credits
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
, MVC
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
you can realize too late that you made some ridiculous choices and there is no way back.
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
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.
> 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
Alain Désilets wrote:
Glossary
Things are sometimes named a bit differently than in other Web Applications. Please see:http://tikiwiki.org/Glossary
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
Smarty/PHP
TikiWiki uses the Smarty template engineThe PHP
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
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
- ….
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 ADODBA 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"> </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"> </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
DatabaseSchemaUpgradeTo 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)
Menu created by sql
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.
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)
Menu created with the TikiWiki API
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.
Menu created with a smarty template
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
Search
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+AdminTo add a new object in a mysql search
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}&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 .= "&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)
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 idPut 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>Self link in templates
tikiwiki >=1.10If 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 withinclude_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'Related links
- Modularity
- TimeZones
- performance
- How login is done?
- Security
- WebCodingStandards
- mass spelling correction
- External Libraries
- Cia Bot
Credits
The documentation is licensed under a Creative Commons Attribution-ShareAlike License.
Author: sylvie g
Sponsors: Gerhard Brehm, Marc Laporte
Author: sylvie g
Sponsors: Gerhard Brehm, Marc Laporte
Contributors to this page: sylvie
,
philippeback
,
mstef
,
luci
,
orionrobots
,
Jyhem
,
nyloth
,
gmartin
,
mose
,
deprez
,
mlaporte
,
mathsinger
and
marclaporte
.
Page last modified on Friday 01 May, 2009 18:19:10 UTC by sylvie
.
Sidebar
Sidebar
To register
To have an account at this site, please register at Tikiwiki.org
, and then use that user name and password to log in here.
This site gets user information from Tikiwiki.org with the InterTiki feature.
This site gets user information from Tikiwiki.org with the InterTiki feature.
Last Comments