<?xml version="1.0"?>
<record><wiki id="wiki?page_id=30">
	<page_name>modules</page_name>
	<page_id>30</page_id>
	<page_title>Xataface Modules</page_title>
	<content>[[toc]]

Xataface provides a number of hooks that allow developers to create modules to extend its functionality.  This page lists a handful of the currently available modules.

* [[ShoppingCart|Shopping Cart]] - Converts your application into a shopping cart.
* [[Filemaker]] - Export record sets as Filemaker XML.
* [[DataGrid|Data Grid]] - Editable Datagrid.
* [[Email]] - Convert your database into a email list.  Send email to any found set.
* [[reCAPTCHA module]] - A reCAPTCHA module to add CAPTCHA support to your Xataface forms.
* [[XataJax]] - Platform for building Web 2.0 AJAX applications with Xataface.  Will be a standard component for Xataface starting with version 1.3.

==Module Installation==

You can add modules in either:

# DATAFACE_PATH/modules directory (since 1.0)
# DATAFACE_SITE_PATH/modules directory (since 1.3)

Modules in the DATAFACE_SITE_PATH directory will supersede modules in the DATAFACE_PATH/modules directory (since 1.3).

To activate a module for your application you also need to add an entry to the [[_modules]] section of your [[conf.ini file]].  Each module will come with its own installation instructions.

==Authentication Modules==

Modules to add alternative authentication methods are added to the modules/Auth directory.

==Developing Your Own Modules==

See [[Module Developers Guide]].</content>
	<keywords>modules, captcha</keywords>
	<language>en</language>
	<original_page>0</original_page>
</wiki>
<wiki id="wiki?page_id=113">
	<page_name>XataJax</page_name>
	<page_id>113</page_id>
	<page_title>Introduction to XataJax</page_title>
	<content>[[toc]]

Xataface 1.3 comes with a new module [[XataJax]] which comes installed standard.  [[XataJax]] serves as a foundation for Javascript/AJAX powered Xataface applications and will hopefully usher in a new fresh generation of Xataface powered applications.

===Features===

Xataface provides pieces of infrastructure:

# [[XataJax Compiler|A Javascript/CSS Compiler &amp; Linker]]
# A Javascript component library &amp; API

====The Javascript/CSS Compiler &amp; Linker====

Web 2.0 and HTML 5 is a great platform for application development, but it presents a challenge when it comes to developing large-scale, robust applications.  It can be difficult to manage applications that consist of dozens or even hundrends of javascript libraries, some of which depend on each other.

The XataJax compiler provides a solution to this problem by providing a just-in-time compilation of all of the javascripts that are necessary to service a particular request.  It doesn&apos;t actually compile your Javascript into machine code, it just aggregates and minifies all of the javascript code together into a single file at runtime so that you don&apos;t have to worry about figuring out exactly which libraries you need to import in each template.

This has 2 key benefits:

1. Load time.  By having all of the scripts grouped into a single file, it is much quicker for the client to load the your scripts.

2. Code organization.  Since the compiler will automatically resolve the script dependencies, you can keep your code nicely organized, which produces a far more maintainable source code base.


====The Javascript Component Library &amp; API====

The 2nd part of the XataJax module is a new API that will help you develop rich Web 2.0 applications that interact with your database.  The will allow you to build forms more dyanmically with Javascript, or load, update, and delete records directly using a javascript API.  

The goal is to eventually expose all important Xataface functionality via the XataJax API.

Additional modules may build on top of this API to produce alternative dynamic interfaces for Xataface using existing web UI component libraries like JQueryUI or Sencha.</content>
	<keywords>XataJax, Ajax, Web 2.0</keywords>
	<language>en</language>
	<original_page></original_page>
</wiki>
<wiki id="wiki?page_id=184">
	<page_name>loginFailed</page_name>
	<page_id>184</page_id>
	<page_title>loginFailed() Application Delegate Trigger</page_title>
	<content>[[toc]]

The loginFailed() method of the Application Delegate class is executed after a failed login attempt.

&apos;&apos;&apos;Available since 2.0.1&apos;&apos;&apos;

==Example==

&lt;code&gt;
function loginFailed($username, $userIp, $time){
    error_log(&quot;Failed login for username: $username at IP $userIp at time $time&quot;);
}
&lt;/code&gt;
</content>
	<keywords>login permissions failed password</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=104">
	<page_name>field__pullValue</page_name>
	<page_id>104</page_id>
	<page_title>field__pullValue delegate class method</page_title>
	<content>[[toc]]

The field__pullValue() delegate class method can be used to transform database from the database for use in an edit/new record form.  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__pushValue]] method which performs the inverse operation and is used to transform the value in an edit form into a format that can be stored in the database.

===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>pushValue, pullValue</keywords>
	<language>en</language>
	<original_page></original_page>
</wiki>
<wiki id="wiki?page_id=65">
	<page_name>LDAP_or_Active_Directory</page_name>
	<page_id>65</page_id>
	<page_title>How to authenticate users with LDAP or Active Directory</page_title>
	<content>[[toc]]

It is often easier to use the existing LDAP or Active Directory to authenticate users in Xataface than to create a new password for every user in the table users.

===In the conf.ini===

In the conf.ini file, in the [auth] part, you need to add your LDAP or AD configuration data :

&lt;code&gt;[_auth]
auth_type=ldap
users_table = xata_users
username_column = id
	ldap_host = &quot;xxx.xxx.xxx.xxx&quot;
	ldap_port = &quot;389&quot;
	ldap_base = &quot;OU=blabla,DC=blablabla&quot;&lt;/code&gt;

Here in the table users, you need the login but the password can be just &apos;&apos;PASS&apos;&apos;, because the password will be fetched into the LDAP base.
You need to add the [http://weblite.ca/svn/dataface/modules/Auth/ldap/trunk/ auth module] in the conf/modules directory.

===See Also===

* [[authentication]] - Overview of Authenthentication features in Xataface</content>
	<keywords>LDAP,Active Directory,Authentication</keywords>
	<language>en</language>
	<original_page>0</original_page>
</wiki>
<wiki id="wiki?page_id=112">
	<page_name>Module_Developers_Guide</page_name>
	<page_id>112</page_id>
	<page_title>Module Developers Guide</page_title>
	<content>[[toc]]

==Why Write a Xataface Module?==

Xataface modules are components that can be used to extend Xataface&apos;s functionality in a generic way so that it can be used on multiple applications.  If you find yourself trying to add the same functionality in multiple applications, you might consider writing a Xataface module so that you can share the functionality more easily.

==What can you do with a Xataface Module==

* Create custom authentication handlers.
* Provide custom actions and templates.
* Implement blocks and slots for existing templates.
* Respond to certain application triggers.


==Where do I place a Xataface Module?==

Xataface modules can be placed in the xataface/modules directory (i.e. DATAFACE_PATH/modules).  As of Xataface 1.3 they can also be placed directly in your application&apos;s modules directory (i.e. DATAFACE_SITE_PATH/modules).

==Your first module==

For our first module, we&apos;re going to create a simple module that adds &quot;hello world&quot; at the beginning of every page.

===Step 1: Create the Module Class===

In your modules directory, create a directory called &quot;Hello&quot;.  And in this directory, create a file named &quot;Hello.php&quot;, with the following contents:
&lt;code&gt;
&lt;?php
class modules_Hello  {
}
&lt;/code&gt;
(So this file would be located at DATAFACE_PATH/modules/Hello/Hello.php)

===Step 2: Implement the block__before_body method===

We are going to add the phrase &quot;hello world&quot; before every page of our application.  The easy way to do this is to fill the [[before_body]] slot of the [[Dataface_Main_Template.html]] template.  We do this by implementing the &apos;&apos;block__before_body&apos;&apos; method in your module (just as we would if we were trying to fill this slot from the [[Application Delegate Class]].

&lt;code&gt;
&lt;?php
class modules_Hello  {
    function block__before_body(){
        echo &quot;hello world&quot;;
        return true;
    }
}
&lt;/code&gt;

===Step 3: Activate the Module===

Xataface only loads the modules that have been enabled in the conf.ini.  We can enable our module by adding the following section to the [[conf.ini file]]:

&lt;code&gt;
[_modules]
modules_Hello=modules/Hello.php
&lt;/code&gt;

All this does is tell Xataface that the module class modules_Hello can be loaded from the location modules/Hello.php.

Now if you start up your application, you should see the phrase &quot;hello world&quot; written at the top of each page.


==Example 2: Adding a Custom Action==

Our first module shows an example of filling blocks and slots using a module.  Let&apos;s now extends that to include a custom action that displays Hello World on its own page.

Complete the following steps:

# Add an &apos;&apos;actions&apos;&apos; directory inside our new module directory.  i.e. modules/Hello/actions
# Add a file named hello.php inside the &apos;&apos;actions&apos;&apos; directory with the following contents:&lt;code&gt;
&lt;?php
class actions_hello {
    function handle($params){
        echo &quot;Hello World&quot;;
    }
}
&lt;/code&gt;
# Go to index.php?-action=hello To see the results of your action.  It should say &quot;Hello World&quot; on a blank page.

From here on you can improve this action just as you would if you defined the action inside the application&apos;s actions directory.  You can go on to restrict access to this action using permissions, or you could decide to use a template to display the action.

===Defining a Custom &quot;hello&quot; permission for our action===

Perhaps we want to create a special permission for our action so that regular users won&apos;t have access to this action unless they are specifically granted this permission.  Let&apos;s create a &quot;hello&quot; permission with which to limit access to our action.

# Create a file named &quot;permissions.ini&quot; inside your modules/Hello directory with the following contents:&lt;code&gt;
hello = Permission to access the hello action
&lt;/code&gt;

Now if you try to access your action (and you haven&apos;t been assigned ALL() permissions) you should receive either a login prompt or a permission denied message.

If you want users to be able to access your action, you will need to explicitly add this permission to one of the user&apos;s assigned roles or return it as part of the list of authorized permissions in the getPermissions() method.

===Granting the &quot;hello&quot; permission to the &quot;READ ONLY&quot; role===

If we want the default READ ONLY role to have access to the &quot;hello&quot; permission we can actually modify the READ ONLY role inside the [[permissions.ini file]] that we created inside the Hello module:

&lt;code&gt;
hello = Permission to access hello action

[READ ONLY extends READ ONLY]
    hello=1
&lt;/code&gt;


==Example 3: Using Module Templates==

Xataface, by default, stores its templates in the DATAFACE_SITE_PATH/templates and DATAFACE_PATH/templates directories.  However if you are writing a module you probably want to keep templates that are used by the module inside the module directory so that you don&apos;t break dependencies when you use the module in different applications.

You can use the [http://dataface.weblite.ca/df_register_skin df_register_skin] method to register additional directories for Xataface to look for templates in.  This will allow you to add a &apos;&apos;templates&apos;&apos; directory inside your module directory for use by your module&apos;s templates.

It is probably best to register this directory on demand (i.e. as part of individual actions) rather than register it globally.  

===Using a Template from the hello action===

Let&apos;s modify our hello action to use a template that we are going to store and distribute with our module.

# Create a directory named &quot;templates&quot; in the modules/Hello directory.
# Create a file named &quot;hello.html&quot; inside the templates directory with the following contents:&lt;code&gt;
{use_macro file=&quot;Dataface_Main_Template.html&quot;}
    {fill_slot name=&quot;main_section&quot;}
    	Hello World
    {/fill_slot}
{/use_macro}
&lt;/code&gt;  Notice that we are extending the Dataface_Main_Template.html template (which is located in the main Xataface install) so that our hello action can now take on the look and feel of the rest of the application.
# Modify the modules/Hello/actions/hello.php file to look like this:&lt;code&gt;&lt;?php
class actions_hello {
    function handle($params){
        df_register_skin(&apos;hello theme&apos;, dirname(__FILE__).&apos;../templates&apos;);
        df_display(array(), &apos;hello.html&apos;);
    }
}
&lt;/code&gt;  Notice that we call the df_register_skin function to register the templates directory that we created in the previous step.  Then we call df_display() to display the template.



==See Also===

* [[modules]] - A list of existing Xataface modules that you can download and install.
* [[block__blockname]] - A list of some of the available blocks that can be filled in the default Xataface templates.
* [http://xataface.com/documentation/tutorial/customizing-the-dataface-look-and-feel Customizing Xataface&apos;s Look and Feel with Templates] - A tutorial on how to use Xataface&apos;s built-in smarty template engine.  It has some sections on using delegate classes to override blocks and slots.
* [http://xataface.com/documentation/tutorial/getting_started/changing-look-and-feel Changing Xataface&apos;s Look and Feel] - Part of the Getting Started tutorial that shows how to use slots and blocks to customize the Xataface look and feel.</content>
	<keywords>modules</keywords>
	<language>en</language>
	<original_page></original_page>
</wiki>
<wiki id="wiki?page_id=110">
	<page_name>Contribute_to_Xataface_Translation_Project</page_name>
	<page_id>110</page_id>
	<page_title>How to Contribute Translations</page_title>
	<content>[[toc]]

==Synopsis==

Xataface stores its translations in INI files in its lang directory, one for each language.  You can develop your own translation by first copying the en.ini file to xx.ini (where xx is the ISO language code for the language you are translating for), then modifying the translations into your target language. &apos;&apos;&apos;NOTE: THIS IS NOT THE PREFERRED WAY TO CONTRIBUTE TRANSLATIONS.  PLEASE SEE &quot;Adding Translations Using Google Spreadsheets&quot; BELOW&apos;&apos;&apos;.

==Anatomy of a Language .INI file==

The language .INI files (e.g. en.ini, es.ini, etc...) consist of key-value pairs, where the key is a unique identifier for a string in Xataface, and the value is the translation.  All language files should contain the same keys, however if you omit a key from your translation, Xataface will just fall back to the default value that is defined in the PHP source code.

===Example Snippet from en.ini file===

&lt;code&gt;
scripts.GLOBAL.FORMS.OPTION_PLEASE_SELECT = &quot;Please Select ...&quot;
save_button_label = &quot;Save&quot;
scripts.GLOBAL.MESSAGE.PERMISSION_DENIED = &quot;Permission Denied&quot;
scripts.GLOBAL.NO_RECORDS_MATCHED_REQUEST = &quot;No records matched your request.&quot;
&lt;/code&gt;

In this small segment you can see 4 strings that are translated.  The values on the left of the equals sign are the keys.  Their corresponding values are on the right of the equals signs.  A corresponding segment of the fr.ini (French) language file looks like:

&lt;code&gt;
scripts.GLOBAL.FORMS.OPTION_PLEASE_SELECT = &quot;SVP sélectionnez ...&quot;
save_button_label = &quot;Enregistrer&quot;
scripts.GLOBAL.MESSAGE.PERMISSION_DENIED = &quot;Permission Refusée&quot;
scripts.GLOBAL.NO_RECORDS_MATCHED_REQUEST = &quot;Aucun résultat ne correspond à votre requête.&quot;
&lt;/code&gt;

You can see that the keys (the values on the left) are identical to those in the en.ini snippet.  Only the values are changed (translated) into French.

&apos;&apos;&apos;NOTE: IT IS BETTER TO USE GOOGLE SPREADSHEETS TO EDIT TRANSLATIONS, THAN TO WORK WITH INI FILES DIRECTLY. PLEASE SEE &quot;Adding Translations Using Google Spreadsheets&quot; BELOW&apos;&apos;&apos;


==Gotchas: Things to watch out for==

When editing or adding translations in INI files, you need to be aware of a few gotchas related to how INI files work.  If you mess up a line by forgetting to add a quote, you could cause a parse error which would cause Xataface to ignore the language file altogether.  The following are a few common pitfalls:

===Use UTF-8 Encoding===

All ini files should use UTF-8 encoding, so make sure you are using a text editor that supports UTF-8 if you want to edit INI files.  (But it is better to just use Google Spreadsheets for the editing if possible, in which case you don&apos;t have to worry about this).

===Wrap Translations in Double Quotes===

All translations should be wrapped in double quotes.  E.g.
&lt;code&gt;
mykey=&quot;My Value&quot;
&lt;/code&gt;

If you forget to close a quote, it will likely cause a parse error and Xataface will fail to load the file.  E.g.
&lt;code&gt;
mykey=&quot;My Value
&lt;/code&gt;
would be a problem.


===Can&apos;t Use Double Quotes as Part of the Translation===

Since INI files use double quotes to wrap strings, you can&apos;t use a double quote inside your translation.  E.g. you can&apos;t do this:
&lt;code&gt;
mylink=&quot;&lt;a href=&quot;http://google.com&quot;&gt;Google&lt;/a&gt;&quot;
&lt;/code&gt;
because of the inline double quotes.

One way around this is to try to use single quotes where possible.  E.g.
&lt;code&gt;
mylink=&quot;&lt;a href=&apos;http://google.com&apos;&gt;Google&lt;/a&gt;&quot;
&lt;/code&gt;

Another way around this is to the &apos;&apos;&quot;_Q&quot;&apos;&apos; key sequence, which Xataface will
automatically convert to a double quote for you at runtime.  E.g. You could do:
&lt;code&gt;
mylink=&quot;&lt;a href=&quot;_Q&quot;http://google.com&quot;_Q&quot;&gt;Google&lt;/a&gt;&quot;
&lt;/code&gt;

&apos;&apos;&apos;NOTE: If you use Google Spreadsheets to edit your translations, you won&apos;t have this problem.  You can use double quotes inside your translations.  The [[csv2ini]] tool will automatically convert these to an appropriate form when the spreadsheet is converted to the INI files.&apos;&apos;&apos;


===Leave Variables Alone===

Some translated strings include variables that are meant to be replaced by Xataface at runtime.  These should be left intact across translations.  You can identify a variable by their resemblance to PHP variables (prefixed with a $).

E.g. In the en.ini file, the translation:
&lt;code&gt;
No action found = &quot;No action found named &apos;$name&apos;&quot;
&lt;/code&gt;
has the variable &apos;&apos;$name&apos;&apos;.

So the French translation should maintain this variable.  E.g. in the fr.ini file:
&lt;code&gt;
No action found = &quot;Aucune action nommée &apos;$name&apos;&quot;
&lt;/code&gt;


==Adding Translations Using Google Spreadsheets==

In order to help keep translations more up to date, we have developed a set of tools to enable us to use Google Spreadsheets to edit and add translations, and convert these spreadsheets on demand into an appropriate set of language INI files.

The spreadsheet containing the Xataface translations is public to view and is located  [https://spreadsheets.google.com/ccc?key=0AqJNZUI7flxSdFVLWDlnVVpQZ3dMaGZhVjVHN2c3bEE&amp;hl=en here].  If you would like to add your own translations or modify existing translations, please contact [mailto:steve@weblite.ca Steve Hannah] so that you can be given editor permission.  You will first need a google docs account, then we can give you permission to edit the spreadsheet.

This centralized spreadsheet is converted to INI files and merged into SVN before every release.  You can also export this spreadsheet as a CSV and convert it to Xataface&apos;s language INI files yourself using the [[csv2ini]] tool that is located in the tools directory of the Xataface distribution.


===Gotchas with Google Spreadsheets===

Editing translations with Google Spreadsheets is much safer than editing the INI files directly.  You don&apos;t have to worry about encoding issues, and you don&apos;t have to dance around double quotes like you do with INI files.  There is only one known thing to watch out for:

====Starting a translation with a Single Quote====

If you start a translation with a single quote, Google Spreadsheets will interpret this as a directive to indicate that the contents of that cell should be considered a string (and not a number for example).  E.g. If you enter the following into a Google Spreadsheets cell:
&lt;code&gt;
&apos;Help!&apos;, I exclaimed
&lt;/code&gt;
If you unfocus from that cell it will only say:
&lt;code&gt;
Help!&apos;, I exclaimed
&lt;/code&gt;
If you go back into edit mode of the cell again, you&apos;ll see your opening single quote again... and when you tab out, it will disappear again.  

You can work around this issue by just using two single-quotes for the first quote.  E.g.:
&lt;code&gt;
&apos;&apos;Help!&apos;, I exclaimed
&lt;/code&gt;

This way Google will interpret the first quote as a directive, and it will use the second one as an actual single quote.


====Converting the Google Translation Spreadsheet into INI Files====

So you&apos;ve contributed a number of translations to the [https://spreadsheets.google.com/ccc?key=0AqJNZUI7flxSdFVLWDlnVVpQZ3dMaGZhVjVHN2c3bEE&amp;hl=en Xataface Translations Google Spreadsheet], and you want to be able to use them in your installation of Xataface before the next release.  Just follow the steps below:

# Download the spreadsheet as a CSV file, using the &apos;&apos;File&apos;&apos; &gt; &apos;&apos;Download as&apos;&apos; &gt; &apos;&apos;CSV (Current Sheet)&apos;&apos; menu item in Google Spreadsheets.
# Run the [[csv2ini]] PHP script located in the xataface/tools directory to convert the xataface-translations.csv file that you downloaded from Google Spreadsheets in the previous step into INI files.  The conversion command looks like:
&lt;code&gt;
$ php /path/to/xataface/tools/csv2ini.php /path/to/xataface-translations.csv /path/to/destination/dir/
&lt;/code&gt;

This will convert the xataface-translations.csv file into a set of language INI files and place them the specified destination directory  (don&apos;t forget the trailing slash) on /destination/dir so that the script knows its a directory.  You can then copy these INI files into your xataface/lang directory to make them live.

&apos;&apos;&apos;Note: the [[csv2ini]] script has only been used in a unix/os x type environment.  Some small modifications would probably be necessary to make them work on Windows.&apos;&apos;&apos;




</content>
	<keywords>Translations, Google Spreadsheets, en.ini, fr.ini</keywords>
	<language>en</language>
	<original_page></original_page>
</wiki>
<wiki id="wiki?page_id=111">
	<page_name>Relationship_Permissions</page_name>
	<page_id>111</page_id>
	<page_title>Relationship Permissions</page_title>
	<content>[[toc]]

==Synopsis==

As relationships are a core feature of Xataface, it is helpful to understand how to handle permissions on related records.  Even if you apply permissions to every table individually, you need to take into account the relationships that you have defined between tables, because they may open access to actions that you did not intend.

For example, suppose we have two tables: &apos;&apos;people&apos;&apos; and &apos;&apos;publications&apos;&apos;, and we have a relationship from &apos;&apos;publications&apos;&apos; table to the &apos;&apos;people&apos;&apos; table called &apos;&apos;publication_authors&apos;&apos;.

Suppose you give a user write access to a record of the publications table, but no access to the people table.  If you are allowing the &apos;&apos;add new related record&apos;&apos; permission on the &apos;&apos;publications&apos;&apos; table record, then the user will still be able to add new people, via the &quot;Add related people record&quot; function of the database.  This may or may not be desirable.

This article discusses the issues that arise due to relationships and permissions, and how to deal with them.

==Relationship Permissions==

The Xataface [[permissions.ini file]] defines a handful of permissions that are related to the management of related records.  These include:

{| class=&quot;listing listing2&quot;
|-
! Name
! Description
! Included in Roles
|-
| [[add new related record]]
| Permission to add a new related record to a relationship.
| EDIT, DELETE, OWNER, ADMIN, MANAGER
|-
| [[add existing related record]]
| Permission to add an existing record to a relationship.
| EDIT, DELETE, OWNER, ADMIN, MANAGER
|-
| [[remove related record]]
| Permission to remove a record from a relationship.  (This only allows removing a record from the relationship - not deleting the record from the database, so this is only really relevant in a many-to-many relationship).
| EDIT, DELETE, OWNER, ADMIN, MANAGER
|-
| [[delete related record]]
| Permission to delete a related record.  This allows both removing the related record from the relationship, and deleting the record from the database.   This permission is not included in any default roles.  A combination of permission for [[remove related record]] in the source table and [[delete]] in the target table, are equivalent to access to this permission.  Use this permission only when you need to override the ability to delete records from the database based on membership in a relationship.
| -
|-
| [[view related records]]
| Permission to view the records of a relationship.
| READ ONLY, EDIT, DELETE, OWNER, ADMIN, MANAGER
|-
| [[related records feed]]
| Permission to access the RSS feed of a relationship.
| READ ONLY, EDIT, DELETE, OWNER, ADMIN, MANAGER
|}


==Fine-grained, Per-relationship Permissions==

You may often find that defining a flat set of permissions to all relationships on a record is insufficient for your purposes, because some relationships may demand different access levels than others.  You can override the permissions for any particular relationship by implementing the [[rel_relationshipname__permissions]] method in the table&apos;s delegate class, where &apos;&apos;relationshipname&apos;&apos; is the name of the relationship.

e.g.  Consider the relationship &apos;&apos;manufacturers&apos;&apos;:
&lt;code&gt;
function rel_manufacturers__permissions($record){
	// $record is a Dataface_Record object
	return array(
		&apos;view related records&apos; =&gt; 0
	);
}
&lt;/code&gt;
This will tell xataface that users should not be able to view related records on the &apos;&apos;manufacturers&apos;&apos; relationship.  This will override any permissions that were defined in the [[getPermissions]] method.


==More Complete Example==

In the following example, we design a products database.  We use 2 relationships on our products table:  One to keep track of the parts that are used in our product.  The other to keep track of the users that are allowed to edit our products.

We want to make it so that only the product owner can manage the editors for a product, but anyone in the product_editors relationship is allowed to edit the product or add/remove parts from the product.

We don&apos;t want to give any users access directly to the parts, product_parts, or product_editors tables.  We want all access to go through the relationships on the products table.

===Database/Relationship Design===

Consider a database with 4 tables:

# products (product_id, product_name, owner_username)
# parts (part_id, part_name)
# product_parts (part_id, product_id)
# product_editors (product_id, editor_username)
# users (username, password, role)

And we have the following relationships on the &apos;&apos;products&apos;&apos; table:

&lt;code&gt;
[parts]
    parts.part_id=product_parts.part_id
    product_parts.product_id=&quot;$product_id&quot;

[editors]
    product_editors.product_id=&quot;$product_id&quot;
&lt;/code&gt;


===Application Permissions : Very Restrictive===

Like a good boyscout, we define our default permissions in the [[Application Delegate Class]] to be very restrictive: Don&apos;t let anyone do anything.

&lt;code&gt;
class conf_ApplicationDelegate {
    function getPermissions($record){
        return Dataface_PermissionsTool::NO_ACCESS();
    }
}
&lt;/code&gt;


===Products Table Permissions: Less restrictive===

Now we open it up for our products table in the getPermissions() method of the products delegate class.

In tables/products/products.php:
&lt;code&gt;
class tables_products {
    function getPermissions($record){
        $user = Dataface_AuthenticationTool::getInstance()-&gt;getLoggedInUser();
        if ( $user and $record and $record-&gt;val(&apos;owner_username&apos;) == $user-&gt;val(&apos;username&apos;)){
        	// Give the record owner Edit permissions on the product
        	return Dataface_PermissionsTool::getRolePermissions(&apos;EDIT&apos;);
        }
        
        // Everybody else gets read only access to the products table.
        return Dataface_PermissionsTool::READ_ONLY();
    }
}

&lt;/code&gt;

===Checking if the current User is an Editor===

So far we have given the product owner edit permissions and everyone else read only permissions.  We still need to allow editors to edit the product.  In order to do this we need to be able to *efficiently* find out if the current user is an editor of a particular product.  There are a few different ways to do this, but some are better than others.  Some strategies include:

# Perform an SQL query inside the [[getPermissions]] method to see if the user is an editor for the product.  &apos;&apos;&apos;THIS IS VERY BAD!!!&apos;&apos;&apos; The [[getPermissions]] method should not include any IO or database queries because it is called a large number of times per request... making expensive calls in this method will slow down your app dramatically.
# Create a function to load and cache all of the current user&apos;s products so that this can be easily checked at will.  This is fine if the user is expected be able to edit only a few products.  If he could be an editor for thousands of products, this may not be practical as it will cause you to have to load thousands of records into memory on every page request.
# Use the [[__sql__]] method of the delegate class to create a grafted field on the &apos;&apos;products&apos;&apos; table indicating whether the current user is an editor for the product.  This results in a very quick and accessible indicator variable that can be used in the [[getPermissions]] method to check to see if the current user is an editor for the current product.  E.g.  In the tables/products/products.php file (delegate class):&lt;code&gt;
function __sql__(){
    return sprintf(&quot;select p.*, pe.editor_username from products p
                left join product_editors pe on p.product_id=pe.product_id
                where pe.editor_username=&apos;%s&apos;&quot;,
                addslashes(
                   Dataface_AuthenticationTool::getInstance()-&gt;getLoggedInUsername()
                )
            );
                
}&lt;/code&gt;

This will result in a situation where product records will have an additional field &apos;&apos;editor_username&apos;&apos; which will either be blank if the current user is not an editor for the product; or will contain the current user&apos;s username if they are an editor for the product.


===Table Permissions for Product Editors===

Now that we have a reliable way to tell, for any given product, whether the current user is, in fact, an editor, we can ammend the [[getPermissions]] method of the products table to include our editor permissions.

&lt;code&gt;
class tables_products {
    function getPermissions($record){
        $user = Dataface_AuthenticationTool::getInstance()-&gt;getLoggedInUser();
        if ( $user and $record and $record-&gt;val(&apos;owner_username&apos;) == $user-&gt;val(&apos;username&apos;)){
        	// Give the record owner Edit permissions on the product
        	return Dataface_PermissionsTool::getRolePermissions(&apos;EDIT&apos;);
        }
        
        if ( $user and $record and $record-&gt;val(&apos;editor_username&apos;) == $user-&gt;val(&apos;username&apos;) ){
            // If the user is an editor, we give them edit permissions
            // also
            return Dataface_PermissionsTool::getRolePermissions(&apos;EDIT&apos;);
        }
        
        
        if ( $user ){
        // Other logged in users have read only access
            $perms = Dataface_PermissionsTool::READ_ONLY();
            $perms[&apos;new&apos;] = 1; // We&apos;ll also let them add new products
            return $perms;
	}
	    
	// Regular users just get the default permissions as 
	// defined in the Application Delegate class
	return null;
    }
}

&lt;/code&gt;

===Removing Editor Access to the Editor Relationship===

You&apos;ll notice that at this point, the product editor has exactly the same permission as the product owner.  They both have permission to add and remove records from all relationships on the product.  However, we don&apos;t want them to be able to access the editors relationship at all.  We will use the [[rel_relationshipname__permissions]] method to override the permissions for the &apos;&apos;editors&apos;&apos; relationship.

In the tables/products/products.php delegate class:

&lt;code&gt;

function rel_editors__permissions($record){
    $user = Dataface_AuthenticationTool::getInstance()-&gt;getLoggedInUser();
	if ( $user and $record and $record-&gt;val(&apos;owner_username&apos;) == $user-&gt;val(&apos;username&apos;)){
		// Owners should just get their normal permissions
		return null;
	}
	
	if ( $user and $record and $record-&gt;val(&apos;editor_username&apos;) == $user-&gt;val(&apos;username&apos;) ){
		// If the user is an editor, we give them edit permissions
		// also
		return array(
		    &apos;view related records&apos; =&gt; 0,
		    &apos;add new related record&apos; =&gt; 0,
		    &apos;add existing related record&apos; =&gt; 0,
		    &apos;remove related record&apos; =&gt; 0,
		    &apos;delete related record&apos; =&gt; 0
		    );
	}
	
	// Other users just get their normal permissions
	return null;

}

&lt;/code&gt;


===Assigning product owner by default===

With the current permissions, something funny would happen.  Users have permission to add new records, but once the record is added they won&apos;t be able to edit it because they are neither an editor nor the owner of the product.  We&apos;ll fix this by assigning the current user as the product&apos;s owner using the [[beforeSave]] trigger in the products delegate class:

&lt;code&gt;
function beforeSave($record){
	$user = Dataface_AuthenticationTool::getInstance()-&gt;getLoggedInUser();
	if ( $user ){
    	$record-&gt;setValue(&apos;owner_username&apos;, $user-&gt;val(&apos;username&apos;));
    }
}
&lt;/code&gt;

===Testing Out Our Solution===

In your testing of the solution, you should find the following:

# Trying to access any table other than the &apos;&apos;products&apos;&apos; table should result in a &apos;&apos;permission denied&apos;&apos; error.
# If you access the &apos;&apos;products&apos;&apos; table, you should be able to see a list of existing products, and the &quot;Add New Record&quot; action.
# After you add a new product you should see that you are the product owner.
# As a product owner you should see both the &apos;&apos;parts&apos;&apos; and &apos;&apos;editors&apos;&apos; tabs in your product record.  You should be able to view and add new records to both of these relationships.
# Add another user as an editor to your product, then log in as that user.  You should be able to edit the product, but you shouldn&apos;t be able to see the &apos;&apos;editors&apos;&apos; tab for the product.

==See Also==

* [[permissions.ini file]] - Overview of the Xataface permissions.ini file
* [http://xataface.com/documentation/tutorial/getting_started/permissions Getting Started with Xataface Permissions]
* [[How to granulate permissions on each field]] - Brief tutorial on how to set permissions on a field by field basis.
* [[Delegate class methods]] - A list of all of the available delegate class methods that you can implement.  Many of them pertain to permissions and triggers.
* [[Application Delegate Class]] - Overview of the application delegate class.
* [[relationships.ini file]] - The relationships.ini file directives.
</content>
	<keywords>relationships, permissions, rel_relationshipname__permissions, getPermissions, permissions.ini</keywords>
	<language>en</language>
	<original_page></original_page>
</wiki>
<wiki id="wiki?page_id=98">
	<page_name>registration_form</page_name>
	<page_id>98</page_id>
	<page_title>Setting up User Registration</page_title>
	<content>[[toc]]

===Synopsis===

Xataface optionally enables you to allow users to register for an account in your application.  If your &apos;&apos;users&apos;&apos; table includes a column for email, it will also perform email validation before the account is activated.  Before tackling user registration, it is good to have an understanding of Xataface&apos;s [[authentication]] and [http://xataface.com/documentation/tutorial/getting_started/permissions permissions] faculties.

===Enabling Registration===

To enable registration, simply add the following to the &apos;&apos;[[_auth]]&apos;&apos; section of the [[conf.ini file]]:

&lt;code&gt;
allow_register=1
&lt;/code&gt;

e.g. after adding this, your &apos;&apos;[[_auth]]&apos;&apos; section might look like:

&lt;code&gt;
[_auth]
     users_table=users
     username_column=username
     password_column=password
     allow_register=1
&lt;/code&gt;

After doing this, you&apos;ll notice a little &apos;&apos;Register&apos;&apos; link below the login form.  

[[Image:http://media.weblite.ca/files/photos/Picture%2036.png?max_width=640]]

Clicking on this link will produce a registration form for the user which is essentially a &quot;New Record&quot; form on your &apos;&apos;users&apos;&apos; table.

[[Image:http://media.weblite.ca/files/photos/Picture%2037.png?max_width=640]]

Some features of this registration form include:

* Checks to ensure that the username is unique
* If the users table contains an &apos;&apos;email&apos;&apos; field, it will use the user-entered address for email validation before activation is complete.

===Setting up Permissions to Support Registration===

&apos;&apos;&apos;Xataface &lt;= 1.2.4&apos;&apos;&apos;:   You must ensure that unlogged-in users have permission to add new records to the &apos;&apos;users&apos;&apos; table.  This means that your getPermissions() method on the users table should, at least, provide the &apos;&apos;new&apos;&apos; permission.  In addition these users must be granted the &apos;&apos;register&apos;&apos; permission in order to be able to register to begin with.

&apos;&apos;&apos;Xataface &gt;= 1.2.5&apos;&apos;&apos;:  You no longer need to provide the &apos;&apos;new&apos;&apos; permission to allow users to register.  You simply need to provide the &apos;&apos;register&apos;&apos; permission.

====Sample Permissions on Users Table====

In the tables/users/users.php file (assuming my &apos;&apos;users&apos;&apos; table is actually named &quot;users&quot;)

&lt;code&gt;
class tables_users {

    function getPermissions($record){
        if ( isAdmin() ) return null;
        $perms[&apos;register&apos;] = 1;
        return $perms;
     
    }
}
&lt;/code&gt;

&apos;&apos;&apos;Note that this example is only applicable for Xataface 1.2.5 or higher.  In Xataface 1.2.4 you needed to provide users with the &apos;&apos;new&apos;&apos; permission rather than the &apos;&apos;register&apos;&apos; permission, which opens up a small security hole since users could potentially just use the &quot;new&quot; action if they new the URL and by-pass the registration and activation email altogether&apos;&apos;&apos;.

Some notes on this example:

* The isAdmin() function is not part of Xataface.  It is used as a bit of *magic* here to reduce code.  It is supposed to simply return true if the currently logged in user is an admin.  Hence if the user is an admin, this method defers to the Application Delegate class&apos;s permissions (i.e. this method should not affect administrators).
* We are giving all users (logged in or not) the register permission which enables them to register for an account on the system.
* Generally you will want to restrict permissions on some of the fields in the users table.  E.g. users should not be able to set their role or access level when they register.  You can define more fine-grained permissions on these fields using the [[fieldname__permissions]] method of the users table delegate class (per the following example).

====Restricting Permissions on Particular Fields====

You probably don&apos;t want users to be able to set their access level when the register for an account, and your &quot;users&quot; table will quite often contain some field like &quot;role&quot; which stores this information.  So the previous example is not quite realistic.  You will also need to restrict permissions on the &quot;role&quot; field (and any other fields that you want to prevent users from setting themselves.

&lt;code&gt;
function role__permissions(&amp;$record){
    if ( isAdmin() ) return null;
    return Dataface_PermissionsTool::NO_ACCESS();
}
&lt;/code&gt;

This will cut off the user&apos;s ability to set their own role when they register.  You will likely want to set the default role value either in the mysql table definition or in the [[beforeInsert]] trigger.

===Email Validation===

As mentioned above, registration works by sending an activation email to the address specified in the user&apos;s registration.  This email contains a link back to the &apos;&apos;activate&apos;&apos; action of your Xataface application, which will create the user account and log the user in.  This implies that your &apos;&apos;users&apos;&apos; table must store an email address for your users.  If you add a field named &apos;&apos;email&apos;&apos; to the &apos;&apos;users&apos;&apos; table, Xataface will assume that you mean to use this field as the user&apos;s email address, and thus, for email validation.  However you can override this functionality and use *any* field as an email field by setting the &apos;&apos;email&apos;&apos; directive of the appropriate field in the [[fields.ini file]] for the &apos;&apos;users&apos;&apos; table.

&apos;&apos;&apos;Example: Assigning the my_addr field of the users table to be used for email validation&apos;&apos;&apos;:

In the tables/users/fields.ini file:
&lt;code&gt;
[my_addr]
    email=1
&lt;/code&gt;

====Disabling Email Validation====

99% of the time, email validation is the preferred way of ensuring that people who register are who they say they are.  You may, however, prefer to let users register directly without requiring the email activation step.  You can disable email validation by overriding the &apos;&apos;register&apos;&apos; action in the [[actions.ini file]] as follows:

In your application&apos;s [[actions.ini file]]:
&lt;code&gt;
[register &gt; register]
    email_validation=0
&lt;/code&gt;

After setting this, the user account will automatically be created, and the user logged in upon saving the registration form.

===Triggers: Overriding Registration Workflow===

Xataface provides a number of triggers in the [[Application Delegate Class]] to override and extend the behavior of the user registration and activation process.  For a list of available triggers see [[Application Delegate Class#registration]].


===Preventing Spam with CAPTCHA===

One problem with enabling automatic registration is that it invites SPAM in the form of bots that can learn how to automatically register for user accounts and then leave unwanted input into your application.  The Xataface [[reCAPTCHA module]] allows you to avoid these problems to some extent by forcing users who aren&apos;t logged in to fill a CAPTCHA field in order to successfully submit the form.  This is especially helpful for registration forms.

After installing the [[reCAPTCHA module]] the registration form will include a CAPTCHA field like the one depicted below:

[[Image:http://media.weblite.ca/files/photos/Picture%2038.png?max_width=640]]

For more information about the reCAPTCHA module [[reCAPTCHA module|click here]].
    </content>
	<keywords>registration form, _auth, authentication</keywords>
	<language>en</language>
	<original_page></original_page>
</wiki>
<wiki id="wiki?page_id=99">
	<page_name>reCAPTCHA_module</page_name>
	<page_id>99</page_id>
	<page_title>The reCAPTCHA module</page_title>
	<content>[[toc]]

===Synopsis===

The Xataface reCAPTCHA module CAPTCHA support to any Xataface form that is rendered to the public (i.e. when users are not logged in).  This is particularly useful for the [[registration form]] as a means of spam prevention.   Below is a screenshot of a registration form with the reCAPTCHA module installed:

[[Image:http://media.weblite.ca/files/photos/Picture%2038.png?max_width=640]]

For more information about reCAPTCHA see [http://recaptcha.net/].


===Installation===

# Download/extract the module directory into your xataface/modules directory.  Currently this module is only available in SVN (http://weblite.ca/svn/dataface/modules/reCAPTCHA/trunk/)
# Add the following to the &lt;nowiki&gt;[_modules]&lt;/nowiki&gt; section of your [[conf.ini file]].&lt;code&gt;
[_modules]
    modules_reCAPTCHA=modules/reCAPTCHA/reCAPTCHA.php
&lt;/code&gt;
# Add the following section to your conf.ini file.&lt;code&gt;
[reCAPTCHA]
    public_key=&quot;xxxxxxx&quot;
    private_key=&quot;xxxxxxx&quot;
&lt;/code&gt; Where public_key, private_key are your keys from your reCAPTCHA account. &apos;&apos;&apos;(Note that you need to register for a free reCAPTCHA account at [http://recaptcha.net/] in order for this to work.&apos;&apos;&apos;

===Usage===

If you are NOT logged in, you will now see a reCAPTCHA validation image before the submit button for all webforms in your Xataface application.  If you fail to enter the captcha text correctly the form will not validate.  If you are logged in this module has no effect.

===See Also===

* [[registration_form|Enabling User Registration in Xataface]]
* [[modules|Xataface Modules]]
</content>
	<keywords>captcha, registration, validation</keywords>
	<language>en</language>
	<original_page></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=68">
	<page_name>relationship</page_name>
	<page_id>68</page_id>
	<page_title>The relationship fields.ini directive</page_title>
	<content>[[fields.ini file|Return to fields.ini file directives]]

[[toc]]

===Synopsis===

Certain types of widgets (e.g. grid (v1.0) and checkbox (v1.2)) support the relationship directive which allows them to effectively add/remove records from a specified relationship.  This directive only works with transient fields.

===Example 1: Checkboxes to add/remove categories===

(Note: This example requires Xataface 1.2 or higher to work)

Suppose we have a database that keeps track of courses and the branch of research that they belong to.  A course can be part of multiple branches.  We want to be able to select the branches that a particular course belongs to on the edit form for that course using checkboxes.

Table Structure:
&lt;code&gt;
courses:
   course_id : int (primary key)
   course_title : varchar

branches:
   branch_id : int (primary key)
   branch_name : varchar
   branch_description: text

course_branches:
   course_id : int
   branch_id : int
&lt;/code&gt;

Relationship definition:  (from the tables/courses/[[relationships.ini file]]):
&lt;code&gt;
[branches]
    course_branches.course_id=&quot;$course_id&quot;
    course_branches.branch_id=branches.branch_id
&lt;/code&gt;

Field definitions: (from tables/courses/[[fields.ini file]]):
&lt;code&gt;
[branches]
  transient=1
  relationship=branches
  widget:type=checkbox
&lt;/code&gt;

Things to notice:
# This is a many-to-many relationship (hence the need for the course_branches join table.
# The [branches] field is a transient field.
# The relationship directive from the [[fields.ini file]] references our branches relationship that was defined in the [[relationships.ini file]].
# You can call the field anything that you like.  There is no need for it to have the same name as the relationship.  It just turned out that way in this example.  

===Example 2: Using a grid widget===

Let&apos;s modify example 1 slightly to use a grid widget instead of checkboxes.  The grid widget will allow us edit the records in a relationship using dynamic table.  It automatically uses the correct widget for each column of the table according to the definition in the target table&apos;s [[fields.ini file]].  Most of the definition can remain the same.  We only change the [[fields.ini file]] directive:

&lt;code&gt;
[branches]
  transient=1
  relationship=branches
  widget:type=grid
  widget:columns=&quot;branch_name,branch_description&quot;
&lt;/code&gt;

In this case we are able to edit the branch name and description in each row of the grid.

===See Also===

* [[grid|The grid widget]]
* [[checkbox|The checkbox widget]]
* [[relationships.ini file|The relationships.ini file]]
* [[fields.ini file|The fields.ini file]]</content>
	<keywords>grid widget, relationship, checkbox</keywords>
	<language>en</language>
	<original_page>0</original_page>
</wiki>
<wiki id="wiki?page_id=88">
	<page_name>secure</page_name>
	<page_id>88</page_id>
	<page_title>secure fields.ini directive</page_title>
	<content>[[fields.ini file]] directive used only with [[container fields]].  If this flag is set, then the field contents will be treated in a secure manner and will obey the application permissions.  If this directive is not set, then uploaded files in [[container fields]] are served directly by the web server without considering application permissions.  Setting this directive will cause the application use a special get_blob action to serve the uploaded file, and this obeys application permissions.

==Example==

Given a field to upload a PDF report, your [[fields.ini file]] section for this field might be something like:

&lt;code&gt;
[pdf_report]
    Type=container
    allowed_extensions=&quot;pdf&quot;
    savepath=&quot;uploads&quot;
    url=&quot;uploads&quot;
&lt;/code&gt;


Now if we upload a file named &quot;foo.pdf&quot; in this field, it will be uploaded to:
 http://www.example.com/path/to/myapp/uploads/foo.pdf

Now we change the field definition to use the secure directive:

&lt;code&gt;
[pdf_report]
    Type=container
    allowed_extensions=&quot;pdf&quot;
    savepath=&quot;uploads&quot;
    url=&quot;uploads&quot;
    secure=1
&lt;/code&gt;

In this case it will still upload files to the &apos;&apos;uploads&apos;&apos; directory, but all of the links generated in the Xataface interface (and via the &apos;&apos;display()&apos;&apos; and &apos;&apos;htmlValue()&apos;&apos; methods) will be for a URL like:
  http://www.example.com/path/to/myapp/index.php?-action=getBlob&amp;-table=mytable&amp;-field=pdf_report&amp;record_id=10

Which will serve up the PDF file as an attachment.

===Restricting Direct Access to uploads directory===

Note: You still need to restrict access to the uploads directory or it may be possible for users to still guess the absolute URL to files in it.  You can restrict access by placing an .htaccess file in the uploads directory (if you are using Apache) with the following contents:
&lt;code&gt;
deny from all
&lt;/code&gt;

If you are using IIS or another web server you should look into the methods available for you to restrict access to directories.

===HTTP Response Codes===

The [[getBlob action]] will return the following HTTP Response Codes:

* &apos;&apos;&apos;404&apos;&apos;&apos; - If either the record does not exist, or the record&apos;s specified container field is empty.
* &apos;&apos;&apos;403&apos;&apos;&apos; - If the current user doesn&apos;t have permission to access this record.
* &apos;&apos;&apos;500&apos;&apos;&apos; - If there is another error.  The actual error will be written to the error log.</content>
	<keywords>secure,fields.ini file</keywords>
	<language>en</language>
	<original_page></original_page>
</wiki>
<wiki id="wiki?page_id=97">
	<page_name>_auth</page_name>
	<page_id>97</page_id>
	<page_title>_auth section of the conf.ini file</page_title>
	<content>[[conf.ini file|Return to conf.ini file]]

[[toc]]

===Synopsis===

The &apos;&apos;_auth&apos;&apos; section of the conf.ini file includes configuration directives to enable authentication in a Xataface application.  For more information about authentication and registration see [[authentication]].  This section may include the following directives:

===Directives===

{| class=&quot;listing listing2&quot;
|-
! Directive
! Description
! Required
! Default
! Version
|-
| users_table
| The name of the table that contains your user accounts.
| Yes
| None
| 0.6
|-
| username_column
| The name of the column that stores the username.
| Yes
| None
| 0.6
|-
| password_column
| The name of the column that stores the password.
| Required if using basic authentication.
| None
| 0.6
|-
| auth_type
| Specifies the authentication module that is being used.  E.g. basic, cas, ldap, http, facebook, etc...
| No
| basic
| 0.6
|-
| allow_register
| Flag to enable user registration.  If this is set to 1, then a &apos;&apos;register&apos;&apos; link will appear below the login form.
| No
| 0
| 0.8
|-
| session_timeout
| Number of seconds of inactivity after which the user will be logged out. Note: Arithmetic don&apos;t work in the conf.ini, use seconds.
| No
| 86400 (=&gt; 24*60*60 (24 hours))
| 1.3rc4
|}

===See Also===

* [[authentication]] - Overview of Xataface Authentication
* [[conf.ini file]] - Directives available in the conf.ini file.</content>
	<keywords>_auth,authentication,conf.ini file,allow_register</keywords>
	<language>en</language>
	<original_page></original_page>
</wiki>
<wiki id="wiki?page_id=70">
	<page_name>documentation_guide</page_name>
	<page_id>70</page_id>
	<page_title>Documentation Guide</page_title>
	<content>Xataface uses a wiki to manage its online documentation which can be edited by anyone.  All you have to do is [http://xataface.com/wiki/index.php?-action=login login with your forum username and password] ([http://xataface.com/forum/profile.php?mode=register register for the forum here]).  Then when you are browsing a page of the wiki, you&apos;ll see an &apos;Edit&apos; tab along the top.  Click on this tab to start editing the page in your browser.  Wiki markup is a little simpler than HTML and a little more complex than plain text.  It is easy to get a handle on once you get started.  If you aren&apos;t sure how to format it exactly how you want, don&apos;t worry.  Someone may come by after you and improve on your formatting.  That&apos;s what the community approach is all about.

==The Documentation Team==

Join the Xataface documentation team to help participate in the planning of the documentation.  If you want to help out, contact [mailto:steve@weblite.ca Steve Hannah] and he&apos;ll add you to the documentation group where you can access the private documentation forums and meet the rest of the team.

==Using the Wiki==

The following is a brief guide in using the Xataface Wiki.  All following instructions assume that you are already [http://xataface.com/wiki/index.php?-action=login logged in] to the wiki.  You can use your forum username and password to login.

===Editing an Existing Page===

# Navigate to the page that you want to edit
# Click on the &quot;Edit&quot; tab along the top.
# Make changes to your page.
# Save the changes.

===Adding a New Page===

====Method 1: Add a link from an existing page===

# Navigate to an existing page that you want to link to your new page.
# Click on the &quot;Edit&quot; tab along the top.
# Somewhere in the content of the page, add a link to your new page (which doesn&apos;t exist yet), by adding the following markup&lt;code&gt;
[[The name of your new page]]
&lt;/code&gt;
# Save your changes.
# Click on the &quot;view&quot; tab along the top and find the place where you added your link.  It should be displayed with a &apos;?&apos; right after it.  Click on the &apos;?&apos; and it will bring you to the &quot;new page form&quot;.
# fill in the form with your page contents and click save.

====Method 2: Accessing new page form directly====

# Access the [http://xataface.com/wiki/index.php?-action=new&amp;-table=wiki new page form] directly.


===Uploading Images===

Image can be uploaded at [http://media.weblite.ca The Web Lite Media Manager].  You&apos;ll need an account to access this site.  If you are a member of the documentation team you can request an account from [mailto:steve@weblite.ca Steve Hannah] so that you can upload images here.

Steps:

# Log into [http://media.weblite.ca the Web Lite Media Manager].
# Click on &quot;Add New File&quot; in the menu on the left.
# Select a name for the file, and browse to the image you want to upload in the file upload field.  You don&apos;t need to check any category boxes.  Press save.
# Click on the &quot;View&quot; tab for your newly uploaded image.
# Copy the embed code for the image from the &quot;Embed Code&quot; field.
# In the wiki page add the embed code where you want your image to appear as follows:&lt;code&gt;
[[Image:EMBED_CODE]]
&lt;/code&gt; Where EMBED_CODE is the URL for the image as you copied and pasted out of the media manager.
# Save your changes.

===Uploading Video===

===Adding Source Code Snippets===</content>
	<keywords>documentation wiki</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=59">
	<page_name>no_access_text</page_name>
	<page_id>59</page_id>
	<page_title>no_access_text</page_title>
	<content>Whenever the NO_ACCESS permission is given for a field, normally the text NO ACCESS appears.  But we might want to display another text.  Here is an example of the text subscribe is used instead of NO ACCESS whenever the NO_ACCESS permissions is given.

&lt;code&gt;function no_access_text(&amp;$record){
		return &quot;Subscribe&quot;;
	}
&lt;/code&gt;</content>
	<keywords></keywords>
	<language>en</language>
	<original_page>0</original_page>
</wiki>
<wiki id="wiki?page_id=66">
	<page_name>table</page_name>
	<page_id>66</page_id>
	<page_title>table</page_title>
	<content>When using widget:type table, it will store the data as XML.

So the field type must be TEXT (or varchar... but text is better). You can decide which columns you want in the table by creating sub-fields in your fields.ini file as follows:

Suppose you want a column called &apos;name&apos; and a column called &apos;url&apos;

&lt;code&gt;
[myfield]
widget:type=table
[myfield:name]
[myfield:url]
&lt;/code&gt;

Now when you access the stored value using the Dataface API, the value of myfield will be stored as an array of associative arrays. e.g. 

&lt;code&gt;
foreach ( $record-&gt;val(&apos;myfield&apos;) as $vals){ echo $vals[&apos;name&apos;].&apos; -- &apos;.$vals[&apos;url&apos;]; }
&lt;/code&gt;</content>
	<keywords></keywords>
	<language>en</language>
	<original_page>0</original_page>
</wiki>
<wiki id="wiki?page_id=71">
	<page_name>GettingStarted:Introduction</page_name>
	<page_id>71</page_id>
	<page_title>Introduction</page_title>
	<content>Web Lite is a simple framework for building data-driven web applications in PHP and MySQL. This section introduces some of the concepts and applications of Dataface.

To fully understand what Xataface is, we must first define a few key terms:

&apos;&apos;&apos;Framework&apos;&apos;&apos; - A set of software routines that provide a foundation structure for an application. Frameworks take the tedium out of writing an application from scratch. (From Answers.com)

&apos;&apos;&apos;Data-driven design&apos;&apos;&apos;- Designing an application around the data that it will store.

Xataface is a &apos;&apos;Framework&apos;&apos; in the sense that it is a set of classes and libraries that take the tedium out of writing web applications. It provides a simple web interface to a MySQL database enabling users to update, delete, and find data in the underlying database. The interface is targeted at secretaries and end-users as opposed to database administrators.

Xataface enables &apos;&apos;data-driven design&apos;&apos; because it allows developers to develop web sites by first designing the database that will be used to store the data on the website, and then design the pages used to display the data. The developer can focus on the data because he or she does not have to worry about having to build forms to update the data. If the requirements of the application change, the developer can simply add a field to the database table and all associated web forms will be updated automatically (because they are all dynamically generated using the database schema).


===Requirements===

* [http://php.net PHP] &gt;= 4.3
* [http://mysql.com MySQL] &gt;= 3.2.3

===Key Technologies===

* [http://pear.php.net PEAR class libraries] (HTML_QuickForm, etc...)
* [http://smarty.net Smarty Templating Engine]
* [http://plone.org Plone] Javascript and CSS style sheets

===Development Procedures===

# Identify the data that will need to be stored for a web site.
##[[Image:http://xataface.com/documentation/tutorial/getting_started/er-diagram.png]]
# Design the database using your favorite database administration program (e.g., PHPMyAdmin)
##[[Image:http://xataface.com/documentation/tutorial/getting_started/phpMyAdmin-1-small.gif]]
# Tell Xataface some DB connection info, and voila! You have an application:
##[[Image:http://xataface.com/documentation/tutorial/getting_started/new-record-form-1-small.gif]]

===Where to go from here===

This tutorial will teach you the basics of Xataface and how to construct a simple application using the Xataface. After reading this tutorial you will be ready to tackle some medium to large web sites with the help of the Xataface reference documentation. You are also encouraged to mail the [http://xataface.com/forum Xataface forum] if you have questions.</content>
	<keywords>introduction requirements getting started</keywords>
	<language>en</language>
	<original_page></original_page>
</wiki>
<wiki id="wiki?page_id=50">
	<page_name>__field__permissions</page_name>
	<page_id>50</page_id>
	<page_title>__field__permissions</page_title>
	<content>This method can be used to set the default permissions for all fields in a designated table, when specified in that table&apos;s delegate class. It comes in handy in situations when you want to deny access to all fields except for those designated, rather then specifying each field to deny individually. For example, to revoke edit permissions from all fields but one, the user must first have edit permissions to the table overall, otherwise the Edit tab/action will not appear. Then, use this __field_permissions method to revoke edit permissions from all fields. Finally, use the fieldname__permissions method (see below) to allow access to only those fields needed.

=== Also See: ===

* [[How_to_granulate_permissions_on_each_field]]
* [[fieldname__permissions]]</content>
	<keywords></keywords>
	<language>en</language>
	<original_page>0</original_page>
</wiki>
<wiki id="wiki?page_id=103">
	<page_name>Customizing_Theme_Based_on_IP_Address</page_name>
	<page_id>103</page_id>
	<page_title>Customizing Theme Based on IP Address</page_title>
	<content>This article deals with the following topics:

# Using [[field__pullValue]]/[[field__pushValue]] methods to customize how a field is edited and stored in the database.
# Using [[beforeHandleRequest]] to modify the application settings based on the user&apos;s IP address
# Storing ranges of IP addresses in the database.

Last week I set up a site that needed to have slightly different behavior depending on the IP address of the remote user.  E.g.  If a user is connecting from an IP address between 192.168.0.0 to 192.168.0.255 we would use a different theme than if they were connecting from a different block.  In addition to different themes, we also to use different types of authentication depending on which IP block the user is visiting from.

This requirement is actually common for systems that are syndicated by different organizations and should behave slightly differently depending on which organization the user belongs to (assuming they are connecting from that organization&apos;s network).

To implement this behavior we need to solve one issue.

&apos;&apos;&apos;How do we store a range of IP addresses in the database so that they can be queried easily to match if the user&apos;s IP address falls in that range.&apos;&apos;&apos;
	
It turns out that this is quite easy to do, since IP addresses are actually just a 4 digit number (base 256).  So we can easily convert this number to base 10 and store it as a regular unsigned integer in the database.  In addition, both PHP and MySQL provide functions to convert from an IP address to an integer and back.

The PHP functions are called [http://ca3.php.net/long2ip long2ip] and [http://ca3.php.net/ip2long ip2long] respectively.

So we have stored a start IP address and an end IP address as integers, we could simply query the database to see if a given IP address falls in that range as follows:

&lt;code&gt;
$intIP = ip2long($_SERVER[&apos;REMOTE_ADDR&apos;]);
$sql = sprintf(&apos;select * from ip_blocks where start_ip&lt;=%u and end_ip&gt;=%u&apos;, $intIP, $intIP);
... etc....
&lt;/code&gt;

&apos;&apos;&apos;It is important to note that you need to use the sprintf() function for converting $intIP into a string because PHP will convert it to an integer which could overflow if you leave it to do a default conversion.&apos;&apos;&apos;
	
For the above query, we assuming a table with a definition like:

&lt;code&gt;
create table ip_blocks (
    ip_block_id int(11) not null primary key,
    start_ip unsigned int(11) not null
    end_ip unsigned int(11),
    key (start_ip),
    key (end_ip)
)
&lt;/code&gt;
	
Now if we attach some information to the IP block, like the theme that should be used, we can check the user IP address against the available IP blocks at the beginning of each request to set the theme for that request.  We will use the [[beforeHandleRequest]] method of the [[Application Delegate Class]] to house this because it allows us to set things like the theme or change the user&apos;s action.

e.g.

&lt;code&gt;
class conf_ApplicationDelegate {
	function beforeHandleRequest(){
		$app = Dataface_Application::getInstance();
		
		// Get a reference to the current query so we can
		// alter it if necessary.
		$query =&amp; $app-&gt;getQuery();
		
		
		// Get the user&apos;s IP address and covert it to a long int.
		$intIP = ip2long($_SERVER[&apos;REMOTE_ADDR&apos;]);
		$sql = sprintf(&apos;select `theme` from ip_blocks where start_ip&lt;=%u and end_ip&gt;=%u&apos;, $intIP, $intIP);
		
		$res = mysql_query($sql, df_db());
		if ( !$res ) throw new Exception(mysql_error(df_db()));
		
		$row = mysql_fetch_row($res);
		
		// If we didn&apos;t find any valid IP ranges, let&apos;s redirect the
		// user to a different action to let them know that
		// they&apos;re not welcome here.
		if ( !$row ){
			$query[&apos;-action&apos;] = &apos;not_welcome&apos;;
				// This assumes that we have defined an action
				// called &quot;not_welcome&quot;
				
			return;
		}
		
		$theme = $row[0];
		$themePath = &apos;themes/&apos;.basename($theme);
		// Check that the theme exists.
		if ( $theme and file_exists($themePath) ){
			df_register_skin($theme, $themePath);
		}
	}
}
&lt;/code&gt;

The above snippet makes use of the [[df_register_skin]] method that registers a theme to be used dynamically.  The first parameter is the theme name, and the second parameter is the path to the theme.


This code works great if we already have IP addresses stored properly as integers in our database, but how do we make it so users can work with the IP addresses as IP addresses and not integers?  We need to be able to transform from integer to IP address to display in the edit record form, and then convert the resulting IP address back to an integer for storage in the database.  Xataface provides two delegate class methods precisely for this purpose:

# [[field__pullValue]] - Transforms a value as stored in the database to a format that is preferred in the edit form.
# [[field__pushValue]] - Transforms a value entered into the edit form into a format that is preferred by the database.

So, in our delegate class we would have:

&lt;code&gt;
&lt;?php
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;
	}
	
	function end_ip__pushValue($record, $el){
		$val = ip2long($el-&gt;getValue());
		if ( $val !== false ){
			return sprintf(&apos;%u&apos;, $val );
		}
		return null;
	}
	
	function end_ip__pullValue($record, $el){
		$val = $record-&gt;val(&apos;end_ip&apos;);
		if ($val){
			return long2ip($val);
		}
		return $val;
	}
	
	
}
&lt;/code&gt;

The [[field__pullValue]] and [[field__pushValue]] method should be inverses of each other.

&apos;&apos;&apos;Note that support for [[field__pullValue]] and [[field__pushValue]] are supported by Xataface since version 0.6, however support for them with the grid widget was not added until Xataface version 1.3.&apos;&apos;&apos;
	

Now, on the edit form, users can enter and edit IP addresses in the normal format, but they will be converted to unsigned integers for storage in the database.

There is only one thing remaining, though.  In the list view still shows the integer version of the IP addresses. We want them to show them as regular IP addresses.  So we add [[field__display]] methods to our delegate class:

&lt;code&gt;
function start_ip__display($record){
	$val = $record-&gt;val(&apos;start_ip&apos;);
	if ( $val )
		return long2ip($val);
	return $val;
}

function end_ip__display($record){
	$val = $record-&gt;val(&apos;end_ip&apos;);
	if ($val){
		return long2ip($val);
	}
	return $val;
}
&lt;/code&gt;

==References==

* [http://xataface.com/documentation/how-to/how-to-define-custom-serialization-for-fields How to define custom serialization for fields]
</content>
	<keywords>ip address, pullValue, pushValue, beforeHandleRequest</keywords>
	<language>en</language>
	<original_page></original_page>
</wiki>
<wiki id="wiki?page_id=83">
	<page_name>Key</page_name>
	<page_id>83</page_id>
	<page_title>fields.ini Directive: Key</page_title>
	<content>The &apos;&apos;&apos;Key&apos;&apos;&apos; directive is used only when the table is a view and you need to explicitly define which columns are part of the primary key.  For example, if we created a view on the books table to only show books in a given year as follows:
&lt;code&gt;
create view books_2000 as
select * from books where year=&apos;2000&apos;
&lt;/code&gt;

And we wanted to use this view as a table in our Xataface application we would need to tell it that the primary key of this view is the book_id field.  So in the fields.ini file we would add:

&lt;code&gt;
[book_id]
    Key=PRI
&lt;/code&gt;

Note that this is case sensitive.  key=PRI will not work.

===Compound Primary Keys===

For primary keys comprising multiple columns we would add this directive for each field in the key.  E.g. if our books_2000 view had 2 fields in the primary key, say author_id and book_index, we would have in the books_2000 fields.ini file:
&lt;code&gt;
[author_id]
    Key=PRI

[book_index]
    Key=PRI
&lt;/code&gt;

Links:
* [http://xataface.com/forum/viewtopic.php?f=4&amp;t=6723 Lookup widget on view with compound primary key]

Return to [[fields.ini file]]</content>
	<keywords>Key, Views, MySQL Views, Create View, PRI, Primary Keys</keywords>
	<language>en</language>
	<original_page></original_page>
</wiki>
<wiki id="wiki?page_id=114">
	<page_name>XataJax_Compiler</page_name>
	<page_id>114</page_id>
	<page_title>Introduction to the XataJax Compiler</page_title>
	<content>Return to [[XataJax]]

&apos;&apos;&apos;DISCLAIMER&apos;&apos;&apos;: This page introduces features that require Xataface 1.3 or higher.  At present (Jan. 2011) only Xataface 1.2.6 has been released to the public.

[[toc]]

===Synopsis===

The XataJax compiler is a Javascript CSS compiler and linker that comes with the [[XataJax]] module and will be a standard part of Xataface starting in version 1.3.  It provides a mechanism to process and compile (or so to speak) all of the javascripts required for a page request at the time that the page is requested.  This results in a more scalable, manageable javascript and CSS source base - and in improved performance for your applications.

===Compiler Directives===

{| class=&quot;listing listing2&quot;
|-
! Name
! Description
! Version
|-
| [[xatajax include directive|include]]
| Includes another javascript file inside the current one in place of this directive.  Sample code:&lt;code&gt;//include &lt;myscript.js&gt;&lt;/code&gt;
| XataJax 0.1 Xataface 1.3
|-
| [[xatajax require directive|require]]
| Includes another javscript file inside the current one only if that file hasn&apos;t already been included.  Sample code: &lt;code&gt;//require &lt;myscript.js&gt;&lt;/code&gt;
| XataJax 0.1 Xataface 1.3
|-
| [[xatajax require-css directive|require-css]]
| Includes a CSS script in the CSS file.  This will will search in the [[Dataface_CSSTool]] include path for the script.  Sample code: &lt;code&gt;//require-css &lt;mystyles.css&gt;&lt;/code&gt;
| XataJax 0.1 Xataface 1.3
|-
| [[xatajax load directive|load]]
| Loads the specified Javascript file in a separate script tag.  This enables you to reference other scripts without including them in the same bundle, allowing for more effective caching.  Sample code: &lt;code&gt;//load &lt;myscript.js&gt;&lt;/code&gt;
| XataJax 0.1 Xataface 1.3
|}


===How it Works===

The XataJax compiler works similar to a regular code compiler.  It provides 4 server-side directives to allow you to express dependencies between scripts and stylesheets:

# &apos;&apos;&apos;include&apos;&apos;&apos; : Includes another javascript file inside the current script in place of the &apos;&apos;&apos;include&apos;&apos; directive.
# &apos;&apos;&apos;require&apos;&apos;&apos; : Includes another javascript file inside the current script (if it hasn&apos;t already been included) - i.e. if a script is included twice with a require directive, it will only actually be included once.
# &apos;&apos;&apos;load&apos;&apos;&apos; : Registers a dependency to another script, but doesn&apos;t include it in the same bundle.  This may be used if your script requires code from another javascript, but you don&apos;t want it all to be bundled into the same javascript file.  This may help with caching in certain cases.
# &apos;&apos;&apos;require-css&apos;&apos;&apos; : Registers a dependency to a CSS file.   If your script depends on a CSS file, then it can be registered in this way.


===Brief Example===

&apos;&apos;scriptA.js&apos;&apos;:
&lt;code&gt;
//require &lt;scriptB.js&gt;
alert(&apos;You are in script A&apos;);
&lt;/code&gt;

&apos;&apos;scriptB.js&apos;&apos;:
&lt;code&gt;
alert(&apos;You are in script B&apos;);
&lt;/code&gt;

If you loaded &apos;&apos;scriptA.js&apos;&apos;, it would actually result in the following javascript being executed:
&lt;code&gt;
alert(&apos;You are in script B&apos;);
alert(&apos;You are in script A&apos;);
&lt;/code&gt;

Notice that it included &apos;&apos;scriptB.js&apos;&apos; inside script A before the alert of script A.  That is why script B&apos;s alert comes first.  Note that this example won&apos;t work if you simply try to load scriptA.js directly in Apache.  These directives are only evaluated if the scripts are served by Xataface.  Here is a simple Xataface action that demonstrates how to use this in your Xataface script.

====Creating a custom action====

In your application directory, create an &apos;&apos;actions&apos;&apos; directory if you don&apos;t already have one.  Then create a single file named &apos;&apos;hello.php&apos;&apos; with the following content:
&lt;code&gt;
class actions_hello {
    function handle($params){
        $jsTool = Dataface_JavascriptTool::getInstance();
        $jsTool-&gt;addPath(&apos;js&apos;, DATAFACE_SITE_URL.&apos;/js&apos;);
        $jsTool-&gt;import(&apos;scriptA.js&apos;);
        echo &apos;&lt;html&gt;&lt;head&gt;&lt;/head&gt;&lt;body&gt;&apos;.$jsTool-&gt;getHtml().&apos;&lt;/body&gt;&lt;/html&gt;&apos;;
        exit;
    }
}
&lt;/code&gt;

&apos;&apos;&apos;About this code:&apos;&apos;&apos;

&lt;code&gt;$jsTool = Dataface_JavascriptTool::getInstance();&lt;/code&gt;
We start by obtaining an instance of the JavascriptTool.  This is the object that does all of the magic of compiling your scripts and managing dependencies.

&lt;code&gt;$jsTool-&gt;addPath(&apos;js&apos;, DATAFACE_SITE_URL.&apos;/js&apos;);&lt;/code&gt;
This line adds the &apos;&apos;js&apos;&apos; directory to the tool&apos;s include path, and specifies (with the 2nd parameter) the URL to reach this directory also.  The JavascriptTool works like most source code compilers.  You need to give it the path where it can expect to find its libraries and scripts.  Only paths that you add here will be searched for javascripts.  You can add as many paths as you like.  By default it will have the DATAFACE_PATH/js and the XATAJAX_PATH/js directories in the include path so you can directly reference any scripts in those directories always.

&lt;code&gt; $jsTool-&gt;import(&apos;scriptA.js&apos;);&lt;/code&gt;
This is where we declare that we want to use &apos;&apos;scriptA.js&apos;&apos; in the current request.  This line then assumes that the scriptA.js file is located in one of the directories of the current include path.  In our case we make sure that it resides in the DATAFACE_SITE_PATH/js directory.

&lt;code&gt;echo &apos;&lt;html&gt;&lt;head&gt;&lt;/head&gt;&lt;body&gt;&apos;.$jsTool-&gt;getHtml().&apos;&lt;/body&gt;&lt;/html&gt;&apos;;&lt;/code&gt;
On this line we simply output the HTML script tags that the javascript tool generates linking to our resulting script.  


Now we can test our our action by going to the page index.php?-action=hello.  If everything worked correctly you should see the appropriate alert dialogs appear  - first telling you you&apos;re in Script B, then telling you you&apos;re in Script A.  If it doesn&apos;t work, you should check your javascript error logs to see what went wrong.

&apos;&apos;&apos;NOTE:&apos;&apos;&apos; - This simple example actually shows you the step of writing out the HTML tags explicitly with the getHtml() method.  If you are using a standard Xataface template that is based on the Dataface_Main_Template.html template, then this step is unnecessary because the XataJax module will automatically include this HTML just before the closing &lt;/body&gt; tag in your pages.



</content>
	<keywords>XataJax, compiler, javascript, css, compiler</keywords>
	<language>en</language>
	<original_page></original_page>
</wiki>
<wiki id="wiki?page_id=61">
	<page_name>lookup</page_name>
	<page_id>61</page_id>
	<page_title>The Lookup Widget</page_title>
	<content>Return to [[widget:type]] page to see list of all widget types.
Back to [[fields.ini file]] to see other fields.ini directives.

[[toc]]

===Synopsis===

The lookup widget allows users to look a record from another table to insert into the field.  It is like a select widget except that it doesn&apos;t use a vocabulary.  Instead you just specify a table on which it should search using the widget:table directive.  In order to use the lookup widget to edit a field, you should set the [[widget:type]] directive of the [[fields.ini file]] for the field to &apos;&apos;&apos;lookup&apos;&apos;.  I.e.
&lt;code&gt;
[fieldname]
    widget:type=lookup
    widget:table=mytable
&lt;/code&gt;

&apos;&apos;&apos;Note that the lookup widget requires the [[widget:table]] directive to be set to the target table of the lookup or it will not work properly.&apos;&apos;&apos;

===Required Directives===

The following [[fields.ini file]] directives are required to accompany the field definition if a lookup widget is used:

{| class=&quot;listing listing2&quot;
|-
! Name
! Description
! Version
|-
| widget:table
| The name of the table in which the lookup widget should look up related records.
| 1.0
|}


===Optional Directives===

The following additional optional directives may be used to customize the behaviour of the lookup widget:

{| class=&quot;listing listing2&quot;
|-
! Name
! Description
! Version
|-
| widget:filters:-limit
| Sets the number of records that are shown by default in the lookup widget.  Default is 30 if this is omitted. E.g.&lt;code&gt;widget:filters:-limit=100&lt;/code&gt; to show 100 records at a time.
| 1.0
|-
| widget:filters:-sort
| Specifies the columns to sort the results on. E.g. &lt;code&gt;widget:filters:-sort=category_name asc, year desc&lt;/code&gt;
| 1.0
|-
| widget:filters:*
| Any valid Xataface directive can be used to filter the results by specifying widget:filters:param  (where &quot;param&quot; is a valid Xataface GET parameter, which could include a column name to filter results on, or other filter directives). &lt;code&gt;widget:filters:country=Canada&lt;/code&gt; To only show results with Country=Canada.
| 1.0
|-
| widget:filters:*=$*
| Dynamic filters.  Causes the options in the record browser to be filtered on the value of another field in the form.  e.g. &lt;code&gt;widget:filters:country_id=&quot;$country_id&quot;&lt;/code&gt; would show only results with records having country_id matching the value of the &apos;country_id&apos; field in the current form.
| 1.3.1
|}

See [[URL Conventions]] for an overview of the types of GET parameters Xataface can take.  Any GET parameters that manipulate a query can be used with the widget:filters:* directive to modify the query results that are shown in the lookup widget.


===Example===

In this example we have a field named appointee that is supposed to reference the contacts table.  So in the [[fields.ini file]] we would have:

&lt;pre&gt;
[appointee]
    widget:type=lookup
    widget:table=contacts
&lt;/pre&gt;

Initially we just have a little find icon next to the field. If the user clicks it, a dialog pops up enabling them to search for the contact that they want:

[[Image:http://media.weblite.ca/files/photos/Picture%2023.png?max_width=640]]


===Additional Tips===

Although the lookup widget does not use a vocabulary as indicated in the Synopsis above, it is still useful to define a vocabulary in the fields.ini file for this field. The reason is because the lookup widget is only used with the edit action, where you are inserting or editing data into the field. However, it is not used to the display the data in the view or list actions. Therefore, you must still have a vocabulary defined to properly display these values.

In order to customize the display of the lookup widget&apos;s select list, you must edit the delegate class for the table which is referenced by the widget:table directive. There are two important points to note:

# The items in the selection list are formatted based on the getTitle(&amp;$record) delegate class function if it is defined. However, ...
# The Search box will search on text in VARCHAR and TEXT fields. If you need to search for data in numeric fields, you can create a grafted field using a function such as CONCAT() to display numbers as text.

Links:
* [http://xataface.com/forum/viewtopic.php?f=4&amp;t=6723 Lookup widget on view with compound primary key]</content>
	<keywords>lookup widget, widget:filters, widget:-filters:limit, widget:table</keywords>
	<language>en</language>
	<original_page>0</original_page>
</wiki>
<wiki id="wiki?page_id=128">
	<page_name>list:type</page_name>
	<page_id>128</page_id>
	<page_title>list:type relationships.ini file directive</page_title>
	<content>Return to [[relationships.ini file]]

[[toc]]

The list:type directive allows you to override the default list that is used to display related records.  As of Xataface 1.3 there is only one possible value that will have any effect on this directive: &quot;treetable&quot;.  

Setting
&lt;code&gt;
list:type=treetable
&lt;/code&gt;
will cause the related records to be displayed as an expandable/collapsible tree table as shown here:
&lt;nowiki&gt;&lt;img src=&quot;http://media.weblite.ca/files/photos/Screen%20shot%202011-04-29%20at%2011.49.33%20AM.png?max_width=640&quot;/&gt;&lt;/nowiki&gt;

===Prerequisites===

The TreeTable component needs to be able to figure out the logical children of each record in order to know what to show when a row is expanded.  You can use either the [[meta:class]] directive of the [[relationships.ini]] file to specify a relationship as a &quot;children&quot; relationship, or you can implement the [[getChildren]] method of the table delegate class to manually define a record&apos;s child elements.

==See Also==

* [[getChildren]]
* [[meta:class]]
* [[getParent]]</content>
	<keywords></keywords>
	<language>en</language>
	<original_page></original_page>
</wiki>
<wiki id="wiki?page_id=127">
	<page_name>meta:class</page_name>
	<page_id>127</page_id>
	<page_title>meta:class relationships.ini file directive</page_title>
	<content>Return to [[relationships.ini file]]

[[toc]]

The &apos;&apos;meta:class&apos;&apos; directive allows you to ascribe special meaning to a relationship which Xataface can use in various parts of your application to provide enhanced capabilities.

For example you can specify a relationship as a &quot;parent&quot; relationship, thereby using the relationship to obtain the &quot;parent&quot; of records of this table.  This can be used to help build breadcrumbs.

You can also specify a relationship as a &quot;children&quot; relationship which would treat records in the relationship as children of the current record.  This can be used in conjunction with the [[list:type]]=treetable directive of the [[relationships.ini file]] to build a tree table that navigates all child records and subtrees.

The Dataface_Record class contains some methods for retrieving the parent and children of records and these methods will take into account any settings you make here.

===Allowed Values===

{| class=&quot;listing listing2&quot;
|-
! Name
! Description
! Version
|-
| parent
| Designates the relationship as a &apos;parent&apos; relationship, meaning that the first record in this relationship will be treated as the parent of the current record.  This setting can be overridden by the [[getParent]] method of the table delegate class if implemented.
| 0.8
|-
| children
| Designates the relationship as a &apos;children&apos; relationship meaning that records of the the relationship will be treated as a children.  This setting can be overridden by the [[getChildren]] method of the table delegate class if implemented.
| 0.8
|}


==See Also==

# &apos;&apos;&apos;[[list:type]]&apos;&apos;&apos; - [[relationships.ini file]] directive to use a treetable for the related record list of a relationship.
# &apos;&apos;&apos;[[getChildren]]&apos;&apos;&apos; - Delegate class method to explicitly define the Dataface_Record objects that are to be considered as child records of the current record.
# &apos;&apos;&apos;[[getParent]]&apos;&apos;&apos; - Delegate class method to explicitly define the Dataface_Record object that is to be considered as the parent record of the current record.
</content>
	<keywords></keywords>
	<language>en</language>
	<original_page></original_page>
</wiki>
<wiki id="wiki?page_id=106">
	<page_name>__global__</page_name>
	<page_id>106</page_id>
	<page_title>__global__ section for the fields.ini file</page_title>
	<content>Return to [[fields.ini file]]

[[toc]]

===Synopsis===

The fields.ini file supports a __global__ section that applies to all fields in the current table.  This is particularly useful for setting up default functionality that you wish to see on all fields except a few.  For example you may wish to have all fields hidden from list view by default, and only explicitly enable a few.  Same for CSV export or the details form.

===Example 1: Hiding All Fields from List View===

In the fields.ini file:
&lt;code&gt;
[__global__]
    ;; hide all of the fields from list view
    visibility:list=hidden

[first_name]
    ;; show the first name in list view 
    visibility:list=visible

[last_name]
    visibility:list=visible

;;.... etc....
&lt;/code&gt;

In the above example we used the __global__ section to declare that we want all fields to be hidden from list view by default.  Then we explicitly showed first_name and last_name in list view. In this case only first_name and last_name will appear in the list view.

==See Also==

*[[fields.ini file]]
*[[visibility:list]]</content>
	<keywords>__global__, fields.ini, visibility:list</keywords>
	<language>en</language>
	<original_page></original_page>
</wiki>
<wiki id="wiki?page_id=95">
	<page_name>validators</page_name>
	<page_id>95</page_id>
	<page_title>validators:NAME fields.ini directive</page_title>
	<content>Return to [[fields.ini file]]

[[toc]]

===Synopsis===

In the fields.ini file you can specify validation rules to be applied to any field by adding the validators:NAME directive in that field&apos;s section of the [[fields.ini file]].

===Available Validators===

{| class=&quot;listing listing2&quot;
|-
! Name
! Description
! Value
! Version
|-
| required
| Field is required
| 1
| All
|-
| maxlength
| Maximum number of characters allowed.
| $length
| All
|-
| minlength
| Minimum number of characters allowed.
| $length
| All
|-
| rangelength
| Range (min and max) characters allows
| $min,$max
| All
|-
| email
| Input must be syntactically correct email address.
| 1
| All
|-
| emailorblank
| Accepts an email address or a blank field.
| 1
| All
|-
| regex
| Input must match the provided regular expression.
| A regular expression
| All
|-
| lettersonly
| Input must contain only letters (i.e. [a-zA-Z]
| 1
| All
|-
| numeric
| The input must contain a valid positive or negative integer or decimal number.
| 1
| All
|-
| nopunctuation
| The input must not contain any of these characters: &lt;nowiki&gt;( ) . / * ^ ? # ! @ $ % + = , &quot; &apos; &amp;gt; &amp;lt; ~ [ ] { }.&lt;/nowiki&gt;
| 1
| All
|-
| nonzero
| The input must not begin with zero.
| 1
| All
|-
| uploadedfile
| The element must contain a successfully uploaded file.
| 1
| All
|-
| maxfilesize
| The uploaded file must be no more than $size bytes.
| $size
| All
|-
|filename
| The uploaded file must have a filename that matches the regular expression $file_rx.
| $file_rx
| All
|}


===Examples===

To make a the first_name field required we add the following to the [[fields.ini file]]:
&lt;code&gt;
[first_name]
    validators:required=1
&lt;/code&gt;

&apos;&apos;&apos;Note that fields that are declared NOT NULL in the database are required by default.&apos;&apos;&apos;.  If you wanted to remove the &apos;&apos;required&apos;&apos; validator from a field that is NOT NULL in the database you would add the following to the [[fields.ini file]]:
&lt;code&gt;
[first_name]
    validators:required=0
&lt;/code&gt;

===See Also===

* [[fieldname__validate]] - For more complex validation you can define the [[fieldname__validate]] method in the [[Delegate class methods|Table Delegate Class]].
* [http://www.devarticles.com/c/a/Web-Graphic-Design/Using-HTML-Quickform-for-Form-Processing/12/ HTML_QuickForm article] going over HTML_Quickform validation.  Dataface&apos;s forms are built on HTML_QuickForm.
* [http://xataface.com/documentation/tutorial/getting_started/validation Form Validation] - Section from getting started tutorial introducing form validation in a tutorial format.

</content>
	<keywords>validation, form validation, validators,validator:name</keywords>
	<language>en</language>
	<original_page></original_page>
</wiki>
<wiki id="wiki?page_id=96">
	<page_name>validators:VALIDATOR_NAME:message</page_name>
	<page_id>96</page_id>
	<page_title>validators:VALIDATOR_NAME:message directive for the fields.ini file</page_title>
	<content>Return to [[fields.ini file]]

[[toc]]

===Synopsis===

If you want to customize the error message associated with a particular [[validator|validation rule]] you can use the validators:VALIDATOR_NAME:message directive in the fields.ini file.

===Format===

&lt;code&gt;
[myfield]
    validators:VALIDATOR_NAME:message = MESSAGE
&lt;/code&gt;

===Examples===

If you don&apos;t like the default error message that is displayed when you make the first_name field required, you can customize it with your own message.  E.g.
&lt;code&gt;
[first_name]
    validators:required=1
    validators:required:message = &quot;Please enter your first name&quot;
&lt;/code&gt;

===See Also===

* [[validators]] - The [[fields.ini file]] directive for adding a validation rule to a field.  This directive must be used in conjunction with [[validators]].
* [[fieldname__validate]] - For more complex validation rules you can define them in the table delegate class.
* [http://xataface.com/documentation/tutorial/getting_started/validation Form Validation] - Section in the Getting Started tutorial on form validation.</content>
	<keywords>validation messages,error messages,form validation rules</keywords>
	<language>en</language>
	<original_page></original_page>
</wiki></record>