<?xml version="1.0"?>
<record><wiki id="wiki?page_id=182">
	<page_name>column:legend</page_name>
	<page_id>182</page_id>
	<page_title></page_title>
	<content></content>
	<keywords></keywords>
	<language>en</language>
	<original_page></original_page>
</wiki>
<wiki id="wiki?page_id=183">
	<page_name>advmultiselect</page_name>
	<page_id>183</page_id>
	<page_title></page_title>
	<content></content>
	<keywords></keywords>
	<language>en</language>
	<original_page></original_page>
</wiki>
<wiki id="wiki?page_id=89">
	<page_name>file</page_name>
	<page_id>89</page_id>
	<page_title></page_title>
	<content>==Dynamic select boxes==

To create two select boxes whose one is dependent (slave) of the other (master), we need to use some javascript with Jason.

Create the valuelists.ini:
&lt;code&gt;

;valuelist for the slave
[slaves_list]
__sql__ = &quot;select slave_id, slave_name, master_id from slaves&quot;

; valuelist for the masters
[masters_list]
__sql__ = &quot;select master_id,master_name from masters&quot;
&lt;/code&gt;

fields.ini:
&lt;code&gt;
[master]
vocabulary=masters_list

[slave]
vocabulary=slaves_list
&lt;/code&gt;

delegate class in the table directory :
&lt;code&gt;
...
function block__after_new_record_form(){
echo &lt;&lt;&lt;END
&lt;script language=&quot;javascript&quot;&gt;&lt;!--
var slave_field= document.getElementById(&apos;slave&apos;);
var master_field = document.getElementById(&apos;master&apos;);
END;
// Let&apos;s get all the slaves available.
$app =&amp; Dataface_Application::getInstance();
$query =&amp; $app-&gt;getQuery();
$table =&amp; Dataface_Table::loadTable($query[&apos;-table&apos;]);
$slaves = $table-&gt;getValuelist(&apos;slaves_list&apos;);
$slave_masters = $table-&gt;getValuelist(&apos;slaves_list__meta&apos;);
// Note that the slaves_list__meta valuelist is automatically created
// because we had three columns in the slaves valuelist.
// The first and third columns effectively create a 2nd valuelist
// named &apos;slaves_list__meta&apos;

// $slaves is an array with keys slave_id and values slave_name
// slave_masters is an array with keys slave_id and values master_id

import(&apos;Services/JSON.php&apos;);
$json =&amp; new Services_JSON(); // A JSON encoder to allow us to easily
// convert PHP arrays to javascript arrays.
echo &apos;
var slaves_options = &apos;.$json-&gt;encode($slaves).&apos;;
var slaves_master = &apos;.$json-&gt;encode($slave_masters).&apos;;
&apos;;

echo &lt;&lt;&lt;END
master_field.onchange = function(){
var selected_master = master_field.options[master_field.selectedIndex].value;
slave_field.options.length = 0;
var index = 0;
for ( slave_id in slaves_options){
if ( selected_master == slaves_master[slave_id] ){
slave_field.options[index++] = new Option(slaves_options[slave_id], slave_id);
}
}
};
//--&gt;&lt;/script&gt;
END;
}

// Also place this javascript after an edit record form...
function block__after_edit_record_form(){
return $this-&gt;block__after_new_record_form();
}


&lt;/code&gt; </content>
	<keywords></keywords>
	<language>en</language>
	<original_page></original_page>
</wiki>
<wiki id="wiki?page_id=90">
	<page_name>Dynamic_select_boxes</page_name>
	<page_id>90</page_id>
	<page_title></page_title>
	<content>==Dynamic select boxes==

To create two select boxes whose one is dependent (slave) of the other (master), we need to use some javascript with Jason.

Create the valuelists.ini:
&lt;code&gt;

;valuelist for the slave
[slaves_list]
__sql__ = &quot;select slave_id, slave_name, master_id from slaves&quot;

; valuelist for the masters
[masters_list]
__sql__ = &quot;select master_id,master_name from masters&quot;
&lt;/code&gt;

fields.ini:
&lt;code&gt;
[master]
vocabulary=masters_list

[slave]
vocabulary=slaves_list
&lt;/code&gt;

delegate class in the table directory :
&lt;code&gt;
...
function block__after_new_record_form(){
echo &lt;&lt;&lt;END
&lt;script language=&quot;javascript&quot;&gt;&lt;!--
var slave_field= document.getElementById(&apos;slave&apos;);
var master_field = document.getElementById(&apos;master&apos;);
END;
// Let&apos;s get all the slaves available.
$app =&amp; Dataface_Application::getInstance();
$query =&amp; $app-&gt;getQuery();
$table =&amp; Dataface_Table::loadTable($query[&apos;-table&apos;]);
$slaves = $table-&gt;getValuelist(&apos;slaves_list&apos;);
$slave_masters = $table-&gt;getValuelist(&apos;slaves_list__meta&apos;);
// Note that the slaves_list__meta valuelist is automatically created
// because we had three columns in the slaves valuelist.
// The first and third columns effectively create a 2nd valuelist
// named &apos;slaves_list__meta&apos;

// $slaves is an array with keys slave_id and values slave_name
// slave_masters is an array with keys slave_id and values master_id

import(&apos;Services/JSON.php&apos;);
$json =&amp; new Services_JSON(); // A JSON encoder to allow us to easily
// convert PHP arrays to javascript arrays.
echo &apos;
var slaves_options = &apos;.$json-&gt;encode($slaves).&apos;;
var slaves_master = &apos;.$json-&gt;encode($slave_masters).&apos;;
&apos;;

echo &lt;&lt;&lt;END
master_field.onchange = function(){
var selected_master = master_field.options[master_field.selectedIndex].value;
slave_field.options.length = 0;
var index = 0;
for ( slave_id in slaves_options){
if ( selected_master == slaves_master[slave_id] ){
slave_field.options[index++] = new Option(slaves_options[slave_id], slave_id);
}
}
};
//--&gt;&lt;/script&gt;
END;
}

// Also place this javascript after an edit record form...
function block__after_edit_record_form(){
return $this-&gt;block__after_new_record_form();
}


&lt;/code&gt; 

The 2.0 version has a [http://xataface.com/dox/modules/depselect/latest| depselect module] to produce cascading dynamic select boxes very simply.</content>
	<keywords></keywords>
	<language>en</language>
	<original_page></original_page>
</wiki>
<wiki id="wiki?page_id=86">
	<page_name>site_with_backoffice</page_name>
	<page_id>86</page_id>
	<page_title></page_title>
	<content>==How to build a site with an optional login form==
To publish a public site with data without any need to login to access, here is the code :
&lt;code&gt;
function getPermissions(&amp;$record){
    if ( isAdmin() ) return Dataface_PermissionsTool::ALL();
    else return Dataface_PermissionsTool::READ_ONLY();
} 
&lt;/code&gt;
In this way, you still can login to administrate your data.</content>
	<keywords></keywords>
	<language>en</language>
	<original_page></original_page>
</wiki>
<wiki id="wiki?page_id=93">
	<page_name>Authenticating_Against_the_Joomla!_Users_Table</page_name>
	<page_id>93</page_id>
	<page_title></page_title>
	<content>Xataface is able to use the joomla users table to authenticate against so that, you can allow your users to log into your Xataface application using the same credentials as they use to access your joomla website. Achieving this level of integration requires 2 simple steps :
1 - Set up the [_auth] section of your conf.ini file to reference the joomla users table and the correct username and password columns.
2 - Create a delegate class for the joomla users table to be able to decrypt the password set in the table.
==Configure the conf.ini file==
Joomla users table is named jos_users. So you have to declare this table in the conf.ini file.
&lt;code&gt;[_auth]
users_table = jos_users
username_column = username
password_column = password&lt;/code&gt;
Note that username_column and password_column are very simple...
==Create a delegate class for your users table==
Now we have to create a delegate class for the users table to decrypt the passwords set in joomla.
Joomla uses a custom md5 encryption.
===Joomla encryption===
When a user is setting a password in joomla, the system does several things :
1 - generate a random key containing alphanumeric characters
example : 
&lt;code&gt;8NdiRqLRKLHaNwudJ3InJknsew9sc7pL&lt;/code&gt;
2 - concate the clear entered password with the random key
example : 
&lt;code&gt;password8NdiRqLRKLHaNwudJ3InJknsew9sc7pL&lt;/code&gt;
3 - doing a md5 encryption on the result string
example : 
&lt;code&gt;md5(password8NdiRqLRKLHaNwudJ3InJknsew9sc7pL = f2b1fb3996442db549c1ed1a1eebbfe1&lt;/code&gt;
4 - concate the md5 string with the random key separated by &quot;:&quot;
example :
&lt;code&gt;f2b1fb3996442db549c1ed1a1eebbfe1:8NdiRqLRKLHaNwudJ3InJknsew9sc7pL&lt;/code&gt;
So it&apos;s a great encryption but xataface doesn&apos;t know how to do that.
Here is the utility of the delegate class. We will define a function inside which could compare the entered password in xataface with the joomla stored password.
===Creating the delegate class===
1 - Add a jos_users directory in your directory table
2 - Create a jos_users.php file inside this new directory
===Creating the decrypt password function===
Before posting this code, I would like to thank fantomasdm who created this function.
So here is the code of the function to paste directly in the jos_users delegate class :
&lt;code&gt;&lt;?
class tables_jos_users {
	
function password__serialize($password){

   $app =&amp; Dataface_Application::getInstance(); 
   $query = &quot;SELECT id, gid, block, password, usertype FROM jos_users where username=&apos;&quot;.$_POST[&apos;UserName&apos;].&quot;&apos;&quot;;
   $result = mysql_query($query,$app-&gt;db()) or die(&quot;Query failed&quot; . mysql_error() );

   $line = mysql_fetch_array($result, MYSQL_ASSOC);
   mysql_free_result($result);

   $arraypass=explode(&quot;:&quot;, $linea[&apos;password&apos;]);
   $key=$arraypass[1];
   
   $ret = md5(trim($password).$key).&quot;:&quot;.$key;
   return $ret;
} 
}
?&gt;&lt;/code&gt;
Save your file and test the result.
Enjoy ! ;-)</content>
	<keywords>joomla authentication md5</keywords>
	<language>en</language>
	<original_page></original_page>
</wiki>
<wiki id="wiki?page_id=105">
	<page_name>field__pushValue</page_name>
	<page_id>105</page_id>
	<page_title></page_title>
	<content>[[toc]]

The field__pushValue() delegate class method can be used to transform a field value as entered in the edit form into a format that can be stored in the database..  Sometimes it is the case that we want users to be able to work with data differently than it is stored in the database.

This method should always be accompanied by a corresponding [[field__pullValue]] method which performs the inverse operation and is used to transform the value in the database into a format that can be edited in the edit form.

===Example===

Given a field &apos;&apos;start_ip&apos;&apos; that stores an IP address in the database as an unsigned INT, we want to be able to work with the data on the edit form in a friendlier format - the standard IP address dot notation, so we define pullValue and pushValue methods for the field in the table&apos;s delegate class.

&lt;code&gt;
class tables_ip_blocks {

	/**
	 * @param Dataface_Record $record The record we are pushing the value
	 *		into
	 * @param HTML_QuickForm_element $el The QuickForm widget that we are 
	 *      retrieving the value from.
	 */
	function start_ip__pushValue($record, $el){
		$val = ip2long($el-&gt;getValue());
		if ( $val !== false ){
			return sprintf(&apos;%u&apos;, $val );
		}
		return null;
	}
	
	function start_ip__pullValue($record, $el){
		$val = $record-&gt;val(&apos;start_ip&apos;);
		if ( $val )
			return long2ip($val);
		return $val;
	}
}
&lt;/code&gt;

==References==

* [[Delegate class methods]]
* [[Application Delegate Class]]
* [[http://dataface.weblite.ca/Dataface_Record Dataface_Record API docs]
* [http://xataface.com/documentation/how-to/how-to-define-custom-serialization-for-fields How to define custom serialization for fields] - A how-to document.
</content>
	<keywords>pullValue, pushValue</keywords>
	<language>en</language>
	<original_page></original_page>
</wiki>
<wiki id="wiki?page_id=84">
	<page_name>http://xataface.com/documentation/how-to/site_with_backoffice_How_to_build_a_site_with_a_backoffice_</page_name>
	<page_id>84</page_id>
	<page_title>A site with a backoffice</page_title>
	<content>==A site with a backoffice==
To create a site with a backoffice for the administrator, so that the visitors do not have to log in to read the pages, you add this code in the ApplicationDelegate.php file in the conf directory :
&lt;code&gt;

function getPermissions(&amp;$record){
    if ( isAdmin() ) return Dataface_PermissionsTool::ALL();
    else return Dataface_PermissionsTool::READ_ONLY();
}
 
&lt;/code&gt;
</content>
	<keywords></keywords>
	<language>en</language>
	<original_page></original_page>
</wiki>
<wiki id="wiki?page_id=36">
	<page_name>about</page_name>
	<page_id>36</page_id>
	<page_title>about</page_title>
	<content>==About Xataface==

[[toc]]

Xataface is a flexible and shapable skin that sits on top of MySQL, making it accessible to every-day users. It automatically generates the appropriate forms, lists, and menus for a user to interact with the database without having to know any SQL. 

It is a full-featured Web application framework, and gives developers the flexibility to customize the features and behavior of their application via configuration files (using the simple INI-file syntax), templates, and plug-ins. A generic application with no customizations is completely functional, but the developer is free to customize things at his leisure.

===Who is Xataface for?===

Xataface is for web developers and database administrators who would like to build a front-end for their MySQL database.  However the resulting applications are targeted at non-technical users such as secretaries.

===Requirements===

====Xataface 1.1.x and below:====

* MySQL 3.23+
* PHP 4+

Some advanced features require MySQL version 4.1 or higher.

====Xataface 1.2 and higher====

* MySQL 3.23+
* PHP 5+

Some advanced features require MySQL version 5 or higher.

===At a Glance: Your first App===

# Create a directory for your app.
# Copy the &apos;&apos;xataface&apos;&apos; directory inside your application directory.
# Create a configuration file named &apos;&apos;conf.ini&apos;&apos; in your application directory with your database settings:&lt;code&gt;
[_database]
    host=localhost
    name=mydb
    user=me
    password=mypass

[_tables]
    ; A list of tables to include in your application&apos;s menu
    ; These tables must already exist in your database
    people=Profiles
    news=News Articles
&lt;/code&gt;
# Create an .htaccess file in your application directory to prevent access to your &apos;&apos;conf.ini&apos;&apos; file:&lt;code&gt;
&lt;FilesMatch &quot;\.ini$&quot;&gt;
Deny from all
&lt;/FilesMatch&gt;
&lt;/code&gt;
# Create a PHP script in your application directory as an access point for your app.  We&apos;ll call it &apos;&apos;index.php&apos;&apos;:&lt;code style=&quot;php&quot;&gt;
&lt;?php
// Include the Xataface API
require_once &apos;xataface/dataface-public-api.php&apos;;

// Initialize Xataface framework
df_init(__FILE__, &apos;xataface&apos;);
    // first parameter is always the same (path to the current script)
    // 2nd parameter is relative URL to xataface directory (used for CSS files and javascripts)

// Create a new application
$app =&amp; Dataface_Application::getInstance();

// Display the application
$app-&gt;display()
&lt;/code&gt;
# You&apos;re done.  Your app is ready to use!

This is just the beginning, though.  There is no limit to the customizations you can make on your application.

Read the [http://xataface.com/documentation/tutorial/getting_started Getting Started Tutorial] for more information on developing applications with Xataface.


===Product Comparison===

Xataface fits a niche that is not well covered by existing apps/frameworks.  Xataface is &apos;&apos;&apos;NOT&apos;&apos;&apos;:

* A database administration system like PHPMyAdmin
* Simply a software library/Framework like PHPCake
* Simply a content management system like Drupal
* A code generator

Xataface is a framework, but it is not a typical framework.  Most frameworks require a substantial amount of development before you get a usable application.  Xataface, on the other hand, provides you with a fully-functional application with as little as 4 lines of PHP code.  It doesn&apos;t generate any code so it is easy to maintain your application and expand on it later.

As a development framework, Xataface most closely resembles Django, a python framework for building data-driven applications.  As an application, Xataface most closely resembles Filemaker, a popular relational database that makes it easy for the end user to create layouts and manage their data.

===Features===

====General====

* &apos;&apos;&apos;Out-of-the-box Database Front-end&apos;&apos;&apos; - With as little as 4 lines of PHP code, you can have a full-featured web application for your database.
* &apos;&apos;&apos;Simple, Intuitive User interface&apos;&apos;&apos; - Default application is consistent and simple to use.  There is a &apos;tables&apos; menu, to select a table, and each table has &quot;details&quot;, &quot;list&quot;, and &quot;find&quot; tabs.  Very easy to navigate.
* &apos;&apos;&apos;Powerful configuration options&apos;&apos;&apos; - You can configure your application details (such as widget types) using simple configuration files.
* &apos;&apos;&apos;Extendible&apos;&apos;&apos; - You can modify your application as you see fit using configuration files and PHP delegate classes.
* &apos;&apos;&apos;Hooks&apos;&apos;&apos; - By observing simple conventions you can extend Xataface&apos;s functionality with hooks, triggers, and events.  E.g. add a function that is called after a record is inserted.
* &apos;&apos;&apos;Permissions&apos;&apos;&apos; - Powerful, pluggable permissions system.
* &apos;&apos;&apos;Authentication&apos;&apos;&apos; - Provides login/logout ability.  You just specify which table your users are stored in.
* &apos;&apos;&apos;Relationships&apos;&apos;&apos; - Tell Xataface how your tables are related to one another and it will provide you with more logical functionality for managing your data.
* &apos;&apos;&apos;Themeable&apos;&apos;&apos; - Xataface uses the Smarty template engine as a base, but extends it with some powerful new features such as extendable templates and theming support.
* &apos;&apos;&apos;Modular&apos;&apos;&apos; - There are several add-on modules available to extend the features of Xataface even further, and a simple API for writing your own modules.


====Editing====

* &apos;&apos;&apos;Automatic Form Generation&apos;&apos;&apos; - Automatically generates appropriate web forms to add new records and edit existing records.
* &apos;&apos;&apos;Widgets&apos;&apos;&apos; - Support for many different widget types including text fields, text areas, checkboxes, select lists, html editors, grids, file uploads, and more.
* &apos;&apos;&apos;Configurable&apos;&apos;&apos; - Customize forms using configuration files and delegate classes.
* &apos;&apos;&apos;Personalizable&apos;&apos;&apos; - Show different forms to different users depending on their permissions and preferences.
* &apos;&apos;&apos;Add Related Records&apos;&apos;&apos; - Insert records and automatically track their relationships to other tables.
* &apos;&apos;&apos;Editable Data Grid&apos;&apos;&apos; - Manage your data like a spreadsheet using the DataGrid module.
* &apos;&apos;&apos;Copy&apos;&apos;&apos; - Copy sets of records.
* &apos;&apos;&apos;Update Found Set&apos;&apos;&apos; - Update multiple records with one swipe.
* &apos;&apos;&apos;Fine-grained Permissions&apos;&apos;&apos; - Assign editing permission based on table, record, or field. 
* &apos;&apos;&apos;File uploads&apos;&apos;&apos; - Support for file uploads with storage either in a BLOB field or on the file system.
* &apos;&apos;&apos;Delete&apos;&apos;&apos; - Delete single record or delete the current found set.

====Searching====

* &apos;&apos;&apos;Automatic Find Form&apos;&apos;&apos; - The Xataface find form allows you to search a table on any field.
* &apos;&apos;&apos;Range Searches&apos;&apos;&apos; - Search for records matching values in a certain range (e.g. find all people between the ages of 20 and 30).
* &apos;&apos;&apos;Exact Matching&apos;&apos;&apos; - Search for exact matches.
* &apos;&apos;&apos;Partial Matching&apos;&apos;&apos; - Search for fields that contain a keyword phrase.
* &apos;&apos;&apos;Multi-field search&apos;&apos;&apos; - There is always a simple search field accessible which searches all fields in the current table.  E.g. a search for &quot;Tom&quot; would match any record in the current table that contained the phrase &quot;Tom&quot; in any of its columns.
* &apos;&apos;&apos;Related Record Searches&apos;&apos;&apos; - Find records that contain related records matching a search term.  (E.g. find all people who got an &apos;A&apos; in a particular course).


====Browsing====

* &apos;&apos;&apos;Automatic Details View&apos;&apos;&apos; - Each record has user-friendly details page to browse the contents of the record.
* &apos;&apos;&apos;AJAX Record Tree&apos;&apos;&apos; - Provides optional AJAX record tree to browse the data in your database by relationships.
* &apos;&apos;&apos;Expand for More&apos;&apos;&apos; - Quickly expand a row in list view to see the full record details.
* &apos;&apos;&apos;Drag and Drop Reordering&apos;&apos;&apos; - The details view for a record can be broken up into related sections.  Users can reorder these sections via drag and drop.

====Exporting====

* &apos;&apos;&apos;RSS&apos;&apos;&apos; - Support for RSS 1.0, 2.0 and Atom feeds of any found set.
* &apos;&apos;&apos;XML&apos;&apos;&apos; - Export any found set as XML so that the data can be interchanged with other products (e.g. desktop publishing suites).
* &apos;&apos;&apos;CSV&apos;&apos;&apos; - Export any found set to CSV (comma-separated-value) to open in a spreadsheet application like Excel.
* &apos;&apos;&apos;JSON&apos;&apos;&apos; - Export any found set to JSON.  This feature makes Xataface a good choice for serving the next generation of Web 2.0 AJAX applications.

====Internationalization====

* &apos;&apos;&apos;String Internationalization&apos;&apos;&apos; - Xataface fully supports internationalizing your application.  It provides you with language files to provide translations of all of the strings and labels in your application.
* &apos;&apos;&apos;Dynamic Data Translation&apos;&apos;&apos; - Xataface even allows you to internationalize your existing database data without having to change your database structure.
* &apos;&apos;&apos;Templates&apos;&apos;&apos; - Includes a {translate} tag for Smarty templates to easily translate template text.
* &apos;&apos;&apos;In the background&apos;&apos;&apos; - You can use Xataface to internationalize any PHP/MySQL website without having to make any drastic changes to your existing code.  Just include Xataface as a library and use some of its useful internationalization functions to convert your application into multiple languages.
* &apos;&apos;&apos;Translation Form&apos;&apos;&apos; - If multiple languages are enabled, Xataface provides a simple translation form to translate content between languages.
* &apos;&apos;&apos;Translation Status Tracking&apos;&apos;&apos; - Track the status of translations to mark whether they need to be retranslated.

====Importing====

* &apos;&apos;&apos;Import Filter API&apos;&apos;&apos; - Using delegate classes, it is easy to define an import filter to import any type of data into the database.
* &apos;&apos;&apos;User Preview&apos;&apos;&apos; - User can preview imported data before confirming that he wants to import it.

====History====

* &apos;&apos;&apos;Optional History Support&apos;&apos;&apos; - If history is enabled, all changes made to any data are recorded.
* &apos;&apos;&apos;Undo/Redo Support&apos;&apos;&apos; - Easily revert to an earlier version of a record.
* &apos;&apos;&apos;View Snapshot&apos;&apos;&apos; - Browse previous versions of records.
* &apos;&apos;&apos;View Diffs&apos;&apos;&apos; - View differences/changes between versions of records, similar to a wiki.

====Caching====

* &apos;&apos;&apos;Output cache&apos;&apos;&apos; - Supports output cache that caches output of pages to improve performance dramatically for busy sites.  Cache is automatically refreshed whenever changes are made to tables that are used to generate the page.
* &apos;&apos;&apos;APC Support&apos;&apos;&apos; - If APC (Alternate PHP Cache) is installed, Xataface will automatically use it to cache table configuration information.  This tends to increase performance by about 20%.


====Security====

* &apos;&apos;&apos;Fine-grained permissions&apos;&apos;&apos; - Define permissions to the entire application, a single table, by the record, or by the field.  Each feature has an associated permission that can be allowed or disallowed on a per-user basis.
* &apos;&apos;&apos;Cascading Permissions&apos;&apos;&apos; - You can very restrictive permissions to the application as a whole and then apply more permission permissions to specific tables or fields that you want uses to be able to access.  Table permissions override application permissions.  Field permissions override field permissions.
* &apos;&apos;&apos;Role-based permissions&apos;&apos;&apos; - You can define &quot;&quot;&quot;roles&quot;&quot;&quot; which are sets of permissions that can be assigned to users.
* &apos;&apos;&apos;Extendable Permissions Model&apos;&apos;&apos; - You can easily define your own permissions and roles, extending existing roles, custom for your application.
* &apos;&apos;&apos;Built-in Authentication&apos;&apos;&apos; - It is easy to set up login/logout features for your application.  Just tell Xataface which table you store your user records in, and Xataface will do the rest.
* &apos;&apos;&apos;Password Encryption&apos;&apos;&apos; - Xataface supports and is compatible with most of the standard password encryptions including MD5, SHA1, and MySQL Password.
* &apos;&apos;&apos;Pluggable Authentication&apos;&apos;&apos; - Easy to create your own authentication plugins in case you want to implement your own custom authentication.
* &apos;&apos;&apos;CAS&apos;&apos;&apos; - Module available for the Yale CAS (Central Authentication Service).
* &apos;&apos;&apos;LDAP&apos;&apos;&apos; - LDAP authentication module available.
* &apos;&apos;&apos;HTTP&apos;&apos;&apos; - Optional HTTP login support.  Standard login uses a web-based login form, but you can also use HTTP headers for authentication.

====Relationships====

* &apos;&apos;&apos;Powerful Relationship Model&apos;&apos;&apos; - It is easy to define relationships between your tables using simple configuration files.  Syntax is simple, but the results are powerful.
* &apos;&apos;&apos;Add New Related Record&apos;&apos;&apos; - Create a new record and add it to a parent record&apos;s relationship at the same time. (E.g. create a new &quot;course&quot; record and add it to a teacher&apos;s list of taught courses).
* &apos;&apos;&apos;Add Existing Related Record&apos;&apos;&apos; - Add an existing record to a parent record&apos;s relationship. (e.g. Add an existing course record to a teacher&apos;s list of taught courses).
* &apos;&apos;&apos;Remove related record&apos;&apos;&apos; - Remove a record from a relationship. (e.g. remove a course record from a teacher&apos;s list of taught courses).

====API====

Xataface includes a powerful API to allow you to more efficiently work with your database.

* &apos;&apos;&apos;Data Objects&apos;&apos;&apos; - Provides a simple API to work with database records.  Searching, loading, saving, editing, and deleting records supported.

====Templates====

* &apos;&apos;&apos;Smarty Template Engine&apos;&apos;&apos; - Xataface uses the Smarty template engine as a base, one of the fastest PHP template engines available.
* &apos;&apos;&apos;Template Inheritance&apos;&apos;&apos; - You can create templates that inherit from other templates, and replace the content in specified &quot;slots&quot; of the original template.  This drastically increases template reuse and development productivity.
* &apos;&apos;&apos;Cascading Support&apos;&apos;&apos; - All system templates are stored in the Dataface/templates directory.  Your application can have its own templates directory where you can place templates to override system templates.  All parts of the system can be overridden without modifying the original templates themselves.

====Themes====

Xataface includes a powerful themes API.  You can create multiple looks for your application and switch between them with a simple configuration setting.

====REST Support====

Xataface&apos;s intelligent URL protocols make it a powerful platform for REST web services.  You can specify a query directly in the URL to obtain the exact found-set that you want.  This is also very useful in standard web applications because you can easily create links to desired parts of your application.  Or you can use Xataface to provide missing functionality in your existing applications and link only to the parts of your Xataface app that you need.

===History===

Xataface (formerly Dataface) was originally created by Steve Hannah in 2005 to increase productivity created data-driven applications for Simon Fraser University.  He came from faculty that used Filemaker extensively for their databases.  As a PHP developer he preferred open technologies like MySQL as they provided fewer &quot;road blocks&quot;, but it was hard to deny the benefits of filemaker when it came to providing users with an instant user interface for their databases.  It was difficult to justify spending 3 weeks building an administration console for a MySQL application when it could have been done in 3 hours had Filemaker been used.

Xataface was designed to:

# Increase developer productivity to the point where MySQL applications could be created as quickly as Filemaker applications without sacrificing usability and functionality.
# Add an abstraction over a database to make is accessible to non-technical users.  The secretary shouldn&apos;t need to know SQL in order to interact with a database.
# Test the limits of PHP and MySQL

As it was built with the intention of providing an alternative for Filemaker, many implementation details and concepts have been inspired by Filemaker.  For example, Xataface&apos;s implementation of relationships is very similar to Filemaker relationships; as are valuelists.  In addition the method of searching follows many Filemaker conventions.

The first application built with Xataface was a group content management system for the Faculty of Applied Sciences at Simon Fraser University.  This system was used by faculty to manage their research profiles and their research groups.  The database itself pre-existed the Xataface implementation.   Xataface was used to build a new administrative interface to the system.  Since then Xataface has been used to develop many systems for SFU including website content management systems, auctions, event registration systems, research databases, shopping carts, and more.

==Where to go from here==

* [http://xataface.com/documentation/tutorial/getting_started Getting Started Tutorial]
* [http://xataface.com/videos Watch Demonstration Videos of Xataface]
* Sign up for the Xataface Maillist to receive free updates and development tips.  (See sign-up form in upper left of the page).</content>
	<keywords></keywords>
	<language>en</language>
	<original_page>0</original_page>
</wiki>
<wiki id="wiki?page_id=6">
	<page_name>actions.ini_file</page_name>
	<page_id>6</page_id>
	<page_title>actions.ini_file</page_title>
	<content>==actions.ini file Reference==

[[toc]]

The actions.ini file stores information about the various [[action]]s that can be performed by your application.  An action may be manifested in two ways:

# As a web page
# As a menu item

And there is no reason why an action cannot serve in both capacities simultaneously.  All menu items and functions that Xataface performs are defined in the Xataface actions.ini file (in the root of the Xataface installation dirctory).  You can also create an actions.ini file in your application&apos;s root directory to override existing Xataface actions, or to create your own.  If you want to modify an existing action instead of overriding it, you can use this syntax.

&lt;code&gt;
[browse &gt; browse]
	label = Browse
&lt;/code&gt;

The &amp;gt; symbol simply means to inherit from the existing browse action.  All the attributes are the same, and we just override the label to Browse (originally was Details)

Additionally, for actions that pertain only to a single table, an actions.ini file may be placed in any [[table configuration directory]].

===Syntax===

As with the [[fields.ini file]] and the [[valuelists.ini file]], the actions.ini file uses the simple [[INI file syntax]] to define its actions.  Each action is defined in its own section, and can have a number of directives to specify the action&apos;s behavior.

Here is a snippet from the Xataface actions.ini file to give you an idea:

&lt;code&gt;
;; Show the details of the current record
[browse]
	label = Details
	category = table_tabs
	url = &quot;{$this-&gt;url(&apos;-action=view&apos;)}&quot;
	accessKey = &quot;b&quot;
	mode = browse
	permission = view
	order=0

;; Show a list of the records in the current found set
[list]
	label = List
	category = table_tabs
	url = &quot;{$this-&gt;url(&apos;-action=list&apos;)}&quot;
	accessKey = &quot;l&quot;
	mode = list
	template = Dataface_List_View.html
	permission = list
	order=0.5

;; Show a &quot;Find Record Form&quot;
[find]
	label = Find
	category = table_tabs
	url = &quot;{$this-&gt;url(&apos;-action=find&apos;)}&quot;
	accessKey = &quot;f&quot;
	mode = find
	permission = find
	template = Dataface_Find_View.html
	order=0.75
&lt;/code&gt;

This snippet shows the definition of the browse, list, and find actions - three of the most central actions in a Xataface application.  Notice how each action has its own section (according to [[INI file syntax]]) with a number of directives which specify how the action behaves.  For instance, each action has a &quot;category&quot; value of &quot;table_tabs&quot;, which tells Xataface to display the actions as part of the table tabs in the user interface.

===Directives===

{| class=&quot;listing listing2&quot;
|-
! Name
! Description
! Version
|-
| [[action allow_override|allow_override]]
| An optional directive to indicate that this action can be overridden by more specific directives in another ini file.  Currently there is only support for a value of &quot;relationships.ini&quot; indicating that the settings can be overridden in the relationships.ini file.  In order for this to work, related=1 must also be set.
| 1.3rc4
|-
| [[action label|label]]
| The label to display if the action is used as a menu item.
| all
|-
| [[action category|category]]
| The name of the action&apos;s category which can be used to group this action together with other similar actions to be used in a menu in the user interface.
| all
|-
| [[action url|url]]
| If the action appears as a menu item, this is the URL that the menu item points to.  This may contain PHP expressions inside curly braces.
| all
|-
| [[action accessKey|accessKey]]
| The key code to automatically select this action if it is included as a menu item.  I.e. ALT+accessKey calls the action.
| all
|-
| [[action mode|mode]]
| This indicates which tab of the table tabs (find, details, list, etc...) that this action should appear to be part of when the action is viewed as a web page.  If this is left undefined, or it does not match any existing visible action in the table tabs, then no tab will appear to be selected.
| all
|-
| [[action permission|permission]]
| The name of a permission required to both see the action as part of a menu and to access the action as a web page.
| all
|-
| [[action visible|visible]]
| A boolean value indicating whether the action should be visible as a menu item.
| all
|-
| [[action condition|condition]]
| A boolean value or a PHP expression evaluating to a boolean value to indicate whether the action should be visible as a menu item.
| all
|-
| [[action url_condition|url_condition]]
| A PHP expression evaluating to a boolean value to indicate whether the URL directive should be evaluated.  This basically checks to make sure that its OK to evaluate the &quot;url&quot; expression, just in case the current state of affairs would cause it to throw a fatal error.
| all
|-
| [[action order|order]]
| A numeric value indicating the order in which the action should be displayed as part of a menu.  Low numbers result in higher placement in the menu.
| all
|-
| [[action icon|icon]]
| The path to an icon that should be used when the action appears as a menu item.
| all
|-
| [[action template|template]]
| The path to the template that should be used when the action is displayed as a web page.
| all
|-
| [[action description|description]]
| Mouseover text for the action (when displayed as a menu item).
| all
|}

===PHP Expression Context===

Notice that the [[action url|url]], [[action condition|condition]], and [[action url_condition|url_condition]] directives allow you to use a PHP expression for their values.  In order for this to be helpful, you should know a little bit about the context and environment in which these expressions will be executed.  All expressions are evaluated immediately prior to being rendered, so the same action can be displayed multiple times in the same page, but have very different resulting values for their [[action url|urls]] and [[action condition|conditions]].

These expressions are all executed within the context of the Dataface_Application::parseString() method, with the following variables loaded in the local symbol table (i.e. you can use the following variables in your expressions).

{| class=&quot;listing listing2&quot;
|-
! Name
! Description
! Version
|-
| [[action context:site_url|$site_url]]
| The URL to the current application&apos;s directory (not including &quot;index.php&quot;)
| all
|-
| $site_href
| The URL to the current application including &quot;index.php&quot;
| all
|-
| $dataface_url
| The URL to the xataface installation directory.
| all
|-
| $table
| The name of the current table (i.e. the value of the &quot;-table&quot; request parameter&quot;
| all
|-
| $query
| An associative array of the current query variables.
| all
|-
| $app
| A reference to the current Dataface_Application object.  Alias of &quot;$this&quot;
| all
|-
| $resultSet
| A reference to the Dataface_QueryTool object for the current query.
| all
|-
| [[action context:record|$record]]
| A reference to the current Dataface_Record object.
| all
|-
| [[action context:context|$context]]
| An associative array of context variables that are passed to the action from the context in which the action is called.
| all
|}</content>
	<keywords></keywords>
	<language>en</language>
	<original_page>0</original_page>
</wiki>
<wiki id="wiki?page_id=123">
	<page_name>afterCopy</page_name>
	<page_id>123</page_id>
	<page_title>afterCopy Delegate class Method</page_title>
	<content>Return to [[Delegate class methods]]

[[toc]]

===Synopsis===

A delegate class method that will be executed after a record is copied using the copy set or copy selected function.  All xataface copies are shallow which means that related records are not copied by default.  If you want a more complex copy function for a table you can implement functionality in this hook.

Available since version 1.3

===Signature===
&lt;code&gt;
function afterCopy( Dataface_Record $original, Dataface_Record $copy);
&lt;/code&gt;

===Parameters===

* &apos;&apos;&apos;$original&apos;&apos;&apos; - The original record that was copied.
* &apos;&apos;&apos;$copy&apos;&apos;&apos; - The resulting copied record.

===Returns===

* Either return nothing or you may return a PEAR_Error object to indicate that an error occurred with the copy.

==See Also==

* [[beforeCopy]] - The beforeCopy hook that can be implemented in the delegate class to run just before a record is copied.
</content>
	<keywords>afterCopy, copy record hook</keywords>
	<language>en</language>
	<original_page></original_page>
</wiki>
<wiki id="wiki?page_id=14">
	<page_name>afterRegister</page_name>
	<page_id>14</page_id>
	<page_title>afterRegister</page_title>
	<content>==afterRegister() Trigger==

A trigger that can be implemented in the [[Application Delegate Class]] or the [[Table Delegate Class]], to be executed after the registration form is saved.  This can be used to perform some custom actions like emailing the administrator.

===Signature===

function afterRegister( Dataface_Record &amp;$record ) : mixed

====Parameters====

{| class=&quot;listing listing2&quot;
! Name
! Description
|-
| &amp;$record
| A Dataface_Record object encapsulating the record that is being inserted in the users table for this registration.
|-
| returns
| Mixed. If this method returns a PEAR_Error object, then registration will fail with an error.
|}

===Example===

&lt;code&gt;
&lt;?php
class conf_ApplicationDelegate {
    function afterRegister(&amp;$record){
        // mail the admin to let him know that the registration is occurring.
        mail(&apos;admin@example.com&apos;, &apos;New registration&apos;, &apos;A new user &apos;.$record-&gt;val(&apos;username&apos;).&apos; has registered);
    }
}
&lt;/code&gt;

===See Also===

* [[beforeRegister]]
* [[validateRegistrationForm]]
* [[sendRegistrationActivationEmail]]
* [[getRegistrationActivationEmailInfo]]
* [[getRegistrationActivationEmailSubject]]
* [[getRegistrationActivationEmailMessage]]
* [[getRegistrationActivationEmailParameters]]
* [[getRegistrationActivationEmailHeaders]]</content>
	<keywords></keywords>
	<language>en</language>
	<original_page>0</original_page>
</wiki>
<wiki id="wiki?page_id=181">
	<page_name>after_action_activate</page_name>
	<page_id>181</page_id>
	<page_title>after_action_activate Delegate Class Method</page_title>
	<content>Return to [[Application Delegate Class]]

[[toc]]


The &apos;&apos;&apos;after_action_activate&apos;&apos;&apos; hook is a method that can be defined in the [[Application Delegate Class]] which is called after an account has been activated via the registration process.  The full registration process goes as follows:

# User fills in registration form.
# An email is sent to the user with a link to activate their account.
# User clicks on activation link.
# User is taken back to the application and activation occurs, which consists of creating a new record in the &apos;&apos;&apos;users&apos;&apos;&apos; table.
# The &apos;&apos;after_action_activate&apos;&apos; trigger is called.

===Since===

This hook has been available since Xataface Version 1.2

===Example===

&lt;code&gt;
/**
 * A trigger to send the user a confirmation email after their account has been activated.
 * @params array $params Associative array of passed parameters.  Contains a single key &apos;record&apos;
 * with the Dataface_Record object of the users table with the user that was activated.
 */
function after_action_activate(array $params){
    $user = $params[&apos;record&apos;];
    
    mail($user-&gt;val(&apos;email&apos;), &apos;Your account is activated&apos;, &apos;Your account has been activated... etc..&apos;);
}
&lt;/code&gt;

===See Also===

* [[Application Delegate Class]]
* [[registration_form]] - More information user registration forms.
* [[beforeRegister]] - Trigger called before the user registration form is saved.
* [[afterRegister]] - Trigger called after registration form is saved.
* [[validateRegistrationForm]] - Validates the input into the registration form.
* [[sendRegistrationActivationEmail]] - Overrides the sending of the registration activation email.
* [[getRegistrationActivationEmailInfo]] - Overrides the activation email info.  Returns an associative array of the email details (e.g. subject, to, headers, etc...
* [[getRegistrationActivationEmailSubject]] - Returns the subject of the activation email.
* [[getRegistrationActivationEmailMessage]] - Returns the message body for the activation email.
* [[getRegistrationActivationEmailParameters]] - Returns the parameters for the actication email.
* [[getRegistrationActivationEmailHeaders]] - Returns the headers for the activation email.
</content>
	<keywords>Registration, activation, register, activate, users</keywords>
	<language>en</language>
	<original_page></original_page>
</wiki>
<wiki id="wiki?page_id=33">
	<page_name>after_action_new</page_name>
	<page_id>33</page_id>
	<page_title>after_action_new</page_title>
	<content>==after_action_new trigger==

[[toc]]

This trigger is called after the &apos;&apos;&apos;new&apos;&apos;&apos; action is successfully completed.  This trigger can be defined in the table [[Delegate class methods|delegate class]] and is often used to redirect to a particular page after a new record is submitted.  This should not be confused with the [[afterInsert]] trigger, which is executed after a record is inserted into the database (this can occur multiple times per request).  The after_action_new trigger is only executed once after the &apos;new&apos; action has been successfully completed.  i.e. a maximum of once per request.

===Signature===

&lt;code&gt;
function after_action_new($params=array()){ ... } : return void
&lt;/code&gt;

====Parameters====

This method takes a single associative array as a parameter. This array includes the following keys:

* &apos;&apos;&apos;record&apos;&apos;&apos; - The [http://dataface.weblite.ca/Dataface_Record Dataface_Record] object that was just inserted.


===Examples===

====Example 1: Redirect to the view tab for the inserted record====

&lt;code&gt;
function after_action_new($params=array()){
    $record =&amp; $params[&apos;record&apos;];
    header(&apos;Location: &apos;.$record-&gt;getURL(&apos;-action=view&apos;).&apos;&amp;--msg=&apos;.urlencode(&apos;Record successfully inserted.&apos;));
    exit;
}
&lt;/code&gt;
</content>
	<keywords></keywords>
	<language>en</language>
	<original_page>0</original_page>
</wiki>
<wiki id="wiki?page_id=12">
	<page_name>Application_Delegate_Class</page_name>
	<page_id>12</page_id>
	<page_title>Application Delegate Class</page_title>
	<content>[[toc]]

===Synopsis===

The application delegate class is similar to the [[Delegate_class_methods|table_delegate_class]] except that it is applicable to the application as a whole, not just one table.  It allows the developer to implement hooks that will be executed by Xataface to modify behavior.

Examples of customizations that can be made with the Application Delegate class include:

* Permissions
* User Preferences
* Custom content to be inserted into templates.
* Triggers
* more.

===Location===

The delegate class is optional and should be located in the conf/ApplicationDelegate.php file in the application directory.

===Example===

&lt;code&gt;
&lt;?php
class conf_ApplicationDelegate {
   function getPermissions(&amp;$record){
       return Dataface_PermissionsTool::NO_ACCESS();
   }
}
&lt;/code&gt;

===Available Methods===

====Triggers====
{| class=&quot;listing listing2&quot;
! Name
! Description
! Version
|-
| after_action_activate
| Trigger called after activation is complete.  Activation occurs after a user registers and responds to the registration confirmation email.
| 1.2.5
|-
| after_action_login
| Trigger called after a user logs in
| 1.0
|-
| after_action_logout
| Trigger called after a user logs out
| 1.0
|-
| after_action_edit
| Trigger called after the edit action completes.
| 1.0
|-
| after_action_new
| Trigger called after new action completes.
| 1.0
|-
| after_action_delete
| Trigger called after the delete action completes.
| 1.0
|-
| [[after_action_activate]]
| Trigger called after successfully email validation (after registering).
| 1.2
|-
| [[before_authenticate]]
| Trigger called just before authentication is carried out.  This allows you to change the authentication type based on such things as SESSION variables etc...
| 1.2.5
|-
| [[beforeHandleRequest]]
| Trigger called on each page request immediately before the action handler is called.  This is handy if you need to perform some action on each page request, such as changing the default action depending on the logged in user.
| 1.0
|-
| [[loginFailed]]
| Trigger called after a failed login attempt.  Allows you to provide your own logging.
| 2.0.1
|-
| [[startSession]]
| If implemented, this overrides how Xataface starts its sessions.  If you implement this method, your custom method should at least include a call to [http://php.net/session_start session_start].
| 1.2.5
|}

====Preferences====

{| class=&quot;listing listing2&quot;
! Name
! Description
! Version
|-
| getPreferences
| Returns the user preference settings.
| 0.6
|}


====Permissions====

{| class=&quot;listing listing2&quot;
! Name
! Description
! Version
|-
| getPermissions
| Returns the permissions available for a given record.
| 0.6
|-
| getRoles
| Returns the roles allowed for a given record.
| 1.0
|-
| __field__permissions
| Returns the default permissions for a field of a given record.
| 1.0
|-
| __field__roles
| Returns the default roles for a field of a given record.
| 1.0
|-
| fieldname__permissions
| Returns the permissions that are allowed for the field &quot;fieldname&quot; on a given record.
| 0.7
|-
| fieldname__roles
| Returns the roles that are allowed for the field &quot;fieldname&quot; on a given record.
| 1.0
|-
| rel_relationshipname__permissions
| Returns the permissions pertaining to the relationship &apos;&apos;relationshipname&apos;&apos; on a given record.
| 1.0
|-
| rel_relationshiopname__roles
| Returns the role or roles pertaining to the relationship &apos;&apos;relationshipname&apos;&apos; on a given record.
| 1.0
|}

See [[permissions]] for more information about Xataface&apos;s permissions architecture and how to implement custom application permissions.

&lt;nowiki&gt;&lt;a name=&quot;registration&quot;&gt;&lt;/a&gt;&lt;/nowiki&gt;
====Registration====

{| class=&quot;listing listing2&quot;
! Name
! Description
! Version
|-
| [[beforeRegister]]
| Trigger called before the user registration form is saved.
| 1.0
|-
| [[afterRegister]]
| Trigger called after registration form is saved.
| 1.0
|-
| [[validateRegistrationForm]]
| Validates the input into the registration form.
| 1.0
|-
| [[sendRegistrationActivationEmail]]
| Overrides the sending of the registration activation email.
| 1.0
|-
| [[getRegistrationActivationEmailInfo]]
| Overrides the activation email info.  Returns an associative array of the email details (e.g. subject, to, headers, etc...
| 1.0
|-
| [[getRegistrationActivationEmailSubject]]
| Returns the subject of the activation email.
| 1.0
|-
| [[getRegistrationActivationEmailMessage]]
| Returns the message body for the activation email.
| 1.0
|-
| [[getRegistrationActivationEmailParameters]]
| Returns the parameters for the actication email.
| 1.0
|-
| [[getRegistrationActivationEmailHeaders]]
| Returns the headers for the activation email.
| 1.0
|-
| [[after_action_activate]]
| Trigger fired after activation is complete.
| 1.2
|}

See [[registration form]] for more information about Xataface&apos;s registration system and how to allow users to register for an account on your application.

&lt;nowiki&gt;&lt;a name=&quot;password-reset&quot;&gt;&lt;/a&gt;&lt;/nowiki&gt;
====Forgot Password====

{| class=&quot;listing listing2&quot;
! Name
! Description
! Version
|-
| [[getPasswordChangedEmailInfo]]
| Optional method to define the settings for the email that is sent to the user upon successful resetting of their password using the password reset function.  
| 1.3
|-
| [[getResetPasswordEmailInfo]]
| Optional method to define the settings for the email that is sent when a user requests to reset their password.  This step comes before the password changed email as first the user requests a password reset and receives this email.  Then they click a link in this email to reset the password upon which time they receive a second email containing their temporary password.  That email is generated by the [[getPasswordChangedEmailInfo]] method if defined.  If this method is not defined then a generic email predefined in Xataface will be sent instead.
| 1.3
|}




====RSS Feed Customization====
{| class=&quot;listing listing2&quot;
! Name
! Description
! Version
|-
| [[getFeedItem]]
| For RSS Feeds, overrides the defaults and returns an associative array with feed elements for a particular record
| 1.0
|-
| [[getFeed]]
| For RSS feeds, overrides the default feed for a query, returning an array of feed items.
| 1.0
|-
| getFeedSource
| Overrides the default feed source parameter for an RSS feed.
| 1.0
|-
| [[getRelatedFeed]]
| For RSS feeds, overrides the default feed for a related feed.
| 1.0
|-
| getRSSDescription
| Overrides the default generated RSS description for a record.
| 1.0
|}


====Template Customization====
{| class=&quot;listing listing2&quot;
! Name
! Description
! Version
|-
| [[block__blockname]]
| Outputs content that is meant to override a slot or a block named &quot;blockname&quot;.
| 0.6
|-
| [[getNavItem]]
| Overrides the navigation menu item for a particular table.
| 1.3
|-
| [[navItemIsSelected]]
| Overrides the &quot;selected&quot; setting for nav menu items.  This is used by the default implementation of [[getNavItem]].
| 1.3
|-
| [[getTemplateContext]]
| Returns an associative array of variables that should be made available to all templates.
| 1.0
|}

====Output Cache Customization====
{| class=&quot;listing listing2&quot;
! Name
! Description
! Version
|-
| [[getOutputCacheUserId]]
| Returns a unique user id that is used by the output cache to ensure that different users don&apos;t use the same cached page (unless appropriate).   This is generally not necessary as the output cache by default uses a different cache for each user... but in some cases you may want to use a different cache for the same user.
| 2.0
|}

====Valuelist Customization====
{| class=&quot;listing listing2&quot;
! Name
! Description
! Version
|-
| [[valuelist__valuelistname]]
| Defines a valuelist named &apos;&apos;valuelistname&apos;&apos;.
| 0.7
|}
</content>
	<keywords>application delegate class</keywords>
	<language>en</language>
	<original_page>0</original_page>
</wiki>
<wiki id="wiki?page_id=92">
	<page_name>Authenticating_Against_the_PHPBB_Users_table</page_name>
	<page_id>92</page_id>
	<page_title>Authenticating Against the PHPBB Users Table</page_title>
	<content>Return to [[authentication]]

[[toc]]

Xataface is able to use the PHPBB users table to authenticate against so that, you can allow your users to log into your Xataface application using the same credentials as they use to access your PHPBB message forum.  Achieving this level of integration requires 2 simple steps:

# Set up the [[_auth]] section of your [[conf.ini file]] to reference the PHPBB users table and the correct username and password columns.
# Specify the correct encryption on the password column.  This step will be different for different versions of PHPBB.

==PHPBB 2==

PHPBB version 2 and lower simply use MD5 encryption on the password column, which Xataface supports natively via the [[encryption]] directive of the [[fields.ini file]].  Therefore we can set up our Xataface application to authenticate against our PHPBB2 database (&apos;&apos;&apos;assuming that our PHPBB is set up in the same database as our Xataface app&apos;&apos;&apos;) by doing the following:

# Set up the [_auth] section of the [[conf.ini file]] as follows:&lt;code&gt;
[_auth]
users_table = phpbb_users
username_column = username
password_column = user_password
&lt;/code&gt;
# Set up the user_password field to use md5 encryption in the &apos;&apos;tables/phpbb_users/fields.ini&apos;&apos; file &lt;code&gt;
[user_password]
encryption=md5
&lt;/code&gt;

That&apos;s it!  Now you should be able to log into your Xataface application using the username/password from PHPBB.


==PHPBB 3==

PHPBB version 3 and higher uses a custom encryption function for the password column so it is a little more complicated (but not that much).  Step one (the [[conf.ini file]]) is the same as for PHPBB version 2 listed above.  The 2nd part, however, requires us to implement a custom serialization for the user_password field.  So the steps are below:

# Set up the [_auth] section of the [[conf.ini file]] as follows:&lt;code&gt;
[_auth]
users_table = phpbb_users
username_column = username
password_column = user_password
&lt;/code&gt;
# Implement the user_password__serialize() method in your phpbb_users delegate class (i.e. the &apos;&apos;tables/phpbb_users/phpbb_users.php&apos;&apos; file):&lt;code&gt;
&lt;?php
class tables_phpbb_users {
	

	function user_password__serialize($password){
		$itoa64 = &apos;./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz&apos;;
		$sql = &quot;select user_password from phpbb_users where username=&apos;&quot;.addslashes($_POST[&apos;UserName&apos;]).&quot;&apos;&quot;;
		$res = mysql_query($sql, df_db());
		if ( !$res ) throw new Exception(mysql_error(df_db()));
		$row = mysql_fetch_assoc($res);
		mysql_free_result($res);
		$hash = $this-&gt;_hash_crypt_private($password, $row[&apos;user_password&apos;], $itoa64);
		return $hash;
	}
	
	
	/**
	* The crypt function/replacement
	*/
	function _hash_crypt_private($password, $setting, &amp;$itoa64)
	{
		$output = &apos;*&apos;;
	
		// Check for correct hash
		if (substr($setting, 0, 3) != &apos;$H$&apos;)
		{
			return $output;
		}
	
		$count_log2 = strpos($itoa64, $setting[3]);
	
		if ($count_log2 &lt; 7 || $count_log2 &gt; 30)
		{
			return $output;
		}
	
		$count = 1 &lt;&lt; $count_log2;
		$salt = substr($setting, 4, 8);
	
		if (strlen($salt) != 8)
		{
			return $output;
		}
	
		/**
		* We&apos;re kind of forced to use MD5 here since it&apos;s the only
		* cryptographic primitive available in all versions of PHP
		* currently in use.  To implement our own low-level crypto
		* in PHP would result in much worse performance and
		* consequently in lower iteration counts and hashes that are
		* quicker to crack (by non-PHP code).
		*/
		if (PHP_VERSION &gt;= 5)
		{
			$hash = md5($salt . $password, true);
			do
			{
				$hash = md5($hash . $password, true);
			}
			while (--$count);
		}
		else
		{
			$hash = pack(&apos;H*&apos;, md5($salt . $password));
			do
			{
				$hash = pack(&apos;H*&apos;, md5($hash . $password));
			}
			while (--$count);
		}
	
		$output = substr($setting, 0, 12);
		$output .= $this-&gt;_hash_encode64($hash, 16, $itoa64);
	
		return $output;
	}
	
	/**
	* Encode hash
	*/
	function _hash_encode64($input, $count, &amp;$itoa64)
	{
		$output = &apos;&apos;;
		$i = 0;
	
		do
		{
			$value = ord($input[$i++]);
			$output .= $itoa64[$value &amp; 0x3f];
	
			if ($i &lt; $count)
			{
				$value |= ord($input[$i]) &lt;&lt; 8;
			}
	
			$output .= $itoa64[($value &gt;&gt; 6) &amp; 0x3f];
	
			if ($i++ &gt;= $count)
			{
				break;
			}
	
			if ($i &lt; $count)
			{
				$value |= ord($input[$i]) &lt;&lt; 16;
			}
	
			$output .= $itoa64[($value &gt;&gt; 12) &amp; 0x3f];
	
			if ($i++ &gt;= $count)
			{
				break;
			}
	
			$output .= $itoa64[($value &gt;&gt; 18) &amp; 0x3f];
		}
		while ($i &lt; $count);
	
		return $output;
	}

	

}
&lt;/code&gt;</content>
	<keywords>PHPBB, authentication, security, authentication modules</keywords>
	<language>en</language>
	<original_page></original_page>
</wiki>
<wiki id="wiki?page_id=21">
	<page_name>authentication</page_name>
	<page_id>21</page_id>
	<page_title>authentication</page_title>
	<content>==Xataface Authentication==

[[toc]]

Xataface comes with authentication ready to roll out of the box.  With a couple of [[_auth|configuration options]] in the [[conf.ini file]], you can activate the default authentication scheme which uses a table (of your choice) in the database to authenticate against.  It supports [[password encryption]], and even includes a [[registration form]] if you choose to allow registrations for your application.

In addition Xataface&apos;s authentication is pluggable, meaning you can write your own plug-ins to integrate your application with any authentication scheme you choose.  Some authentication modules that already exist include:

* [[CAS Authentication Module|Yale CAS]]
* [[LDAP_or_Active_Directory|LDAP]]
* [[Facebook Authentication Module|Facebook]]
* [[HTTP Authentication Module|HTTP]]

====See Also:====

* [[Writing Custom Authentication Plugins]]
* [[Authenticating Against the PHPBB Users table]]
* [[Authenticating Against the Joomla! Users Table]]

Depending on the complexity of the authentication scheme, these plugins may be easy or complex to create.

===Setting up Basic Authentication===

# Create a table (if you haven&apos;t already) to store your application&apos;s users.  At the bare minimum, this table should have fields to store the username and password (you may call these fields whatever you like).  An example table might be: &lt;code&gt;
CREATE TABLE `users` (
  `username` VARCHAR(32) NOT NULL,
  `password` VARCHAR(32) NOT NULL,
  PRIMARY KEY (`username`)
)
&lt;/code&gt;
# Add the following ([[_auth|_auth section]]) to your [[conf.ini file]]: &lt;code&gt;
[_auth]
     users_table=users
     username_column=username
     password_column=password
&lt;/code&gt;  This tell Xataface which table you are storing your user accounts in, and the names of the username and password columns.
# Add a sample user record to the users table if one does not exist yet.&lt;code&gt;
INSERT INTO `users` (`username`,`password`) VALUES (&apos;steve&apos;,&apos;mypass&apos;)
&lt;/code&gt;
# Load your application in your web browser and you&apos;ll notice a &quot;login&quot; link in the upper right that allows you to log in.


===Using MD5 Encryption for the Password===

It is good practice to perform some type of encryption on passwords that you store in a database, so that they will be safe, even if your server&apos;s security is compromised.  One common form of encryption it MD5.  You can apply encryption to your passwords by defining the &apos;&apos;&apos;encryption&apos;&apos;&apos; property to the &apos;&apos;&apos;[password]&apos;&apos;&apos; field&apos;s section of the users table [fields.ini file]. E.g.
&lt;code&gt;
[password]
    encryption=md5
&lt;/code&gt;

This tells Xataface to save data to the password field of the users table with MD5 encryption.

In order to switch to MD5 encryption with an existing Xataface installation, all un-encrypted (plain text) passwords must be first converted to MD5. There are several ways to do this. One method is to directly convert the passwords in the database with the MySQL MD5 function. This can be done from the command-line or using a tool such as phpMyAdmin. It can also be done solely within Xataface as follows, assuming a small number of users where you either know all of the passwords or are planning to change them:

# Log in to your Xataface application as an existing user with ADMIN-level access.
# Navigate to the users table. If you do not already have a link to it, modify your URL to include &quot;-table=&quot; and the name of your users table.
# While logged in, add the encryption=md5 parameter to the fields.ini file as described above.
# Select each user and re-enter or reset their password. It will now be stored with MD5 encryption.
# After completing the above step for all users, you may log out and log back in to verify the change.

===Limiting Access Based on User===

Authentication and permissions are distinct issues, but they are related.  It is quite common to require a user to log in to access a section of an application.  Permissions can be defined in either the Application delegate class or a table&apos;s delegate class - or both.

As an example, if we want to require users to log in to access our application we could define the following getPermissions() method to our application delegate class:

&lt;code&gt;
&lt;?php
class conf_ApplicationDelegate {
    function getPermissions(&amp;$record){
        // $record is a Dataface_Record object
        $auth =&amp; Dataface_AuthenticationTool::getInstance();
        $user =&amp; $auth-&gt;getLoggedInUser();
        if ( $user ) return Dataface_PermissionsTool::ALL();
        else return Dataface_PermissionsTool::NO_ACCESS();
    }
}
&lt;/code&gt;


===Checking Who Is Logged In===

The [http://dataface.weblite.ca/Dataface_AuthenticationTool Dataface_AuthenticationTool] class handles all of the dirty work of Xataface&apos;s authentication.  It provides public methods to check who is logged in and perform authentication if necessary.  Anywhere inside your Xataface application you can find out who is logged in using one of the following two methods:

* [http://dataface.weblite.ca/getLoggedInUser getLoggedInUser()] - Returns a [http://dataface.weblite.ca/Dataface_Record Dataface_Record] object representing a record from the users table.
* [http://dataface.weblite.ca/getLoggedInUsername getLoggedInUsername()] - Returns a string.

It is quite useful in the getPermissions() method of your delegate classes to find out who is logged in:

&lt;code&gt;
function getPermissions(&amp;$record){
    $auth =&amp; Dataface_AuthenticationTool::getInstance();
    $user =&amp; $auth-&gt;getLoggedInUser();
    if ( $user and $user-&gt;val(&apos;username&apos;) == &apos;shannah&apos; ){
        // Steve is logged in so we give him special permissions
        return Dataface_PermissionsTool::ALL();
    } else {
        // Steve is not logged in so we give only read only permissions
        return Dataface_PermissionsTool::READ_ONLY();
    }
}
&lt;/code&gt;

====Checking Who is Logged In from a Template====

All templates in Xataface have access to the *$ENV* array that contains references to lots of useful information, including the currently logged in user:

* &apos;&apos;&apos;$ENV.user&apos;&apos;&apos; - The user object of the currently logged in user (or null if nobody is logged in).  This is a [http://dataface.weblite.ca/Dataface_Record Dataface_Record] object.
* &apos;&apos;&apos;$ENV.username&apos;&apos;&apos; - The name of the currently logged in user.  A string.

For example:

&lt;code&gt;
&lt;!-- 
     Print &apos;Hello Steve&apos; if Steve is logged in,
     &apos;Hello Helen&apos; if Helen is logged in, or just 
     &apos;Hello&apos; if nobody is logged in. 
--&gt;
Hello {$ENV.username}

&lt;!-- Print some personal user info --&gt;
{if $ENV.user}
    Phone number: {$ENV.user-&gt;val(&apos;phone&apos;)}&lt;br/&gt;
    Email address: {$ENV.user-&gt;val(&apos;email&apos;)}&lt;br/&gt;
{/if}
&lt;/code&gt;
This example presumes that the users table has &apos;phone&apos; and &apos;email&apos; fields.


====See Also:====

* [http://xataface.com/documentation/tutorial/getting_started/permissions Permissions Section of Getting Started Tutorial]
* [http://xataface.com/documentation/how-to/disallow_tables How to disallow access to tables in conf.ini file]
* [http://xataface.com/documentation/how-to/security_filters How to use security filters to hide records from certain users]
* [[LDAP_or_Active_Directory| Using LDAP or Active Directory for Authentication]]
* [[_auth|_auth section directives in conf.ini file]]</content>
	<keywords>authentication, [_auth], CAS Authentication, Authentication Modules, Basic Authentication, Security</keywords>
	<language>en</language>
	<original_page>0</original_page>
</wiki>
<wiki id="wiki?page_id=108">
	<page_name>beforeAddRelatedRecord</page_name>
	<page_id>108</page_id>
	<page_title>beforeAddRelatedRecord Delegate Class Method</page_title>
	<content>Return to [[Delegate class methods]]

[[toc]]

==Synopsis==

The &apos;&apos;beforeAddRelatedRecord&apos;&apos; delegate class method can be implemented in any table&apos;s delegate class.  It will be executed before any related record is added to that table&apos;s relationships.  Since it will be fired for all relationships on the table, you will have to include logic to only execute if the relationship that you are targeting is being added to.

==Method Signature==

&lt;code&gt;
function beforeAddRelatedRecord( Dataface_RelatedRecord $record );
&lt;/code&gt;

==Parameters==

* &apos;&apos;&apos;$record&apos;&apos;&apos; - The [http://dataface.weblite.ca/Dataface_RelatedRecord Dataface_RelatedRecord] object encapsulating the record that is being added to the relationship.

===Returns===

* void - If all is well
* [http://dataface.weblite.ca/Dataface_Error Dataface_Error] object if something went wrong.  

It is quite common to return a permission denied error from this method after doing some checks. e.g.

&lt;code&gt;
function beforeAddRelatedRecord($record){
    if ( /* some checks here */ ){
        return Dataface_Error::permissionDenied(&apos;Sorry you don\&apos;t have permission to do this.&apos;);
    }
}
&lt;/code&gt;

==Examples==

===Example 1: Permission Check===

&lt;code&gt;
function beforeAddRelatedRecord($record){
    if ( $record-&gt;_relationshipName == &apos;program_roles&apos; ){
        // check to make sure that we are allowed to add roles to this program
        $program = df_get_record(&apos;programs&apos;, array(&apos;program_id&apos;=&gt;&apos;=&apos;.$record-&gt;val(&apos;program_id&apos;)));
        if ( !$program ){
            return Dataface_Error::permissionDenied(&quot;Program could not be found&quot;);
        }
        if ( !$program-&gt;checkPermission(&apos;add new related record&apos;, array(
                &apos;relationship&apos; =&gt; &apos;program_roles&apos;
                )
             )
           ){
            return Dataface_Error::permissionDenied(&quot;You don&apos;t have permission to add roles to this program&quot;);
        }
    }
}
&lt;/code&gt;

The above example requires a little bit of context to understand.  This method is defined in the &apos;users&apos; table.  There is a relationship between the &apos;&apos;users&apos;&apos; table and the &apos;&apos;programs&apos;&apos; table called &apos;program_roles&apos;.  It keeps track of the roles that users have with respect to programs.  There is a mirror relationshp in the &apos;&apos;programs&apos;&apos; table that goes to the &apos;&apos;users&apos;&apos; table, also named &apos;&apos;program_roles&apos;&apos;.  Both the &apos;&apos;users&apos;&apos; table and the &apos;&apos;programs&apos;&apos; table contain rel_program_roles__roles() methods to define who can and cannot add to this relationship.  However these don&apos;t discern on the content that is being added to the relationship, so it is still possible that an ineligible program could be added to the relationship via the users table (or vice versa).

So, in the &apos;&apos;users&apos;&apos; table we defined the &apos;&apos;beforeAddRelatedRecord&apos;&apos; above which checks the permissions of the programs table to see if that particular program can be added to this relationship by this user.


==See Also==

* [http://dataface.weblite.ca/Dataface_RelatedRecord Dataface_RelatedRecord API Docs]
* [[Delegate class methods]]
* [http://xataface.com/documentation/tutorial/getting_started/relationships Introduction to Relationships] - from the Getting Started Tutorial
* [[relationships.ini file]] reference
</content>
	<keywords>beforeAddRelatedRecord, Delegate class methods, relationship triggers</keywords>
	<language>en</language>
	<original_page></original_page>
</wiki>
<wiki id="wiki?page_id=124">
	<page_name>beforeCopy</page_name>
	<page_id>124</page_id>
	<page_title>beforeCopy Delegate Class Method</page_title>
	<content>Return to [[Delegate class methods]]

[[toc]]

===Synopsis===

A delegate class method that will be executed before a record is copied using the copy set or copy selected function.  All xataface copies are shallow which means that related records are not copied by default.  If you want a more complex copy function for a table you can implement functionality in this hook.

Available since version 1.3

===Signature===
&lt;code&gt;
function beforeCopy( Dataface_Record $original, array $values);
&lt;/code&gt;

===Parameters===

* &apos;&apos;&apos;$original&apos;&apos;&apos; - The original record that is to be copied.
* &apos;&apos;&apos;$values&apos;&apos;&apos; - Associative array of values that are meant to be changed in the copy.  Keys correspond with column names.

===Returns===

* Either return nothing or you may return a PEAR_Error object to indicate that an error occurred with the copy.

==See Also==

* [[afterCopy]] - The afterCopy hook that can be implemented in the delegate class to run just after a record is copied.
</content>
	<keywords>beforeCopy, copy records</keywords>
	<language>en</language>
	<original_page></original_page>
</wiki>
<wiki id="wiki?page_id=107">
	<page_name>beforeHandleRequest</page_name>
	<page_id>107</page_id>
	<page_title>beforeHandleRequest Application Delegate Class Method</page_title>
	<content>Return to [[Application Delegate Class]]

[[toc]]

===Synopsis===

The beforeHandleRequest method is a very useful hook that can be implemented in an [[Application Delegate Class]] to perform some processing before every request.  

This hook is called after user authentication is taken care of, but before control has been passed to the specific action.  This means that it is possible to do things such as change the current action or adjust query parameters depending on various factors.

===Example Uses===

* To require users to fill agree to license terms before they can visit particular parts of the application.
* To implement custom logging functionality to record user actions
* To change the default action for some or all tables.
* To automatically create user accounts in some cases.
* To change query parameters (e.g. default sorting etc...).

==Examples==

===Example 1: Changing the default action for a particular table===

&lt;code&gt;
class conf_ApplicationDelegate {
	
	function beforeHandleRequest(){
		$app = Dataface_Application::getInstance();
		$query =&amp; $app-&gt;getQuery();
			// Make sure you assign by reference (i.e. =&amp; )
			// for this if you want to make changes to the query
			
		if ( $query[&apos;-table&apos;] == &apos;dashboard&apos; and $app-&gt;_conf[&apos;using_default_action&apos;] ){
			$query[&apos;-action&apos;] = &apos;my_default_action&apos;;
		}
	}
}
&lt;/code&gt;

In the above example, we make use of the Application configuration variable [[using_default_action]] to find out if the request is using the default action.  This flag is set by Xataface if the user hasn&apos;t explicitly declared the action in the URL (i.e. -action has not explicitly been set).


==See Also==

* [[Application Delegate Class]]
* [http://dataface.weblite.ca/Dataface_Application Dataface_Application API Docs]
* [[Xataface URL Conventions]]
* &apos;&apos;&apos;[[Customizing Theme Based on IP Address]]&apos;&apos;&apos; - Article containing an example of using beforeHandleRequest hook.</content>
	<keywords>beforeHandleRequest, Application Delegate</keywords>
	<language>en</language>
	<original_page></original_page>
</wiki>
<wiki id="wiki?page_id=13">
	<page_name>beforeRegister</page_name>
	<page_id>13</page_id>
	<page_title>beforeRegister</page_title>
	<content>==beforeRegister() Trigger==

A trigger that can be implemented in the [[Application Delegate Class]] or the [[Table Delegate Class]], to be executed before the registration form is saved.  This can be used to perform some custom actions like emailing the administrator.

===Signature===

function beforeRegister( Dataface_Record &amp;$record ) : mixed

====Parameters====

{| class=&quot;listing listing2&quot;
! Name
! Description
|-
| &amp;$record
| A Dataface_Record object encapsulating the record that is being inserted in the users table for this registration.
|-
| returns
| Mixed. If this method returns a PEAR_Error object, then registration will fail with an error.
|}

===Example===

&lt;code&gt;
&lt;?php
class conf_ApplicationDelegate {
    function beforeRegister(&amp;$record){
        // mail the admin to let him know that the registration is occurring.
        mail(&apos;admin@example.com&apos;, &apos;New registration&apos;, &apos;A new user &apos;.$record-&gt;val(&apos;username&apos;).&apos; has registered);
    }
}
&lt;/code&gt;

===See Also===

* [[afterRegister]]
* [[validateRegistrationForm]]
* [[sendRegistrationActivationEmail]]
* [[getRegistrationActivationEmailInfo]]
* [[getRegistrationActivationEmailSubject]]
* [[getRegistrationActivationEmailMessage]]
* [[getRegistrationActivationEmailParameters]]
* [[getRegistrationActivationEmailHeaders]]</content>
	<keywords></keywords>
	<language>en</language>
	<original_page>0</original_page>
</wiki>
<wiki id="wiki?page_id=109">
	<page_name>beforeSave</page_name>
	<page_id>109</page_id>
	<page_title>beforeSave Trigger</page_title>
	<content>Back to [[Delegate class methods]]

[[toc]]



===Synopsis===

The beforeSave trigger can be implemented in any table&apos;s [[delegate class|Delegate Class Methods]] to perform functionality that should be run *before* a record of that table is saved.  This is a useful place to insert additional field values depending on the input of the save record form.

This method is called both when records are inserted and when existing records are updated.  Some other triggers include [[beforeInsert]], [[beforeUpdate]], [[afterSave]], [[afterInsert]], and [[afterUpdate]], which do what you might expect.


===Method Signature===

&lt;code&gt;function beforeSave( Dataface_Record $record);&lt;/code&gt;

====Parameters====

# &apos;&apos;&apos;$record&apos;&apos;&apos; - The record that is about to be saved.  This is a [http://dataface.weblite.ca/Dataface_Record Dataface_Record] object.

====Returns====

# [http://dataface.weblite.ca/Dataface_Error Dataface_Error] on failure (if you want to cancel the save).


===Examples===

Given a table named &quot;people&quot;, suppose we wanted to automatically populate a field named &quot;full_name&quot;  with the concatenation of the &quot;first_name&quot; and &quot;last_name&quot; fields.  (Note you could also achieve a similar thing by making a calculated field for &quot;full_name&quot;, but for this example, we assume that we actually want to store this in the database.

We create a beforeSave() trigger that automatically updates the &quot;full_name&quot; field every time the record is saved.

In the &quot;people&quot; table delegate class (i.e. tables/people/people.php)
&lt;code&gt;
class tables_people {
    function beforeSave($record){
        $record-&gt;setValue(&apos;full_name&apos;, 
            $record-&gt;val(&apos;first_name&apos;).&apos; &apos;.$record-&gt;val(&apos;last_name&apos;)
        );
    }
}
&lt;/code&gt;

==See Also==

* [http://www.xataface.com/documentation/tutorial/getting_started/triggers Triggers section of the Xataface Getting Started Tutorial]
</content>
	<keywords>triggers, beforeSave,</keywords>
	<language>en</language>
	<original_page></original_page>
</wiki>
<wiki id="wiki?page_id=102">
	<page_name>before_authenticate</page_name>
	<page_id>102</page_id>
	<page_title>before_authenticate hook</page_title>
	<content>Return to [[Application Delegate Class]]

The &apos;&apos;&apos;before_authenticate&apos;&apos;&apos; hook is a method that can be defined in the [[Application Delegate Class]] which is called before the authentication step occurs on &apos;&apos;&apos;every&apos;&apos;&apos; request (not just on login).  It is meant to be used to perform custom code that may affect the authentication settings.

===Since===

This hook has been available since Xataface Version 1.2.5.

===Example===

&lt;code&gt;
/**
 * Implemented trigger to be called before authentication to set the authentication
 * type to basic.
 */
function before_authenticate(){
    $auth = Dataface_AuthenticationTool::getInstance();
    if ( @$_SESSION[&apos;-login-type&apos;] == &apos;basic&apos; ) $auth-&gt;setAuthType(&apos;basic&apos;);
}
&lt;/code&gt;

In the above example we used a separate action to store the user&apos;s preferred login type in a session variable.  This preference is then applied in the before_authenticate method to override the authentication type.

===Chain Authentication Support===

The most common use of this hook is likely to implement some sort of chain authentication, where authentication methods are attempted until one succeeds. 

===See Also===

* [[Application Delegate Class]]
* [[authentication]] - Overview of Xataface authentication
* [[Writing Custom Authentication Plugins]]
* [[Authenticating Against the PHPBB Users Table]]
* [[LDAP or Active Directory]] - Using LDAP or Active Directory for authentication.
* [http://xataface.com/documentation/tutorial/getting_started/permissions Permissions Section of the Getting Started tutorial]
* [[_auth]] - Directives available in the [[_auth]] section of the [[conf.ini file]].</content>
	<keywords>authentication</keywords>
	<language>en</language>
	<original_page></original_page>
</wiki>
<wiki id="wiki?page_id=55">
	<page_name>blob</page_name>
	<page_id>55</page_id>
	<page_title>blob</page_title>
	<content></content>
	<keywords></keywords>
	<language>en</language>
	<original_page>0</original_page>
</wiki>
<wiki id="wiki?page_id=11">
	<page_name>block__blockname</page_name>
	<page_id>11</page_id>
	<page_title>block__blockname</page_title>
	<content>===Available Blocks===

This is a grep to show the blocks that are defined in Xataface templates:

* Dataface_ActionsMenu.html:actions_menu_head
* Dataface_ActionsMenu.html:actions_menu_tail
* Dataface_Add_Existing_Related_Record.html:before_add_existing_related_record_form
* Dataface_Add_Existing_Related_Record.html:before_add_existing_related_`$ENV.relationship`_form
* Dataface_Add_Existing_Related_Record.html:after_add_existing_related_`$ENV.relationship`_form
* Dataface_Add_Existing_Related_Record.html:after_add_existing_related_record_form
* Dataface_Add_New_Related_Record.html:before_add_new_related_record_form
* Dataface_Add_New_Related_Record.html:before_add_new_related_`$ENV.relationship`_form
* Dataface_Add_New_Related_Record.html:after_add_new_related_`$ENV.relationship`_form
* Dataface_Add_New_Related_Record.html:after_add_new_related_record_form
* Dataface_AjaxEventDetails.html:before_event_details
* Dataface_AjaxEventDetails.html:after_event_details
* Dataface_Delete_Record.html:before_delete_record_form
* Dataface_Delete_Record.html:after_delete_record_form
* Dataface_Edit_Record.html:before_edit_record_form
* Dataface_Edit_Record.html:after_edit_record_form
* Dataface_FindForm.html:findform_before_`$element.field.name`_row
* Dataface_FindForm.html:findform_before_`$element.field.name`_widget
* Dataface_FindForm.html:findform_after_`$element.field.name`_widget
* Dataface_FindForm.html:findform_after_`$element.field.name`_row
* Dataface_FindForm.html:before_findform_table
* Dataface_FindForm.html:findform_before_`$element.field.name`_row
* Dataface_FindForm.html:findform_before_`$element.field.name`_widget
* Dataface_FindForm.html:findform_after_`$element.field.name`_widget
* Dataface_FindForm.html:findform_after_`$element.field.name`_row
* Dataface_FindForm.html:after_findform_table
* Dataface_Find_View.html:before_find_form
* Dataface_Find_View.html:after_find_form
* Dataface_Form_Section_Template.html:before_quickform_table
* Dataface_Import_RelatedRecords.html:before_import_related_records_form
* Dataface_Import_RelatedRecords.html:before_import_related_`$ENV.relationship`_form
* Dataface_Import_RelatedRecords.html:after_import_related_`$ENV.relationship`_form
* Dataface_Import_RelatedRecords.html:after_import_related_records_form
* Dataface_List_View.html:before_result_list
* Dataface_List_View.html:after_result_list
* Dataface_Login_Prompt.html:before_login_form
* Dataface_Login_Prompt.html:after_login_form
* Dataface_Main_Template.html:custom_stylesheets2
* Dataface_Main_Template.html:head
* Dataface_Main_Template.html:body_atts
* Dataface_Main_Template.html:before_body
* Dataface_Main_Template.html:before_header
* Dataface_Main_Template.html:after_header
* Dataface_Main_Template.html:before_search
* Dataface_Main_Template.html:after_search_form_submit
* Dataface_Main_Template.html:after_search
* Dataface_Main_Template.html:before_nav_menu
* Dataface_Main_Template.html:after_nav_menu
* Dataface_Main_Template.html:before_language_selector
* Dataface_Main_Template.html:after_language_selector
* Dataface_Main_Template.html:before_user_status_logged_in
* Dataface_Main_Template.html:after_user_status_logged_in
* Dataface_Main_Template.html:before_user_status_not_logged_in
* Dataface_Main_Template.html:after_user_status_not_logged_in
* Dataface_Main_Template.html:before_personal_tools
* Dataface_Main_Template.html:after_personal_tools
* Dataface_Main_Template.html:before_bread_crumbs
* Dataface_Main_Template.html:after_bread_crumbs
* Dataface_Main_Template.html:before_main_table
* Dataface_Main_Template.html:before_left_column
* Dataface_Main_Template.html:before_record_tree
* Dataface_Main_Template.html:after_record_tree
* Dataface_Main_Template.html:before_nav_menu
* Dataface_Main_Template.html:after_nav_menu
* Dataface_Main_Template.html:before_application_menu
* Dataface_Main_Template.html:after_application_menu
* Dataface_Main_Template.html:after_left_column
* Dataface_Main_Template.html:before_main_column
* Dataface_Main_Template.html:before_message
* Dataface_Main_Template.html:message
* Dataface_Main_Template.html:after_message
* Dataface_Main_Template.html:before_errors
* Dataface_Main_Template.html:error
* Dataface_Main_Template.html:after_errors
* Dataface_Main_Template.html:before_table_tabs
* Dataface_Main_Template.html:before_menus
* Dataface_Main_Template.html:after_menus
* Dataface_Main_Template.html:before_main_section
* Dataface_Main_Template.html:before_recently_viewed
* Dataface_Main_Template.html:after_recently_viewed
* Dataface_Main_Template.html:before_record_content
* Dataface_Main_Template.html:after_record_content
* Dataface_Main_Template.html:after_main_section
* Dataface_Main_Template.html:before_fineprint
* Dataface_Main_Template.html:after_fineprint
* Dataface_Main_Template.html:before_global_footer
* Dataface_Main_Template.html:after_global_footer
* Dataface_Main_Template.html:before_main_section
* Dataface_Main_Template.html:before_recently_viewed
* Dataface_Main_Template.html:after_recently_viewed
* Dataface_Main_Template.html:before_record_content
* Dataface_Main_Template.html:after_record_content
* Dataface_Main_Template.html:after_main_section
* Dataface_NavMenu.html:tables_menu_head
* Dataface_NavMenu.html:tables_menu_tail
* Dataface_NavMenu.html:tables_menu_head
* Dataface_NavMenu.html:tables_menu_tail
* Dataface_New_Record.html:before_new_record_form
* Dataface_New_Record.html:after_new_record_form
* Dataface_Record_Template.html:before_details_controller
* Dataface_Record_Template.html:after_details_controller
* Dataface_Record_Template.html:before_record_heading
* Dataface_Record_Template.html:after_record_heading
* Dataface_Record_Template.html:before_record_tabs
* Dataface_Record_Template.html:before_record_content
* Dataface_Record_Template.html:after_record_content
* Dataface_Record_Template.html:before_record_footer
* Dataface_Record_Template.html:after_record_footer
* Dataface_Registration.html:before_registration_form
* Dataface_Registration.html:after_registration_form
* Dataface_Related_Records_List.html:before_related_`$ENV.relationship`_records_list
* Dataface_Related_Records_List.html:after_related_`$ENV.relationship`_records_list
* Dataface_Remove_Related_Record.html:before_remove_related_record_form
* Dataface_Remove_Related_Record.html:before_remove_related_`$ENV.relationship`_record_form
* Dataface_Remove_Related_Record.html:after_remove_related_`$ENV.relationship`_record_form
* Dataface_Remove_Related_Record.html:after_remove_related_record_form
* Dataface_View_Record.html:before_view_tab_content
* Dataface_View_Record.html:before_record_actions
* Dataface_View_Record.html:after_record_actions
* Dataface_View_Record.html:after_view_tab_content
* Dataface_related_records_checkboxes.html:before_related_`$ENV.relationship`_records_checkboxes
* Dataface_related_records_checkboxes.html:before_related_records_checkboxes
* Dataface_related_records_checkboxes.html:after_related_records_checkboxes
* Dataface_related_records_checkboxes.html:after_related_`$ENV.relationship`_records_checkboxes
* Dataface_set_translation_status.html:before_details_controller
* Dataface_set_translation_status.html:after_details_controller

===Available Slots===

* Dataface_ActionsMenu.html:actions_menu
* Dataface_Add_Existing_Related_Record.html:add_existing_related_`$ENV.relationship`_form
* Dataface_Add_Existing_Related_Record.html:add_existing_related_record_form
* Dataface_Add_New_Related_Record.html:add_new_related_`$ENV.relationship`_form
* Dataface_Add_New_Related_Record.html:add_new_related_record_form
* Dataface_AjaxEventDetails.html:event_details
* Dataface_Delete_Record.html:delete_record_form
* Dataface_Edit_Record.html:edit_record_form
* Dataface_FindForm.html:findform_`$element.field.name`_row
* Dataface_FindForm.html:findform_`$element.field.name`_widget
* Dataface_FindForm.html:findform_`$element.field.name`_row
* Dataface_FindForm.html:findform_`$element.field.name`_widget
* Dataface_Find_View.html:find_form
* Dataface_Import_RelatedRecords.html:import_related_`$ENV.relationship`_form
* Dataface_Import_RelatedRecords.html:import_related_records_form
* Dataface_List_View.html:result_list
* Dataface_List_View_summary.html:result_list
* Dataface_Login_Prompt.html:login_form
* Dataface_Main_Template.html:doctype_tag
* Dataface_Main_Template.html:html_tag
* Dataface_Main_Template.html:html_head
* Dataface_Main_Template.html:html_title
* Dataface_Main_Template.html:dataface_stylesheets
* Dataface_Main_Template.html:custom_stylesheets
* Dataface_Main_Template.html:dataface_javascripts
* Dataface_Main_Template.html:custom_javascripts
* Dataface_Main_Template.html:head_slot
* Dataface_Main_Template.html:html_body
* Dataface_Main_Template.html:global_header
* Dataface_Main_Template.html:search_form
* Dataface_Main_Template.html:language_selector
* Dataface_Main_Template.html:user_status_logged_in
* Dataface_Main_Template.html:user_status_not_logged_in
* Dataface_Main_Template.html:personal_tools
* Dataface_Main_Template.html:bread_crumbs
* Dataface_Main_Template.html:main_table
* Dataface_Main_Template.html:left_column
* Dataface_Main_Template.html:application_menu
* Dataface_Main_Template.html:main_column
* Dataface_Main_Template.html:table_tabs
* Dataface_Main_Template.html:menus
* Dataface_Main_Template.html:main_section
* Dataface_Main_Template.html:record_content
* Dataface_Main_Template.html:fineprint
* Dataface_Main_Template.html:global_footer
* Dataface_Main_Template.html:main_section
* Dataface_Main_Template.html:record_content
* Dataface_Main_Templateold.html:doctype_tag
* Dataface_Main_Templateold.html:html_tag
* Dataface_Main_Templateold.html:html_head
* Dataface_Main_Templateold.html:html_title
* Dataface_Main_Templateold.html:dataface_stylesheets
* Dataface_Main_Templateold.html:custom_stylesheets
* Dataface_Main_Templateold.html:dataface_javascripts
* Dataface_Main_Templateold.html:custom_javascripts
* Dataface_Main_Templateold.html:head_slot
* Dataface_Main_Templateold.html:html_body
* Dataface_Main_Templateold.html:global_header
* Dataface_Main_Templateold.html:search_form
* Dataface_Main_Templateold.html:language_selector
* Dataface_Main_Templateold.html:user_status_logged_in
* Dataface_Main_Templateold.html:user_status_not_logged_in
* Dataface_Main_Templateold.html:personal_tools
* Dataface_Main_Templateold.html:bread_crumbs
* Dataface_Main_Templateold.html:main_table
* Dataface_Main_Templateold.html:left_column
* Dataface_Main_Templateold.html:application_menu
* Dataface_Main_Templateold.html:main_column
* Dataface_Main_Templateold.html:table_tabs
* Dataface_Main_Templateold.html:menus
* Dataface_Main_Templateold.html:main_section
* Dataface_Main_Templateold.html:record_content
* Dataface_Main_Templateold.html:fineprint
* Dataface_Main_Templateold.html:global_footer
* Dataface_Main_Templateold.html:main_section
* Dataface_Main_Templateold.html:record_content
* Dataface_NavMenu.html:tables_menu_options
* Dataface_NavMenu.html:tables_menu_options
* Dataface_New_Record.html:new_record_form
* Dataface_Record_Template.html:record_heading
* Dataface_Record_Template.html:record_content
* Dataface_Record_Template.html:record_footer
* Dataface_Registration.html:registration_form
* Dataface_Related_Records_List.html:before_related_list
* Dataface_Related_Records_List.html:related_`$ENV.relationship`_records_list
* Dataface_Related_Records_List.html:related_records_list
* Dataface_Related_Records_List.html:after_related_list
* Dataface_Remove_Related_Record.html:remove_related_`$ENV.relationship`_record_form
* Dataface_Remove_Related_Record.html:remove_related_record_form
* Dataface_View_Record.html:view_tab_content
* Dataface_View_Record.html:record_actions
* Dataface_View_Record.html:record_search
* Dataface_View_Record.html:`$section.name`_section_content
* Dataface_View_Record.html:record_view_main_section
* Dataface_View_Record.html:`$section.name`_section_content
* Dataface_related_records_checkboxes.html:related_`$ENV.relationship`_records_checkbox_form
* Dataface_related_records_checkboxes.html:related_records_checkbox_form
* global_header.html:site_logo

</content>
	<keywords></keywords>
	<language>en</language>
	<original_page>0</original_page>
</wiki>
<wiki id="wiki?page_id=179">
	<page_name>Cached_permissions</page_name>
	<page_id>179</page_id>
	<page_title>Cached Permissions</page_title>
	<content>==Cached Permissions==

===Introduction===
When you insert a SQL query in your getPermissions function, this will slow down the app dramatically because this function is called by each query. To resolve this problem, it is better to use cached permissions in your /conf/ApplicationDelegate.php or table/table.php.

===Procedure===
Here is an example :
&lt;code&gt;
class tables_mytable {

    private $cachedPerms = null;
    private function _getCachedPerms($param1, $param2, ..., $paramN){
        if ( !isset($this-&gt;cachedPerms) ) {
            $this-&gt;cachedPerms = array();
            // do some stuff
            $res = mysql_query(&quot;select * from foo where bar=1 and param2=&apos;&quot;.addslashes($param2).&quot;&apos;&quot;);
            while ( $row = mysql_fetch_assoc($res) )  $this-&gt;cachedPerms[$row[&apos;fooid&apos;]] = $row;
        }
        return $this-&gt;cachedPerms;
    }

    function getPermissions($record){
        // do some stuff
        $perms = $this-&gt;getCachedPerms($param1, $param2, ..., $paramN);
        return $perms;
    }
}&lt;/code&gt;
Here, getPermissions() will run a db query on its first request, but subsequent requests will just load the cached value.</content>
	<keywords>permissions, cache, quick, query</keywords>
	<language>en</language>
	<original_page></original_page>
</wiki>
<wiki id="wiki?page_id=100">
	<page_name>calendar</page_name>
	<page_id>100</page_id>
	<page_title>Calendar Widget</page_title>
	<content>Back to [[widget:type]]

[[toc]]

===Synopsis===

The calendar widget is the default widget for editing date and datetime fields.  It is javascript pop-up calendar that allows users to select date and time visually.  It can be configured to allow different date and time formats, themes, starting days of the week, and more.

[[image:http://media.weblite.ca/files/photos/calendar_widget.png?max_width=400]]

===Usage===

For DATE and DATETIME fields, the calendar widget is the default widget used, so you need not specify it explicitly in the fields.ini file.  For other types of fields you may designate them to use the calendar widget in the [[fields.ini file]] as follows:

&lt;code&gt;
[my_field]
    widget:type=calendar
&lt;/code&gt;

===Configuration Options===

The calendar widget supports some configuration options that can be set in the [[fields.ini file]].  These options are as follows:

{| class=&quot;listing listing2&quot;
|-
! Name
! Description
! Default
! Version
|-
| [[widget:lang]]
| The language to use for the calendar.  This is a 2-digit ISO language code.
| en
| 0.5.3
|-
| [[widget:theme]]
| The theme to use for the calendar.  It only ships with one theme at present.
| calendar-win2k-2
| 0.5.3
|-
| [[widget:firstDay]]
| The first day of the week  (e.g. Monday=1)
| 1
| 0.5.3
|-
| [[widget:showsTime]]
| Boolean value indicating whether the calendar should show the time as well.
| 0 for DATE fields, 1 for DATETIME fields.
| 0.5.3
|-
| [[widget:ifFormat]]
| The input format of the date.  This takes a formatting string as supported by [http://ca2.php.net/strftime the strftime function].
| %Y-%m-%d %I:%M %P
| 0.5.3
|-
| [[widget:timeFormat]]
| Whether to use 12 hour or 24 hour time format.
| 12
| 0.5.3
|}

===Examples===

====Setting the time to use 24 hour format====

In your [[fields.ini file]]:
&lt;code&gt;
[my_field]
    wiget:type=calendar
    widget:timeFormat = 24
&lt;/code&gt;


===See Also===

* [[date]] Widget - A widget for editing date and time using select drop-down lists.
* [[time]] Widget - A widget for selecting time from a set of possibilities in a single select list.</content>
	<keywords>calendar widget, fields.ini file, widget:type</keywords>
	<language>en</language>
	<original_page></original_page>
</wiki>
<wiki id="wiki?page_id=43">
	<page_name>Calendar_Action</page_name>
	<page_id>43</page_id>
	<page_title>Calendar_Action</page_title>
	<content>==Calendar Action==

[[toc]]

Xataface 1.0 includes a built-in calendar action that is disabled by default.  If enabled, it allows you to view the records in any found set as a calendar of events, as follows:

&lt;nowiki&gt;
&lt;div style=&quot;text-align:center;border: 1px solid #ccc; padding: 10px&quot;&gt;
&lt;img src=&quot;http://media.weblite.ca/files/photos/Picture -4.png?max_width=500&quot;
onmouseover=&quot;this.src=&apos;http://media.weblite.ca/files/photos/Picture -4.png&apos;;&quot;
onmouseout=&quot;this.src=&apos;http://media.weblite.ca/files/photos/Picture -4.png?max_width=500&apos;;&quot;/&gt;
&lt;/div&gt;
&lt;/nowiki&gt;

===Features===

* Monthly display
* Hourly schedule for any day by clicking on it.
* Show record details instantly by clicking on it in the calendar.
* Recognizes dates, start and end times for records when interpreted as calendar events.
* Respects searches (i.e. you can filter the records and the calendar will only show those records in the found set).

===Requirements===

Your table records should contain at least dates in order for them to be interpreted as events that can be placed in a calendar.

===Setting up the Calendar===

Suppose I have a table called &apos;&apos;Lessons&apos;&apos; that stores information about scheduled music lessons.  If I want to add the calendar to this table, then I would add an &apos;&apos;[[actions.ini file]]&apos;&apos; to the &apos;&apos;tables/Lessons&apos;&apos; directory with the following contents:&lt;code&gt;
[calendar &gt; calendar]
    condition=&quot;true&quot;
&lt;/code&gt;
This overrides the calendar action which is disabled by default, and enables it for the &apos;&apos;Lessons&apos;&apos; table.

Next I need to inform Xataface which fields store the event dates and times so that the records can be laid out in the calendar appropriately.  (Note that if you skip this step, Xataface will make a best guess based on column types and names - but it is better to specify these explicitly).

In the &apos;&apos;Lessons&apos;&apos; table I have the following fields that are relevant here:

* &apos;&apos;lesson_date&apos;&apos; - A date field containing the date and start time of the event.
* &apos;&apos;start_time&apos;&apos; - A time field with the start time of the lesson.

We can tell Xataface to treat these fields accordingly by adding the following directives to the appropriate field sections of the [[fields.ini file]] for the &apos;&apos;Lessons&apos;&apos; table:

* &apos;&apos;event.date=1&apos;&apos; - Specifies that the field stores the date of the event.
* &apos;&apos;event.start=1&apos;&apos; - Specifies that the field stores the start time of the event.

So in our case we&apos;ll modify the [[fields.ini file]] as follows:

&lt;code&gt;
[lesson_date]
    event.date=1

[start_time]
    event.start=1
&lt;/code&gt;

Now if we load up our application, we should now see a &apos;&apos;calendar&apos;&apos; tab along side &apos;&apos;list&apos;&apos;, &apos;&apos;details&apos;&apos;, and &apos;&apos;find&apos;&apos; for the &apos;&apos;Lessons&apos;&apos; table.  Click on this tab to see your records displayed in a calendar.

===Using a datetime field to store both date and start time===

You can also use a single field to store both the date and start time for an event.  In this case you just provide the &apos;&apos;event.date&apos;&apos; and &apos;&apos;event.start&apos;&apos; directives for the same field.  For example if the &apos;&apos;lesson_date&apos;&apos; was a datetime field that marked the date and time of the lesson, we would modify our [[fields.ini]] file as follows:

&lt;code&gt;
[lesson_date]
    event.date=1
    event.start=1
&lt;/code&gt;

===Available Fields===

The Calendar action will look for the following pieces of information in your records:

{| class=&quot;listing listing2&quot;
! Name
! Description
! Version
|-
| event.date
| Indicates that the field contains the date of the event.
| 1.0
|-
| event.start
| Indicates that the field contains the start time of the event.
| 1.0
|-
| event.end
| Indicates that the field contains the end time of the event.
| 1.0
|-
| event.location
| Indicates that the field contains the location of the event.
| 1.0
|-
| event.category
| Indicates that the field contains the category of the event.
| 1.0
|}</content>
	<keywords></keywords>
	<language>en</language>
	<original_page>0</original_page>
</wiki>
<wiki id="wiki?page_id=69">
	<page_name>checkbox</page_name>
	<page_id>69</page_id>
	<page_title>checkbox</page_title>
	<content>==The checkbox widget==

In the [[fields.ini file]] you can specify a field to be edited using a checkbox widget by setting [[widget:type]] to [[checkbox]].  A checkbox widget can function in 2 different ways depending on the parameters that you assign to the field.

[[toc]]

===Example 1: A TinyInt (boolean) field===

Suppose our table has a tinyint field named &quot;Active&quot; which specifies whether the record is currently in use.  This field will store a value of either 0 or 1.  So we configure this field in our [[fields.ini]] file to use a checkbox widget as follows:

&lt;code&gt;
[Active]
  widget:type=checkbox
&lt;/code&gt;

Results:

[[Image:http://media.weblite.ca/files/photos/Picture%2024.png?max_width=640]]

===Example 2: A repeating field (multiple checkboxes for one field===

Checkboxes can store multiple values in a single field by setting the [[vocabulary]] directive and applying it to a varchar or text field.  In this case there will be one value saved per line.  

In this example, suppose we have a varchar field named &apos;&apos;&apos;categories&apos;&apos;&apos; which uses the &apos;&apos;&apos;categories&apos;&apos;&apos; [[valuelist]] to specify the different categories that can be checked at any given time.  Our [[valuelists.ini file]] might look like:
&lt;code&gt;
[categories]
    __sql__ = &quot;select id,name from categories&quot;
&lt;/code&gt;

And our [[fields.ini file]] looks like:
&lt;code&gt;
[categories]
    widget:type=checkbox
    vocabulary=categories
&lt;/code&gt;
* Note that you don&apos;t need to name the field the same as the valuelist.  It just worked out this way.

Now if we save a record with categories 1, 3, and 5 checked, then the categories column of our row in the database will store something like:
&lt;code&gt;
1
3
5
&lt;/code&gt;
i.e. one category id per line.  Note that using this method, your database will not be normalized because you are storing multiple values in a single field.  However in many applications this is sufficient.

Results:

[[Image:http://media.weblite.ca/files/photos/Picture%2025.png?max_width=640]]

===Example 3: Using a &quot;Categories&quot; relationship===

&quot;&quot;&quot;(Note: This example requires Xataface version 1.2 or higher)&quot;&quot;&quot;

Example 2 above shows how we can easily add and remove a record from multiple categories using checkboxes.  However it required multiple pieces of information to be stored in a single database field which may or may not be advantageous for your database design.  If you&apos;re looking for a more normalized database schema you would probably design your database as follows for this case:

# Books table - Stores all of the books.
# Categories table - Stores all of the categories
# Book_Categories table - Stores mapping of books to categories.

With out table structure we will first want to define a relationship from Books to Categories to reflect the connection between books and categories.  The [[relationships.ini file]] for this might look like:

&lt;code&gt;
[categories]
    Books.Book_ID=&quot;$Book_ID&quot;
    Book_Categories.Category_ID=Categories.Category_ID
&lt;/code&gt;

And our [[fields.ini file]] for the Books table might look like:
&lt;code&gt;
[categories]
    widget:type=checkbox
    transient=1
    relationship=categories
&lt;/code&gt;
* Note that there is no need for our field to be named the same as our relationship.  It just turned out this way.  Also note that we used the transient=1 flag here because the Books table no longer has a categories field in the database.  This field is defined purely for the benefit of the edit form so that we will get a checkbox group to select the book&apos;s categories.

Results:
[[Image:http://media.weblite.ca/files/photos/Picture%2025.png?max_width=640]]

==Related Parameters==

# [[vocabulary]] - Assigns a valuelist to be used as the options for this checkbox group.
# [[repeat]] - A boolean value indicating whether this field should be treated as a &apos;repeating field&apos;.  A repeating field is one with multiple checkboxes.  By default the checkbox widget operates as a single checkbox that controls a boolean value.
# [[relationship]] - (Only applicable to [[transient]] fields).  If the [[relationship]] directive is set then this field can be used to add/remove records from a relationship.</content>
	<keywords></keywords>
	<language>en</language>
	<original_page>0</original_page>
</wiki>
<wiki id="wiki?page_id=178">
	<page_name>Clean_the_html_for_the_export</page_name>
	<page_id>178</page_id>
	<page_title>Clean the HTML to export data</page_title>
	<content>==Clean HTML tags and entities to export your data==
#Override the display() of the field to strip the tags... but this would affect all parts of the application where the HTML fields are displayed.
#Create a grafted field, then override its display to show the stripped contents of the HTML area field.

e.g. in the fields.ini:

&lt;code&gt; 
    __sql__ = &quot;select t.*, null as stripped_field from mytable t&quot;
    [original_field]
       widget:type=htmlarea
       visibility:csv=hidden

    [stripped_field]
        visibility:csv = visible
        visibility:list=hidden
        visibility:browse=hidden
        visibility:find=hidden

&lt;/code&gt; 


Then in the delegate class:


&lt;code&gt; 
    function stripped_field__display($record){
        return html_entity_decode(strip_tags($record-&gt;val(&apos;original_field&apos;)), ENT_QUOTES, &apos;UTF-8&apos;);
    }
&lt;/code&gt; </content>
	<keywords></keywords>
	<language>en</language>
	<original_page></original_page>
</wiki></record>