<?xml version="1.0"?>
<record><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=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=26">
	<page_name>permissions.ini_file</page_name>
	<page_id>26</page_id>
	<page_title>permissions.ini_file</page_title>
	<content>==The permissions.ini File==

[[toc]]

The permissions.ini file stores custom permissions and roles that can be used by an application.  It is an optional file that should be placed in the application root directory (i.e. the same directory where your conf.ini, and index.php files are located).

The permissions.ini file allows you to define two things:

# Permissions
# Roles (i.e. sets of permissions).

Permissions and roles are used throughout Xataface to limit access to actions, records, fields, and relationships.  For example, each action in your application can specify a permission that is necessary to perform the action.  Your delegate classes may include getPermissions() methods to define what permissions a user gets when interacting with different records.  This file (permissions.ini) simply defines the permissions that can be used by your application.  It doesn&apos;t actually assign those permissions.  Assigning permissions is the job of the getPermissions() (or getRoles()) method.

===Defining Permissions===

Permissions are defined by standalone properties in the beginning of the permissions.ini file.  For example, if you were desiging a proof-reading application, you might need permissions for &quot;submit_for_proof&quot;, or &quot;approve_text&quot; to correspond with the submitting a document to be proof-read, and approving a document&apos;s proof.  In this case we would have the following at the beginning of our permissions.ini file:

&lt;code&gt;
submit_for_proof = Submit a document to be proofread
approve_text = &quot;Approve this document&apos;s proof&quot;
&lt;/code&gt;

The left side of the equals sign is the name of the permission.  The right side contains a human readable description of the permission and what it is for.

===Limiting Access to Actions based on Permissions===

At this point these permissions don&apos;t do anything.  In order to be useful we need reference these permissions from an action or a section.  For example, let&apos;s create an action called &quot;submit_for_proof&quot; which displays a form for a user to submit a document record to be proofread.

Our actions.ini file entry might look something like:

&lt;code&gt;
[submit_for_proof]
    url=&quot;{$this-&gt;url(&apos;-action=submit_for_proof&apos;)}&quot;
    label=&quot;Submit document for proof&quot;
    category=record_actions
    permission=submit_for_proof
    template=submit_for_proof.html
&lt;/code&gt;

And for completeness, since this make-believe action specifies th &quot;submit_for_proof.html&quot; template, we&apos;ll create the &quot;submit_for_proof.html&quot; template in the templates directory:

&lt;code&gt;
&lt;html&gt;&lt;body&gt;You have permission to perform this action.&lt;/body&gt;&lt;/html&gt;
&lt;/code&gt;

===Defining Who Get&apos;s Which Permissions===

Finally, in order to benefit from permissions, your application has to decide that it is going to use permissions (unless you define a getPermissions() method, users are granted ALL permissions by default.  Hence if you try to access our submit_for_proof action, we&apos;ll see it without any problem.  Regardless of who we are.  So let&apos;s create a simple, but restrictive getPermissions() method in our application delegate class:

&lt;code&gt;
&lt;?php
class conf_ApplicationDelegate {
    function getPermissions(&amp;$record){
        return Dataface_PermissionsTool::READ_ONLY();
    }
}
&lt;/code&gt;

Now if we try to access our submit_for_proof action it will give us a &quot;Permission Denied&quot; message, because we are only granted READ ONLY permissions (which is a role that includes the view permission and some others - but not our custom &quot;submit_for_proof&quot; permission.

Now we&apos;ll make a small modification to our getPermissions() method to provide us with our submit_for_proof permission:

&lt;code&gt;
&lt;?php
class conf_ApplicationDelegate {
    function getPermissions(&amp;$record){
        $perms =  Dataface_PermissionsTool::READ_ONLY();
        $perms[&apos;submit_for_proof&apos;] = 1;
        return $perms;
    }
}
&lt;/code&gt;

Now if we try to access our submit_for_proof action, it will show us our template with no error messages (hopefully).


===Roles===

Roles are sets of permissions.  They are defined in the permissions.ini file as sections with lists of included permissions.  It might be handy to create roles such as EDITOR or MANAGER which contain sets of permissions that are meant to be assigned to users of those types.  For example an EDITOR may have the view and edit permissions, but not the delete permission.  A MANAGER might have the view, edit, and delete permissions.  You can define these two roles in the permissions.ini file as follows:

&lt;code&gt;
[EDITOR]
    view=1
    edit=1

[MANAGER]
    view=1
    edit=1
    delete=1
&lt;/code&gt;

Then we could assign these roles to users using the Dataface_PermissionsTool::getRolePermissions() method:

&lt;code&gt;
function getPermissions(&amp;$record){
    $user =&amp; Dataface_AuthenticationTool::getInstance()-&gt;getLoggedInUser();
    if ( $user and $user-&gt;val(&apos;role&apos;) == &apos;EDITOR&apos; ){
        return Dataface_PermissionsTool::getRolePermissions(&apos;EDITOR&apos;);
    } else if ( $user and $user-&gt;val(&apos;role&apos;) == &apos;MANAGER&apos; ){
        return Dataface_PermissionsTool::getRolePermissions(&apos;MANAGER&apos;);
    }
    return Dataface_PermissionsTool::READ_ONLY();
}
 &lt;/code&gt;

Or equivalently we could use the getRoles() method of our delegate class instead of getPermissions():

&lt;code&gt;
function getRoles(&amp;$record){
    $user =&amp; Dataface_AuthenticationTool::getInstance()-&gt;getLoggedInUser();
    if ( $user and $user-&gt;val(&apos;role&apos;) == &apos;EDITOR&apos; ){
        return &apos;EDITOR&apos;;
    } else if ( $user and $user-&gt;val(&apos;role&apos;) == &apos;MANAGER&apos; ){
        return &apos;MANAGER&apos;
    }
    return &apos;READ ONLY&apos;;
}
&lt;/code&gt;

===Xataface Core Permissions &amp; Roles===

Xataface is distributed with its own permissions.ini file that defines some core permissions and roles.  You can look at this permissions.ini file (located in the Xataface directory) to see what the format should look like.  Any settings you place in your application&apos;s permissions.ini file will augment or override settings in Xataface&apos;s file.

Some core permissions include:


{| class=&quot;listing listing2&quot;
|-
! Name
! Description
! Version
|-
| view
| Permission to view a record or field.  This permission is required to access the view tab, and several other details tabs.
| 0.6
|-
| list
| Permission to access the list tab.
| 0.6
|-
| calendar
| Permission to access the calendar tab.
| 0.6
|-
| edit
| Permission to edit a record or field.  This also gives access to the edit tab.
| 0.6
|-
| new
| Permission to edit a record or field for the purpose of creating a new record.  This permission is required to access the new record form.
| 0.6
|-
| select_rows
| Permission to select rows in list view to perform actions on them.
| 0.6
|-
| post
| Permission to post a record using HTTP POST
| 0.6
|-
| copy
| Permission to copy a record.
| 0.6
|-
| update_set
| Permission to perform an update on a result set (i.e. access the update set action).
| 0.8
|-
| add new related record
| Permission to add a new record to a relationship.  See [[Relationship Permissions]]
| 0.6
|-
| add existing related record
| Permission to add an existing record to a relationship.  See [[Relationship Permissions]]
| 0.6
|-
| view related records
| Permission to view the records in a relationship. See [[Relationship Permissions]]
| 1.0
|-
| delete
| Permission to delete a record.
| 0.6
|-
| delete found
| Permission to access the delete found set action (to delete multiple records at a time).
| 0.6
|-
| show all
| Permission to access show all records action.
| 0.6
|-
| remove related record
| Permission to remove a record from a relationship.  See [[Relationship Permissions]]
| 0.6
|-
| delete related record
| Permission to delete a record in a relationship.  This is stronger than the remove related record permission in that it allows the user to delete the record from the database.  See [[Relationship permissions]]
| 0.6
|-
| find
| Permission to perform the find action.
| 0.6
|-
| import
| Permission to perform the import action (to import records into the database).
| 0.6
|-
| export_csv
| Permission to perform the Export CSV action (to export the result set in comma-separated-value format).
| 0.6
|-
| export_xml
| Permission to perform the Export XML action (to export the result set as XML).
| 0.8
|-
| translate
| Permission to translate a record into another language.  This permission provides access to the &quot;translate&quot; tab.
| 0.8
|-
| history
| Permission to view history information for a record (e.g. the history tab).  This requires that history be enabled.
| 0.8
|-
| edit_history
| Permission to edit history information such as undo/redo support for a record.
| 0.8
|-
| navigate
| Permission to navigate through records of a table.
| 0.6
|-
| reorder_related_records
| Permission to reorder the records of a relationship (this is different than just sorting).  It sets a default order for the records.  Requires the metafields:order directive to be set for the relationship.
| 0.6
|-
| ajax_save
| Permission to save a record through AJAX.
| 0.8
|-
| ajax_load
| Permission to load a record through AJAX.
| 0.8
|-
| ajax_form
| Permission to access the inline editing ajax form for a record.
| 0.8
|-
| find_list
| Permission to search current table.
| 0.6
|-
| find_multi_table
| Permission to perform a site-wide search.
| 0.8
|-
| register
| Permission to register for an account.
| 0.8
|-
| xml_view
| Permission to view a result set as xml.
| 0.8
|-
| view_xml
| View the XML for an individual record.
| 0.8
|-
| manage_output_cache
| Management permission to clear the output cache.
| 0.8
|-
| manage_migrate
| Permission to access the migration tool to migrate between versions.
| 0.8
|-
| manage
| Permission to access the management control panel.
| 0.8
|-
| manage_build_index
| Permission to rebuild the search index.
| 0.8
|-
| expandable
| Whether the record can be expanded in the left nav menu
| N/A
|}

Some core roles include:

{| class=&quot;listing listing2&quot;
|-
! Name
! Permissions Included
! Version
|-
| READ ONLY
| view, list, calendar, view xml, show all, find, navigate, ajax_load, find_list, find_multi_table, rss, export_csv, export_xml, and export_json
| 0.6
|-
| EDIT
| All permissions in READ ONLY, and edit, add new related record, add existing related record, add new record, remove related record, reorder_related_records, import, translate, new, ajax_save, ajax_form, history, edit_history, copy, update_set, and select_rows
| 0.6
|-
| DELETE
| All permissions in EDIT, and delete and delete found.
| 0.6
|-
| OWNER
| All permissions in DELETE except navigate, new, and delete found.
| 0.6
|-
| REVIEWER
| All permissions in READ ONLY, and edit and translate.
| 0.6
|-
| USER
| All permissions in READ ONLY, and add new related record.
| 0.6
|-
| ADMIN
| All permissions in DELETE and xml_view
| 0.6
|-
| MANAGER
| All permissions in ADMIN and manage, manage_output_cache, manage_migrate, manage_build_index, and install.
| 0.6
|}

===Extending and Overriding Roles===

The cleanest and easiest way to define a new role is to extend an existing role.  Xataface allows you to extend roles via the &apos;&apos;&apos;extends&apos;&apos;&apos; keyword.  For example, if you wanted to create a role &apos;&apos;&apos;TEST ROLE&apos;&apos;&apos; that contained all of the same permissions as the READ ONLY role, you could define it as follows in your application&apos;s permissions.ini file:

&lt;code&gt;
[TEST ROLE extends READ ONLY]
&lt;/code&gt;

If we wanted it to contain the same permissions as READ ONLY but to also allow the edit permission we would define it as:
&lt;code&gt;
[TEST ROLE extends READ ONLY]
    edit=1
&lt;/code&gt;

If we wanted to disallow the list permission, we would do something like:

&lt;code&gt;
[TEST ROLE extends READ ONLY]
    edit=1
    list=0
&lt;/code&gt;

===Overriding Existing Roles===

You can also redefine existing roles:

&lt;code&gt;
[READ ONLY extends READ ONLY]
    my_permission=1
&lt;/code&gt;

This is handy if you have added your own custom permissions that you feel should be included in a core role.

Note that there are some caveats regarding the order of how these roles are defined. Please refer to this forum post for more details: 
[http://www.xataface.com/forum/viewtopic.php?t=6187 Overriding Roles / Permissions]

==See Also==

* [[Relationship Permissions]]
* [[getPermissions]] - The getPermissionsMethod
* [[Delegate class methods]] - Delegate class methods.
* [http://xataface.com/documentation/tutorial/getting_started/permissions Getting started with Xataface permissions]</content>
	<keywords>permissions.ini, getPermissions, permissions</keywords>
	<language>en</language>
	<original_page>0</original_page>
</wiki>
<wiki id="wiki?page_id=10">
	<page_name>preferences</page_name>
	<page_id>10</page_id>
	<page_title>preferences</page_title>
	<content>==Xataface Preferences==

[[toc]]

Xataface preferences can be defined in 3 ways:

# In the &apos;&apos;[_prefs]&apos;&apos; section of rhe [[conf.ini file]] for global static preferences.
# Implementing the [[getPreferences]] method in the [[Application Delegate Class]]
# In the [[__prefs__]] section of the fields.ini file for a table for static preferences on that table.  (Limited to only certain preferences).

===Example [_prefs] section===
In the conf.ini
&lt;code&gt;
[_prefs]
    hide_updated=1
    hide_posted_by=1
&lt;/code&gt;

===Example [[getPreferences]] method===
In the [[Application Delegate Class]]:
&lt;code&gt;
function getPreferences(){
    return array(&apos;hide_update&apos;=&gt;1, &apos;hide_posted_by&apos;=&gt;1);

}
&lt;/code&gt;

===Available Preferences===

{| class=&quot;listing listing2&quot;
! Name
! Description
! Default
! Version
|-
| show_result_stats
| Show the result statistics (e.g. found x of y records in table z)
| 1
| 0.6
|-
| show_jump_menu
| Show he drop-down menu that allows you to &quot;jump&quot; to any record in the found set.
| 1
| 0.6
|-
| show_result_controller
| Show Next, previous, page number .. links...
| 1
| 0.6
|-
| show_table_tabs
| Show  Details, List, Find, etc... tabs.
| 1
| 0.6
|-
| show_actions_menu
| Show New record, Show all, delete, etc..
| 1
| 0.6
|-
| show_logo
| Show logo at top of app
| 1
| 0.6
|-
| show_tables_menu
| Show the tabs to select a table.
| 1
| 0.6
|-
| show_search
| Show search field in upper right.
| 1
| 0.6
|-
| show_record_actions
| Show actions related to particular record
| 1
| 0.6
|-
| show_bread_crumbs
| Show bread crumbs at top of page to show where you are.
| 1
| 0.6
|-
| show_record_tabs
| View, Edit, Translate, History, etc...
| 1
| 0.6
|-
| show_record_tree
| Show tree to navigate the relationships of this record.
| 1
| 0.6
|-
| list_view_scroll_horizontal
| Whether to scroll list horizontal if it exceeds page width
| 1
| 0.6
|-
| list_view_scroll_vertical
| Whether to scroll list vertical if it exceeds page height.
| 1
| 0.6
|-
| hide_posted_by
| Whether to hide the &apos;&apos;posted by&apos;&apos; text in glance lists (e.g. in the view tab, the related records are shown in the left column.  This hides the &apos;&apos;posted by&apos;&apos; text next to each related record.
| 0
| 1.0b4
|-
| hide_updated
| Whether to hide the &apos;&apos;updated&apos;&apos; text in the glance lists (e.g. in the view tab, the related records are shown in the left column.  This hides the &apos;&apos;updated&apos;&apos; text next to each related record.
| 0
| 1.0b4
|-
| SummaryList_logo_width
| The width of the logo to be used as the preview image in summary lists.
| null
| 0.7
|-
| SummaryList_hideSort
| Hides the sort control for a summary list (the box that allows users to sort by column).
| 0
| 0.7
|-
| hide_user_status
| Hides the user&apos;s status (e.g. &quot;You are logged in as ...&quot;
| 0
| 0.7
|-
| hide_personal_tools
| Hides the personal tool links in upper right.  This includes likes such as &quot;Control Panel&quot; and &quot;My Profile&quot;
| 0
| 0.7
|-
| hide_resultlist_controller
| Hides the controller for a result list (E.g. next/back/results per page etc...).
| 0
| 0.7
|-
| hide_related_sections
| Hides the sections of the view tab that show the related records.  These are the sortable section boxes.  Not the related tabs.
| 0
| 1.3
|-
| hide_record_search
| Hides the record search form that appears in the view tab.  Not to be confused with the find tab.
| 0
| 1.3
|-
| show_resultlist_controller_only_when_needed
| Sets the resultlist controller (e.g. back/next/results per page/etc...) to only show up if paging is required (i.e. if there are more records than can be shown on one page (according to the &apos;-limit&apos; parameter).
| 0
| 1.0
|-
| hide_record_view_logo
| Hides the logo for a record that appears in the upper left of the view tab for each record.
| 0
| 0.7
|-
| horizontal_tables_menu
| Whether to force the tables menu to appear as tabs along the top of the page (alternative is as a menu on the left). If there are 10 or fewer allowed tables, then the default is 1, otherwise the default is set to 0.
| 1
| 0.6
|-
| hide_result_filters
| In list view, setting this value to 1 will cause the column filters to be hidden (the select lists to filter the results).
| 0
| 0.7
|-
| disable_select_rows
| A value of 1 causes the checkboxes in each row of the list view to be hidden.
| 0
| 0.7
|-
| result_list_use_geturl
| Use the getURL() method to link to records in the list view rather than the default (which uses the -cursor parameter).
| 0
| 0.7
|-
| disable_ajax_record_details
| Whether to disable the ajax record details (the &apos;+&apos; sign beside each record in list view that expands to show the record details.
| 1
| 0.7
|-
| use_old_resultlist_controller
| As of Xataface 1.1, a new style result list controller is used that resembles facebook.  It is more slimmed down and is easier to manage.  If you prefer the old controller, set this preference to 1.
| 0
| 1.1
|}

===Inverse Preferences===

The following preferences perform the inverse of some of the options above. When these options are set to 1, their respective option is set to 0.

{| class=&quot;listing listing2&quot;
! Name
! Inverse
|-
| hide_nav_menu
| show_tables_menu
|-
| hide_view_tabs
| show_table_tabs
|-
| hide_result_controller
| show_result_controller
|-
| hide_table_result_stats
| show_result_stats
|-
| hide_search
| show_search
|}
</content>
	<keywords>preferences, prefs, getPreferences</keywords>
	<language>en</language>
	<original_page>0</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=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=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=20">
	<page_name>relationships.ini_file</page_name>
	<page_id>20</page_id>
	<page_title>relationships.ini_file</page_title>
	<content>==relationships.ini File Reference==

[[toc]]

===Overview===

The relationship.ini file is a configuration file which is associated with a single table of a database application.  It provides metadata about the table&apos;s relationships to other tables to help Xataface dictate how they should be included in the application.  

===Field Directives===

The following directives may be added to a field&apos;s section of the relationship.ini file to customize the field&apos;s behavior.  Some directives are not applicable to all fields.

{| class=&quot;listing listing2&quot;
|-
! Name
! Description
! Version
|-
| __sql__
| The SQL query that defines this relationship. 
| all
|-
| [[action:visible]]
| A boolean value (0 or 1) that indicates whether this relationship should be visible in the record tabs.
| all
|-
| [[action:condition]]
| An expression that evaluates to a boolean that determines at runtime whether the relationship&apos;s tab should appear in the record tabs.
| all
|-
| [[action:delegate]]
| The name of an alternative action that can be used instead of the standard related records list.  One possible value for this would be &quot;related_records_checkboxes&quot; which would provide the user with a checkbox group to select the records that should be part of the relationship rather than the usual related record list.
| 1.0
|-
| [[section:limit]]
| Integer.  The number of records to show in the related record sections (in the view tab).  Default is 5.
| 1.0
|-
| [[section:visible]]
| Boolean value (0 or 1) indicating whether the relationship information should appear as a section on the left side of the table.
| all
|-
| [[actions:addexisting]]
| Boolean value (0 or 1) indicating whether the action to add existing records should exist in this relationship.
| all
|-
| [[actions:addnew]]
| Boolean value (0 or 1) indicating whether the action to add news records should exist in this relationship.
| all
|-
| [[action:label]]
| The label that appears in the relationship tab for this relationship. 
| all
|-
| [[list:type]]
| Optional type of list to use for the related record list.  Possible value: &quot;treetable&quot;
| 0.8
|-
| [[meta:class]]
| An optional special class to assign to the relationship.  E.g. &quot;parent&quot; or &quot;children&quot;.
| 0.8
|-
| [[metafields:order]]
| If the relationship should have a default order this specifies the field that should be used for this sort. 
| all
|-
| [[visibility:fieldName]]
| If given the value hidden will make that particular fieldName disappear in the relationship.  This will only be applied for that particular relationship.  
| all
|-
| [[visibility:find]]
| If given the value hidden this will cause the related fields to not appear on the find form.  Normally each relationship is provided a section of the find form to enable users to find records that contain at least one match in the related records.  
| 1.3rc4
|-
| [[vocabulary:existing]]
| Specifies a valuelist that can be used to provide the set of records that can be added to this relationship.  If target table has a single column primary key then the valuelist should use the primary key for the value.  If it has a multi-column primary key, then the value should be in the form key1=value1&amp;key2=value2 etc...  See also [[relationshipname__getAddableValues]] delegate class method for a programatic solution.
| 1.0
|}

==Relationship Permissions==

See [[Relationship Permissions]]

==See Also==

* [http://xataface.com/documentation/tutorial/getting_started/relationships Getting started with relationships]</content>
	<keywords>relationships.ini file, relationships</keywords>
	<language>en</language>
	<original_page>0</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=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=58">
	<page_name>Selected_Records_Actions</page_name>
	<page_id>58</page_id>
	<page_title>Selected_Records_Actions</page_title>
	<content>==Creating a Custom &apos;&apos;Selected Records&apos;&apos; Action==

[[toc]]

If you view the &apos;&apos;list&apos;&apos; tab in any of your Xataface applications, you&apos;ll notice that there is a checkbox next to each row of the list, and there are a number of actions listed at the bottom of the list that you can perform on the selected records.  Xataface comes pre-built with only a few of these actions:

# Delete selected
# Update selected
# Copy selected

However it is quite easy to add your own actions here that are performed on selected records.  This article describes exactly how to do this.

===What is a &apos;&apos;Selected Record&apos;&apos; action?===

A &apos;&apos;Selected Record&apos;&apos; action is no different than any other action in Xataface, except that it is meant to act on the records that have been selected in the list tab.

==Example Action:  Approve Records==

Consider a news site where news stories are automatically imported into the database en masse, but each news story has a field &apos;&apos;approved&apos;&apos; to indicate whether the store has been approved to appear on the site yet.   The usage pattern of this application involves a lot of looking through lists of news stories and approving them.  Therefore it would be convenient if the user could just select the rows that he wants to approve and click a button to approve them all.

Out of the box Xataface would allow the user to select the records, click &apos;&apos;update selected records&apos;&apos;, then update them all via the &apos;&apos;update selected records&apos;&apos; form.  But avoiding this extra step will improve usability greatly.

===Step 1: Design the Action===

First we need to specifically decide how our action will work.  In this case, the flow goes as follows:

# User selects the news items they want to approve.
# User clicks the &apos;&apos;Approve Selected&apos;&apos; button. (to be created)
# Our action approves the selected records.
# User is automatically redirected back to the list tab with a message stating how many records were successfully approved, and whether there were any errors.

===Step 2: Gather Our Tools===

Before we actually create the action, let&apos;s look at a few tools that we&apos;ll be using from the Xataface framework to make this happen.

# In the [[actions.ini file]], the &apos;&apos;[[selected_result_actions]]&apos;&apos; category is reserved for actions that act on selected records of the list tab.  E.g.&lt;code&gt;
[delete_selected]
    ...
    category=selected_result_actions
    ...
&lt;/code&gt;
# The [http://dataface.weblite.ca/df_get_selected_records df_get_selected_records()] function returns an array of [http://dataface.weblite.ca/Dataface_Record Dataface_Record] objects that represent the rows that were selected to initiate the action.  E.g.&lt;code&gt;
$app =&amp; Dataface_Application::getInstance();
$query =&amp; $app-&gt;getQuery();
$records = df_get_selected_records($query);
foreach ($records as $record){
    ...
}
&lt;/code&gt;
# The [http://dataface.weblite.ca/checkPermission Dataface_Record::checkPermission()] method allows us to see if the current user has access to a specific permission on the given record.  We&apos;ll use this method to ensure that the user has permission to approve the news record. E.g.&lt;code&gt;
if ( !$record-&gt;checkPermission(&apos;edit&apos;, array(&apos;field&apos;=&gt;&apos;approved&apos;)) ){
    return PEAR::raiseError(&quot;You don&apos;t have permission to edit the approved field for this record.&quot;);
}
&lt;/code&gt;
# The Xataface will pass the redirect URL where your action should send the user upon completion of the action as the &apos;&apos;--redirect&apos;&apos; attribute of the &apos;&apos;POST&apos;&apos; variables.  This value is base64_encoded so you&apos;ll need to decode it before redirecting.  E.g.:&lt;code&gt;
if ( @$_POST[&apos;--redirect&apos;] ) 
    $url = base64_decode($_POST[&apos;--redirect&apos;]);
$url .= &apos;&amp;--msg=&apos;.urlencode($updated.&apos; records were deleted.&apos;);
header(&apos;Location: &apos;.$url);
exit;
&lt;/code&gt;

===Step 3: Create the Action===

We will call our action &apos;&apos;approve_news&apos;&apos; so we&apos;ll place it in the &apos;&apos;actions/approve_news.php&apos;&apos; file of our application:
&lt;code&gt;
&lt;?php
class actions_approve_news {
    function handle(&amp;$params){
        // First get the selected records
        $app =&amp; Dataface_Application::getInstance();
        $query =&amp; $app-&gt;getQuery();
        $records =&amp; df_get_selected_records($query);

        $updated = 0;  // Count the number of records we update
        $errs = array();   // Log the errors we encounter

        foreach ($records as $rec){
            if ( !$rec-&gt;checkPermission(&apos;edit&apos;), array(&apos;field&apos;=&gt;&apos;approved&apos;)) ){
                $errs[] = Dataface_Error::permissionDenied(
                    &quot;You do not have permission to approve &apos;&quot;.
                    $rec-&gt;getTitle().
                    &quot;&apos; because you do not have the &apos;edit&apos; permission.&quot;);
                continue;
            }
            $rec-&gt;setValue(&apos;approved&apos;, 1);
 
            $res = $rec-&gt;save(true /*secure*/);
            if ( PEAR::isError($res) ) $errs[] = $res-&gt;getMessage();
            else $updated++;
            
        }
        
        if ( $errs ){
            // Errors occurred.  Let&apos;s let the user know.
            // The $_SESSION[&apos;--msg&apos;] content will be displayed to the user as a message
            // in the next page request.
            $_SESSION[&apos;--msg&apos;] = &apos;Errors Occurred:&lt;br/&gt; &apos;.implode(&apos;&lt;br/&gt; &apos;, $errs);
        } else {
            $_SESSION[&apos;--msg&apos;] = &quot;No errors occurred&quot;;
        }
        

        $url = $app-&gt;url(&apos;-action=list&apos;);   // A default URL in case no redirect was supplied
        if ( @$_POST[&apos;--redirect&apos;] ) $url = base64_decode($_POST[&apos;--redirect&apos;]);
        $url .= &apos;&amp;--msg=&apos;.urlencode($updated.&apos; records were deleted.&apos;);

        // Redirect back to the previous page
        header(&apos;Location: &apos;.$url);
        exit;
    }
}
&lt;/code&gt;

===Step 4: Add the action to your actions.ini file===

The actions.ini file allows us to specify how and where this action is used, and by whom.  We can specify permissions that are required to perform the action, conditions that are required to display the action, confirmation messages that are to be displayed to the user when they are about to perform the action, and more.  Our [[actions.ini file]] entry looks like:

&lt;code&gt;
[approve_news]
    label=&quot;Approve&quot;
    description=&quot;Approve selected records&quot;
    permission = edit
    category=selected_result_actions
    confirm=&quot;Are you sure you want to approve the selected records?&quot;
    icon=&quot;${dataface_site_url}/images/approve.gif&quot;
    condition=&quot;$query[&apos;-table&apos;] == &apos;news&apos;&quot;
&lt;/code&gt;

This should be fairly straight forward.  The only special items here are the &apos;&apos;category&apos;&apos; and &apos;&apos;confirm&apos;&apos; directives.  The &apos;&apos;condition&apos;&apos; directive tells Xataface that this action should only be shown for the &apos;&apos;news&apos;&apos; table. 

The &apos;&apos;confirm&apos;&apos; directive defines a confirmation message that should be displayed to the user when they attempt to approve records.

The &apos;&apos;icon&apos;&apos; directive allows you to specify the path to an icon to display for the action.  In our case we have an icon located in the images directory of our application.

===Step 5: Trying it out===

Now when we go to the &apos;&apos;list&apos;&apos; tab of the &apos;&apos;news&apos;&apos; table there is an &apos;&apos;Approve&apos;&apos; button along the bottom where it says &quot;With Selected&quot;.  You we can click on this button to approve any of the selected rows.


	</content>
	<keywords></keywords>
	<language>en</language>
	<original_page>0</original_page>
</wiki>
<wiki id="wiki?page_id=16">
	<page_name>sendRegistrationActivationEmail</page_name>
	<page_id>16</page_id>
	<page_title>sendRegistrationActivationEmail</page_title>
	<content>==sendRegistrationActivationEmail() Hook==

A hook that can be implemented in the [[Application Delegate Class]] or the [[Table Delegate Class]] to override the sending of an activation email to the user.

===Signature===

function sendRegistrationActivationEmail( Dataface_Record &amp;$record, string $activationURL ) : mixed

====Parameters====

{| class=&quot;listing listing2&quot;
! Name
! Description
|-
| &amp;$record
| A Dataface_Record object encapsulating the record that is being inserted in the users table for this registration.
|-
| $activationURL
| The URL where the user can go to activate their account.
|-
| returns
| Mixed. If this method returns a PEAR_Error object, then registration will fail with an error.
|}

===Example===

&lt;code&gt;
&lt;?php
class conf_ApplicationDelegate {

    function sendRegistrationActivationEmail(&amp;$record, $activationURL){
        // mail the admin to let him know that the registration is occurring.
        $username = $record-&gt;val(&apos;username&apos;);
        $email = $record-&gt;val(&apos;email&apos;);
        
        mail($email, &apos;Welcome to the team&apos;, 
            &apos;Welcome &apos;.$record-&gt;val(&apos;username&apos;).
            &apos;.  You have been successfully registered.  
             Please visit &apos;.$activationURL.&apos; to activate your account&apos;
        );
    }
}
&lt;/code&gt;

===See Also===
* [[beforeRegister]]
* [[afterRegister]]
* [[validateRegistrationForm]]
* [[getRegistrationActivationEmailInfo]]
* [[getRegistrationActivationEmailSubject]]
* [[getRegistrationActivationEmailMessage]]
* [[getRegistrationActivationEmailParameters]]
* [[getRegistrationActivationEmailHeaders]]</content>
	<keywords></keywords>
	<language>en</language>
	<original_page>0</original_page>
</wiki>
<wiki id="wiki?page_id=91">
	<page_name>setSecurityFilters</page_name>
	<page_id>91</page_id>
	<page_title>setSecurityFilter() method</page_title>
	<content>== Example ==

In the delegate class for the users table:

&lt;code&gt;
&lt;?php
class tables_users {
    function init(&amp;$table){
        if ( !isAdmin() ){
            $table-&gt;setSecurityFilter(array(&apos;group_id&apos;=&gt;10));
        }
    }
}
&lt;/code&gt;

This will only set the filter on non-admin users (assuming that you have defined a function isAdmin() to tell you if the current user is an admin user.</content>
	<keywords></keywords>
	<language>en</language>
	<original_page></original_page>
</wiki>
<wiki id="wiki?page_id=31">
	<page_name>ShoppingCart</page_name>
	<page_id>31</page_id>
	<page_title>ShoppingCart</page_title>
	<content>==Xataface Shopping Cart Module==

[[toc]]

Status: Under development
Current Version: 0.2

===Synopsis===

Add a shopping cart to your xataface application.  You can treat any record as a product that can be sold.  Includes Paypal connectivity, shipping calculation, and more.

===Requirements===

* Xataface 1.0 or higher
* PHP 5 or higher
* MySQL 4.1 or higher

===Installation Instructions===

# Download the ShoppingCart module, extract it, and place the ShoppingCart directory in your Xataface modules directory. (i.e. /path/to/xataface/modules/ShoppingCart).
# Add the following line to the [_modules] section of your [[conf.ini file]]:&lt;code&gt;
modules_ShoppingCart=modules/ShoppingCart/ShoppingCart.php
&lt;/code&gt;
# Add the following to the beginning of your [[index.php file]]:&lt;code&gt;
function __autoload($class){
    if ( $class == &apos;ShoppingCart&apos; ) require_once &apos;modules/ShoppingCart/lib/ShoppingCart/ShoppingCart.class.php&apos;;
}
&lt;/code&gt;
# In the [[fields.ini file]] for any table whose records you wish to represent items for sale, add the following:&lt;code&gt;
[__implements__]
    InventoryItem=1
&lt;/code&gt;
# Specify which fields should be used for the item description, price, width, height, length, and weight in the [[fields.ini file]] for each table whose records you wish to represent items for sale by adding the following directives to the appropriate fields:&lt;code&gt;
ShoppingCart.description=1
ShoppingCart.unitPrice=1
ShoppingCart.weight=1
ShoppingCart.width=1
ShoppingCart.height=1
ShoppingCart.length=1
&lt;/code&gt; E.g. if your table has a field named &quot;&quot;price&quot;&quot; that you want to represent the unit price, you would have something like:&lt;code&gt;
[price]
    ShoppingCart.unitPrice=1
&lt;/code&gt;  The shopping cart module will make its best guess on which fields to use for these values if they are not explicitly specified.
# Specify the paypal account where money should be deposited by adding the following to your application&apos;s [[actions.ini file]]:&lt;code&gt;
[view_cart]
    paypal.account=&quot;youremail@example.com&quot;
&lt;/code&gt;


===Usage Instructions===

Once the Shopping Cart module is installed you can:

# Add items to your shopping cart
# View your cart contents
# Checkout and pay with paypal

====Adding Items to the Cart====

In the View tab of any salable record, you&apos;ll notice a little block on the left side of the page with the heading &quot;Add Item to Cart&quot;.  This includes a field to specify the quantity and a button to add the item to the shopping cart.

====Viewing Cart Contents====

The Shopping Cart module automatically introduces an action to view the cart contents.  This action is named &quot;view_cart&quot;.  Hence you can always view the cart contents by entering the URL: index.php?-action=view_cart .

====Checking Out====

# View the cart contents.
# Click &quot;Check out&quot;
# This will take you to a paypal page to pay for your items.


==Actions==

This module adds the following actions to your application.

{| class=&quot;listing listing2&quot;
|-
! Name
! Content-type
! Description
! Version
|-
| checkout
| text/html
| Sends user to paypal to pay for the contents of their cart.
| 0.1
|-
| calculate_shipping
| text/html
| Calculates the shipping charges for the cart.
| 0.1
|-
| add_to_cart
| text/html
| Adds an item to the cart.
| 0.1
|-
| clear_cart
| text/html
| Empties the shopping cart.
| 0.1
|-
| get_shipping_provinces
| text/json
| Returns JSON array of provinces for a given country.
| 0.1
|-
| invoices
| text/html
| Displays the current user&apos;s invoices.
| 0.1
|-
| payment_complete
| text/html
| Page that is displayed after a successful payment on paypal.
| 0.1
|-
| paypal_ipn
| none
| Handles paypal events such as successful payments.
| 0.1
|-
| refresh_shipping_methods
| text/html
| Refreshes the shipping methods available to the system.
| 0.1
|-
| set_shipping_method
| text/html
| Sets the selected shipping method to a particular method.
| 0.1
|- 
| view_cart
| text/html
| View the cart contents.
| 0.1
|}

==Blocks and Slots==

This module adds the following blocks and slots to your applications.

{| class=&quot;listing listing2&quot;
|-
! Name
! Description
! Version
|-
| shipping_method
| A block with a form to select the shipping method.
| 0.1
|-
| add_to_cart
| A block with a form to add a record/item to the shopping cart.
| 0.1 
|}

==Application Delegate Class Hooks==

You can modify the shopping cart behavior by defining the following methods to the application delegate class.

{| class=&quot;listing listing2&quot;
|-
! Name
! Description
! Version
|-
| isShippingMandatory
| Returns a boolean value indicating whether the user must select a shipping method.
| 0.1
|-
| getDefaultShippingMethod
| Returns a string with the name of the default shipping method to be used.
| 0.1
|}


==Table Delegate Class Hooks==

You can modify the behavior of the shopping cart by defining the following methods to the delegate class of any table that implements the InventoryItem ontology (i.e. any table that is to be used to store products that can be added to the cart).

{| class=&quot;listing listing2&quot;
|-
! Name
! Description
! Version
|-
| field__taxes
| A calculated field that returns an associative array of all applicable taxes for a product.
| 0.1
|}

==Internal Storage==

This module creates the following tables to store its data:

===dataface__invoices===

The dataface__invoices table stores the actual invoices for purchases made.  An invoice is automatically created as soon as the user &quot;checks out&quot;.

{| class=&quot;listing listing2&quot;
|-
! Column Name
! Data Type
! Description
! Version
|-
| InvoiceID
| int(11)
| Auto incrementing primary key for the invoice.
| 0.1
|-
| dateCreated
| datetime
| The date that the invoice was created.
| 0.1
|-
| dateModified
| datetime
| The date that the invoice was last modified
| 0.1
|-
| status
| enum
| The status of the invoice (either PENDING, PAID, or APPROVED).
| 0.1
|-
| amount
| decimal(10,2)
| The total amount on the invoice.
| 0.1
|-
| paymentMethod
| varchar(32)
| The name of the payment method used.
| 0.1
|-
| referenceID
| varchar(64)
| ??
| 0.1
|-
| username
| varchar(32)
| The username of the user who owns this invoice.
| 0.1
|-
| firstName
| varchar(32)
| The first name of the payer.
| 0.1
|-
| lastName
| varchar(32)
| The last name of the payer.
| 0.1
|-
| address_name
| varchar(100)
| The name on the shipping address.
| 0.1
|-
| address1
| varchar(100)
| The shipping address line 1.
| 0.1
|-
| address2
| varchar(100)
| The shipping address line 2.
| 0.1
|-
| city
| varchar(40)
| The shipping address city.
| 0.1
|-
| province
| varchar(2)
| The shipping province or state.
| 0.1
|-
| country
| varchar(2)
| The shipping country.
| 0.1
|-
| postalCode
| varchar(32)
| The shipping postal code.
| 0.1
|-
| shipping_method
| varchar(50)
| The name of the shipping method to use.
| 0.1
|-
| phone
| varchar(32)
| The phone number of the payer.
| 0.1
|-
| email
| varchar(127)
| The email address of the buyer.
| 0.1
|-
| data
| text
| Serialize shopping cart data.
| 0.1
|}


===dataface__shipping_methods===

Stores the available shipping methods.

{| class=&quot;listing listing2&quot;
|-
! Column Name
! Data Type
! Description
! Version
|-
| shipping_method_id
| int(11)
| Auto increment ID for a shipping method.
| 0.1
|-
| shipping_method_name
| varchar(50)
| The name of the shipping method.
| 0.1
|-
| shipping_method_label
| varchar(100)
| The label for the shipping method (displayed to the user).
| 0.1
|-
| shipping_method_enabled
| tinyint(1)
| Whether or not this shipping method is currently enabled.
| 0.1
|-
| shipping_method_module
| varchar(32)
| The name of the handler that this shipping method belongs to.
| 0.1
|}

==Payment Handlers==

Information about payment handlers to be added here.

==Shipping Handlers==

The Shopping Cart module is itself modular, allowing you to develop custom shipping handlers for different types of shipping.  A shipping handler is responsible for calculating shipping costs to a destination address.  Currently only a UPS shipping handler has been created, but it is not difficult to create other handlers.

===Shipping Handler Public Interface===

{| class=&quot;listing listing2&quot;
|-
! Method
! Description
! Version
|-
| calculateShipping
| Calculates the shipping cost for the current shopping cart, and adds the shipping cost to the cart as a line item.
| 0.1
|-
| getInfo
| Returns an array of shipping methods that can be handled by this handler.
| 0.1
|}






</content>
	<keywords></keywords>
	<language>en</language>
	<original_page>0</original_page>
</wiki>
<wiki id="wiki?page_id=86">
	<page_name>site_with_backoffice</page_name>
	<page_id>86</page_id>
	<page_title></page_title>
	<content>==How to build a site with an optional login form==
To publish a public site with data without any need to login to access, here is the code :
&lt;code&gt;
function getPermissions(&amp;$record){
    if ( isAdmin() ) return Dataface_PermissionsTool::ALL();
    else return Dataface_PermissionsTool::READ_ONLY();
} 
&lt;/code&gt;
In this way, you still can login to administrate your data.</content>
	<keywords></keywords>
	<language>en</language>
	<original_page></original_page>
</wiki>
<wiki id="wiki?page_id=87">
	<page_name>sql_delegate_method</page_name>
	<page_id>87</page_id>
	<page_title>__sql__ Delegate Method</page_title>
	<content>return to [[Delegate class methods]]

===Synopsis===

The __sql__ delegate class method can be defined in any delegate class to specify the SQL query that should be used to fetch records for a given table.  This method overrides the [[__sql__]] directive of the fields.ini file.  This strategy is primarily used to graft columns from another table onto the base table.

=====Use Caution=====

This is an advanced feature and, if used incorrectly, can muck up your application. Make sure that your SQL query includes a superset of the columns in the base table, and is a row-for-row match for the rows in the base table.  I.e. you should never use an internal join.  Always use a left join so that all of the rows of the base table are returned even if the join table doesn&apos;t have a corresponding row.

If you want to simply filter a table&apos;s records, and don&apos;t need to graft any additional columns onto the table, you should use the [[setSecurityFilters]] method.

===Example===

Given the table foo, its delegate class:

&lt;code&gt;
class tables_foo {
    function __sql__(){
        return &quot;select f.*, c.category_name from foo f left join categories c on f.category_id=c.category_id&quot;;
    }
}
&lt;/code&gt;

This effectively grafts a column &quot;category_name&quot; onto the foo table based on a join with the categories table.

</content>
	<keywords>__sql__, SQL queries, delegate class</keywords>
	<language>en</language>
	<original_page></original_page>
</wiki>
<wiki id="wiki?page_id=56">
	<page_name>struct</page_name>
	<page_id>56</page_id>
	<page_title>struct</page_title>
	<content></content>
	<keywords></keywords>
	<language>en</language>
	<original_page>0</original_page>
</wiki>
<wiki id="wiki?page_id=48">
	<page_name>tab</page_name>
	<page_id>48</page_id>
	<page_title>tab</page_title>
	<content>==tab directive of the fields.ini file==

[[toc]]

The &apos;&apos;tab&apos;&apos; directive of the [[fields.ini file]] specifies which tab of the record edit form a field should be displayed on.  Xataface supports multiple tabs on the edit form by way of this &apos;&apos;tab&apos;&apos; directive.  If no fields contain the &apos;&apos;tab&apos;&apos; directive then all fields are displayed in a single tab (named &apos;&apos;__main__&apos;&apos;).

==Example 1: Placing address info on separate tab==

Consider the following &apos;&apos;people&apos;&apos; table: 
&lt;code&gt;
CREATE TABLE `people` (
    person_id int(11) not null auto_increment primary key,
    first_name varchar(32) not null,
    last_name varchar(32) not null,
    address varchar(100),
    city varchar(100),
    province varchar(100),
    country varchar(100),
    postal_code varchar(20)
)
&lt;/code&gt;

We want to split the fields into two tabs:
* Personal Info
* Address Info

===Splitting form into tabs===
We&apos;ll do this in two steps.  We use the &apos;&apos;tab&apos;&apos; directive to assign all address-related fields to the &apos;&apos;address_info&apos;&apos; tab.  In the tables/people/fields.ini file:
&lt;code&gt;
[address]
    tab=address_info

[city]
    tab=address_info

[province]
    tab=address_info

[country]
    tab=address_info

[postal_code]
    tab=address_info
&lt;/code&gt;

Now, when we load the edit form of the &apos;&apos;people&apos;&apos; table, we see two tabs:

* __main__
* address_info

&lt;nowiki&gt;
&lt;img src=&quot;http://media.weblite.ca/files/photos/Picture 9.png?max_width=640&quot;/&gt;
&lt;img src=&quot;http://media.weblite.ca/files/photos/Picture 10.png?max_width=640&quot;/&gt;
&lt;/nowiki&gt;

&apos;&apos;__main__&apos;&apos; is the name assigned to the default tab (for all fields that don&apos;t have a tab defined explicitly.


===Customizing the tab labels===

Next we will customize the tab labels by adding the following to the beginning of the [[fields.ini file]]:
&lt;code&gt;
[tab:__main__]
    label=&quot;Personal Information&quot;

[tab:address_info]
    label=&quot;Address Information&quot;
&lt;/code&gt;

&lt;nowiki&gt;
&lt;img src=&quot;http://media.weblite.ca/files/photos/Picture 11.png?max_width=640&quot;/&gt;
&lt;img src=&quot;http://media.weblite.ca/files/photos/Picture 12.png?max_width=640&quot;/&gt;
&lt;/nowiki&gt;


===Reordering the tabs===

If we want to reorder the tabs so that the &apos;&apos;address_info&apos;&apos; tab comes first, we would just reorder the definitions of the tabs:
&lt;code&gt;
[tab:address_info]
    label=&quot;Address Information&quot;

[tab:__main__]
    label=&quot;Personal Information&quot;
&lt;/code&gt;

&lt;nowiki&gt;
&lt;img src=&quot;http://media.weblite.ca/files/photos/Picture 13.png?max_width=640&quot;/&gt;
&lt;/nowiki&gt;

===Try This Example App===

You can try this tiny sample application out [http://dev.weblite.ca/tab_test here].</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=24">
	<page_name>templates:tags:use_macro</page_name>
	<page_id>24</page_id>
	<page_title>templates:tags:use_macro</page_title>
	<content>==use_macro Template Tag==

===Synopsis===

The use_macro tag includes another template into the current template with the option to override certain sections.

===Parameters===

{| class=&quot;listing listing2&quot;
|-
! Name
! Description
! Version
|-
| file
| The path the template to include (within the templates directory).
| 0.6
|}

===Example===

In this example we will create a template for a user profile, but this template will include a slot that can be overridden by other templates to customize the user bio.

====user-profile.html====

&lt;code&gt;
&lt;html&gt;
&lt;head&gt;
    &lt;title&gt;User profile&lt;/title&gt;
&lt;/head&gt;
&lt;body&gt;
   &lt;h1&gt;User bio&lt;/h1&gt;
   &lt;div id=&quot;bio&quot;&gt;
   {define_slot name=&quot;bio&quot;}
        This text will be overridden by other templates to place the correct
        bio information.
   {/define_slot}
&lt;/body&gt;
&lt;/html&gt;
&lt;/code&gt;

====steve-profile.html====

&lt;code&gt;
{use_macro file=&quot;user-profile.html&quot;}
    {fill_slot name=&quot;bio&quot;}
        This is Steve&apos;s bio.  It will override the text in the bio slot.
    {/fill_slot}
{/use_macro}
&lt;/code&gt;

===See also:===

* [[xataface templates|Xataface templates]]
* [[templates:tags:define_slot|The define_slot tag]]
* [[templates:tags:fill_slot|The fill_slot tag]]
* [http://www.xataface.com/documentation/tutorial/getting_started/changing-look-and-feel Changing the Look &amp; Feel of Xataface] (From the Getting Started Tutorial)
* [http://www.xataface.com/documentation/tutorial/customizing-the-dataface-look-and-feel Cusomizing the Xataface Look &amp; Feel] Tutorial
</content>
	<keywords></keywords>
	<language>en</language>
	<original_page>0</original_page>
</wiki>
<wiki id="wiki?page_id=2">
	<page_name>testpage2</page_name>
	<page_id>2</page_id>
	<page_title>testpage2</page_title>
	<content>Another test page
[[testpage]]</content>
	<keywords></keywords>
	<language>en</language>
	<original_page>0</original_page>
</wiki>
<wiki id="wiki?page_id=177">
	<page_name>test_page_34</page_name>
	<page_id>177</page_id>
	<page_title>Hello World</page_title>
	<content>Hello world</content>
	<keywords></keywords>
	<language>en</language>
	<original_page></original_page>
</wiki>
<wiki id="wiki?page_id=44">
	<page_name>timestamp</page_name>
	<page_id>44</page_id>
	<page_title>timestamp</page_title>
	<content>Return to [[fields.ini file]]

A very simple sample of this could be your table contains the table date_created as a type of date.  In your fields.ini, you would include this:

&lt;code&gt;
[date_created]
timestamp=insert
widget:type=hidden
&lt;/code&gt;

The widget:type=hidden will make the field not visible during entry and editing.  And the timestamp=insert causes the field to be filled upon insertion of a new record.

===Possible Values===

* &apos;&apos;&apos;update&apos;&apos;&apos; - Causes timestamp to be updated whenever the record is modified.
* &apos;&apos;&apos;insert&apos;&apos;&apos; - Causes the timestamp to be updated only when the record is first inserted.</content>
	<keywords>timestamp, date, datetime</keywords>
	<language>en</language>
	<original_page>0</original_page>
</wiki>
<wiki id="wiki?page_id=49">
	<page_name>Troubleshooting</page_name>
	<page_id>49</page_id>
	<page_title>Troubleshooting</page_title>
	<content>==Xataface Troubleshooting==

This document is intended to help Xataface developers through some of the most common issues.

[[toc]]

==All I get is a blank white screen!==

The most common issue mentioned in the forums is that an application comes up with a blank white screen in the web browser.  This can happen for a number of reasons but the most common reason is because PHP has encountered a fatal error and your PHP installation is not set up to display errors.  

The first step to troubleshooting this problem must be to find out what the error is.  You can do that in one of the following ways:

# Check your Apache error log if you know where it is.  One common location on many linux installations is &lt;code&gt;
/var/log/httpd/error_log
&lt;/code&gt; but your system may have it located elsewhere.  If you cannot find your error log, continue to the next option.
# Turn on the &apos;&apos;display_errors&apos;&apos; flag in your &apos;&apos;php.ini&apos;&apos; file.  I.e., in your &apos;&apos;php.ini&apos;&apos; file, find where it says &lt;code&gt;
display_errors Off
&lt;/code&gt; and change it to &lt;code&gt;
display_errors On
&lt;/code&gt;.  After this is done, restart your apache webserver.  If you don&apos;t know where your &apos;&apos;php.ini&apos;&apos; file is located see the section later in this document on locating your &apos;&apos;php.ini&apos;&apos; file.  If you don&apos;t have access to your php.ini file, move on to the next option.
# In your application&apos;s &apos;&apos;.htaccess&apos;&apos; file, add the following directives to enable displaying errors:&lt;code&gt;
php_flag display_errors on
&lt;/code&gt; .  Note that this method will only work if your apache config file allows you to override these values at the directory level.  If you still get a blank white screen after this, continue to the next option.
# At the beginning of your application&apos;s index.php file, add the following:&lt;code&gt;
&lt;?php
error_reporting(E_ALL);
ini_set(&apos;display_errors&apos;, &apos;on&apos;);
&lt;/code&gt; .  Note that if the error occurs in the parsing or compiling of your PHP files you will still get a blank screen.  But this will at least display runtime errors on the page.

Once you can see the error messages that caused the blank white screen you are in a much better position to solve the problem.

==Locating your php.ini file==

Locating your &apos;&apos;php.ini&apos;&apos; file is actually quite easy.  The quickest way is to create a php script with the following contents:
&lt;code&gt;
&lt;?php
phpinfo();
&lt;/code&gt;
then navigate to this page in your web browser.  This look at the line where it says the &apos;&apos;php.ini file&apos;&apos;.  It will list the path there.</content>
	<keywords></keywords>
	<language>en</language>
	<original_page>0</original_page>
</wiki>
<wiki id="wiki?page_id=37">
	<page_name>URL_Conventions</page_name>
	<page_id>37</page_id>
	<page_title>URL_Conventions</page_title>
	<content>==Xataface URL Conventions==

[[toc]]

Xataface adheres to a few simple URL conventions for all of its actions.  When you understand how Xataface URLs work you begin to get far more out of your applications.  By specifying the appropriate query parameters to can jump directly to any point in your application, or produce a specific result set.

For example, the URL &apos;&apos;index.php?-table=people&apos;&apos; will take you to the &apos;&apos;people&apos;&apos; table (and since the default action for a Xataface application is &apos;&apos;list&apos;&apos;, it will take you to the &apos;&apos;list&apos;&apos; view.

You could be more explicit by specifying the action in the URL directly: &apos;&apos;index.php?-table=people&amp;-action=list&apos;&apos;.  This would take you to the same screen.  From this example, you see that you can specify such things as the table and action via GET parameters.  Xataface accepts many more GET parameters also, as you&apos;ll see in the next section.

===Available GET Parameters===


{| class=&quot;listing listing2&quot;
|-
! Name
! Description
! Default
! Version
|-
| -action
| Specifies the action to perform.  E.g. &apos;&apos;browse&apos;&apos;, &apos;&apos;list&apos;&apos;, &apos;&apos;find&apos;&apos;, &apos;&apos;edit&apos;&apos;, &apos;&apos;new&apos;&apos;, ... etc..
| list
| all
|-
| -table
| The name of the table to use as the context table.
| The first table in the [_tables] section of your [[conf.ini file]]
| all
|-
| -skip
| Skip a certain number of results in the current found set to display.  E.g. If there are 100 records in the table and you want to start browsing from the 30th record, you would set &apos;&apos;-skip=29&apos;&apos;.

Not to be confused with the &apos;&apos;-cursor&apos;&apos; parameter which is used to specify which record to view in the &apos;&apos;details&apos;&apos; tab.
| 0
| all
|-
| -limit
| The maximum number of records in the found set to display.
| 30
| all
|-
| -cursor
| The index of the record in the current found set that is treated as the &quot;current&quot; record.  This is used in the &apos;&apos;details&apos;&apos; tab to identify which record to act on.  E.g. which record to view or edit.
| 0
| all
|-
| -sort
| A comma-delimited list of columns to sort the result set on.
| null
| all
|-
| -relationship
| If we are browsing related records, this specifies the name of the relationship.
| null
| all
|-
| -related:start
| If we are browsing related records, this is the first record in the relationship to show.
| 0
| all
|-
| -related:limit
| If we are browsing related records, this is the number of records to show per page.
| 30
| all
|-
| -search
| A keyword search term to filter the found set on.  Any row containing any field that matches the query will be returned.
| null
| all
|-
| --no-query=1
| A flag to indicate that xataface should not query the database by default.  This flag is used in the new record form to prevent the form parameters from being interpreted as query parameters to search in the database.  If you set this flag, it likely result in a message saying &quot;No records found&quot;.  Generally you would only use this in a custom action where you are not relying on Xataface&apos;s default found set.
| 0
| 1.3
|}

There are many other GET parameters that are used in various contexts but the above parameters are available throughout the entire application.

===Finding Records using the URL===

Notice that all of the GET parameters mentioned in the previous section begin with a hyphen (i.e. &apos;-&apos;).  This is a convention Xataface uses to distinguish directives from search queries.  All parameters that do not begin with &apos;-&apos; are treated as a query to filter the found set.

For example, &apos;&apos;first_name=bob&apos;&apos; used as a GET parameter would cause the found set to be filtered so that only records where the &apos;&apos;first_name&apos;&apos; column contains the phrase &quot;bob&quot; are returned.  Putting this all together, suppose we wanted to show the list tab for the &apos;&apos;people&apos;&apos; table, but only wanted to show the people with first names containing &quot;bob&quot;:

index.php?-action=list&amp;-table=people&amp;first_name=bob

====Exact, Range, and Pattern Matching====

By default, queries on text columns look for partial matches.  I.e. if you search for &quot;bob&quot; it will match &quot;bob&quot;, &quot;bobby&quot;, &quot;rubob&quot;, and any other text that contains &quot;bob&quot;.  If you are only interested in finding records that match &apos;&apos;exactly&apos;&apos; &quot;bob&quot;, then you can prepend an &quot;=&quot; to the query.  E.g. &apos;&apos;first_name==bob&apos;&apos;, or the full URL:

index.php?-action=list&amp;-table=people&amp;first_name==bob

This should show the &apos;&apos;list&apos;&apos; tab for the &apos;&apos;people&apos;&apos; table with only records with first name exactly &quot;bob&quot;.

There are a number of modifiers that you can prepend to your query to modify how it is executed.  They are as follows:

=====Search Operators=====

{| class=&quot;listing listing2&quot;
|-
! Prefix
! Usage Example
! Description
|- 
| &gt;
| age=&gt;10
| Match records greater than search parameter.
|-
| &lt;
| age=&lt;10
| Match records less than search parameter.
|-
| &gt;=
| age=&gt;=10
| Match records greater than or equal to the search parameter.
|-
| &lt;=
| age=&lt;=10
| Match records less than or equal to the search parameter.
|-
| ..
| age=10..20
| Match records in a given range.
|-
| =
| first_name==bob
| Match records that exactly match the search parameter (if there is no prefix then it will search for partial matches on text/varchar/char fields.).
|-
| ~
| first_name=~a%
| Exact match, but you can include wildcards such as &apos;%&apos; and &apos;?&apos; in your search.
|}


=====Search Examples=====

Given the following data set:

{| class=&quot;listing listing2&quot;
|-
! first_name
! age
|-
| Bob
| 10
|-
| Cindy
| 12
|-
| Julie
| 6
|-
| Jake
| 8
|-
| Kabob
| 16
|}

Here are some example queries on this data set and their results:

{| class=&quot;listing listing2&quot;
|-
! Query
! Matches
|- 
| age=&gt;10 
| match records where &apos;&apos;age&apos;&apos; is greater than 10.  This includes &apos;&apos;Cindy&apos;&apos; and &apos;&apos;Kabob&apos;&apos;.
|-
| age=&lt;10 
| match records where &apos;&apos;age&apos;&apos; is less than 10.  This includes &apos;&apos;Julie&apos;&apos; and &apos;&apos;Jake&apos;&apos;
|-
| age=&gt;=10 
| match records where &apos;&apos;age&apos;&apos; is greater or equal to 10.  This includes &apos;&apos;Bob&apos;&apos;, &apos;&apos;Cindy&apos;&apos;, and &apos;&apos;Kabob&apos;&apos;.
|-
| age=&lt;=10
| match records where &apos;&apos;age&apos;&apos; is less than or equal to 10. This includes &apos;&apos;Bob&apos;&apos;, &apos;&apos;Julie&apos;&apos;, and &apos;&apos;Jake&apos;&apos;.
|-
| age=8..10
| match records where &apos;&apos;age&apos;&apos; is between 8 and 10.  This includes &apos;&apos;Bob&apos;&apos; and &apos;&apos;Jake&apos;&apos;.
|-
| first_name=bob
| Matches records where &apos;&apos;first_name&apos;&apos; contains &quot;bob&quot;.  This includes &apos;&apos;Bob&apos;&apos; and &apos;&apos;Kabob&apos;&apos;.
|-
| first_name==bob
| Matches records where &apos;&apos;first_name&apos;&apos; is exactly &quot;bob&quot;.  This includes &apos;&apos;Bob&apos;&apos; only.
|-
| first_name=~J%
| Matches records that begin with &quot;J&quot;.  This includes &apos;&apos;Jake&apos;&apos; and &apos;&apos;Julie&apos;&apos;
|}

====Matching on Related Records====

It is also possible to match records based on their related data (i.e. data that is not physically stored in the record itself, but in related records via a relationship).  For example if we want to find authors who have written about a particular topic, we would normally have to first find all of the articles that contain a topic, and then cross-reference that result against the &apos;&apos;authors&apos;&apos; table.  With Xataface we can perform this query directly from the &apos;&apos;authors&apos;&apos; table using something like the following query:
 index.php?-table=authors&amp;articles/title=sports
This assumes that the &apos;&apos;authors&apos;&apos; table has a relationship named &apos;&apos;articles&apos;&apos; that contains all of the articles that an author has written.  So the above query returns precisely those authors who have written at least one article whose &apos;&apos;title&apos;&apos; field contains the phrase &quot;sports&quot;.


=====Anatomy of a Related Query=====

 %relationship%/%field%=%query%
This matches all records in the current table such that at least one record in its &apos;&apos;&lt;relationship&gt;&apos;&apos; relationship matches the query: &apos;&apos;%field%=%query%&apos;&apos;.


====Using the &apos;&apos;OR&apos;&apos; Operator====

Xataface allows you to search for more than one value at a time using the &apos;&apos;OR&apos;&apos; operator.  E.g.
 first_name=bob+OR+steve
Would match all records with &apos;&apos;first_name&apos;&apos; containing &quot;bob&quot; or &quot;steve&quot;.
 first_name=bob+OR+=steve
Would match all records with &apos;&apos;first_name&apos;&apos; containing &quot;bob&quot; or exactly matching &quot;steve&quot;
 age=&lt;10+OR+&gt;20
Would match all records with age less than 10 or greater than 20.

====Combining Multiple Queries in One Request====

Xataface allows you to filter on more than one field at a time.  If you combine multiple queries in the same request it has the effect of strengthening the filter, matching only those rows that match &apos;&apos;both&apos;&apos; queries.  E.g.
 age=&gt;10&amp;first_name=bob
would match all records where &apos;&apos;age&apos;&apos; is greater than 10 &apos;&apos;&apos;AND&apos;&apos;&apos; that have &apos;&apos;first_name&apos;&apos; containing &quot;bob&quot;.

=====Examples of Combined Queries=====

Given the same data set as the previous set of examples:

{| class=&quot;listing listing2&quot;
|-
! first_name
! age
|-
| Bob
| 10
|-
| Cindy
| 12
|-
| Julie
| 6
|-
| Jake
| 8
|-
| Kabob
| 16
|}

 first_name=bob&amp;age=11
would return no matches because there are no records that contain both &apos;&apos;first_name&apos;&apos; &quot;bob&quot; and &apos;&apos;age&apos;&apos; 11.  However
 first_name=bob&amp;age=10
would return only &apos;&apos;Bob&apos;&apos; and
 first_name=bob&amp;age=16
would return only &apos;&apos;Kabob&apos;&apos;.

====Special Common Queries====

=====Search For Null or Blank Value=====

Searching for a null value or a blank value is an exact match for &quot;&quot;.  Therefore you can simply search for &quot;=&quot;.  E.g. To find records with a null or blank first_name you would use the query &apos;&apos;first_name==&apos;&apos;.  Or the full query:
 index.php?-table=people&amp;first_name==

=====Search for Non-blank Value=====

Searching for a non-blank value is the same as searching for a value greater than &quot;&quot;.  Therefore you can simply search for &quot;&gt;&quot;.  E.g. if you wanted to find records with a first_name, you would use the query &apos;&apos;first_name=&gt;&apos;&apos;.  Or the full query:
 index.php?-table=people&amp;first_name=&gt;

==Preserved vs Non-preserved Parameters==

As mentioned above any parameters that are prefixed by a hyphen (i.e. &quot;=&quot;) are treated as directives rather than search filters.  Hence if you want to use your own GET parameters you should always prefix them with a &quot;-&quot; to ensure that Xataface does not attempt to apply it as a search filter.  In order to keep a consistent context for users, all browsing within the same table preserves both search queries and directives.  Hence if you go to the URL:
 index.php?-table=people&amp;-action=list&amp;first_name=bob
It will show you the &apos;&apos;list&apos;&apos; tab of the &apos;&apos;people&apos;&apos; table with only those records with &apos;&apos;first_name&apos;&apos; &quot;bob&quot;.  Now if you click on the &apos;&apos;details&apos;&apos; tab it will preserve your query &apos;&apos;first_name&apos;&apos;.  The query will become something like:
 index.php?-table=people&amp;-action=details&amp;first_name=bob&amp;...etc... more parameters
(Although the parameters may appear in a different order).  This allows you to navigate forward and back to previous and next records and stay within the same found set.  It also ensures that if you click on the &apos;&apos;list&apos;&apos; tab to return to the list view, it will retain your place in the list.

Note that navigating within the same table it will also preserve your directives.  E.g. If you specify the &apos;&apos;-limit&apos;&apos; directive to show 100 records per page:
 index.php?-table=people&amp;-action=list&amp;-limit=100
And then you click on the &apos;&apos;details&apos;&apos; tab, it will retain your &apos;&apos;-limit&apos;&apos; parameter.  Of course the &apos;&apos;-limit&apos;&apos; parameter is not actually used by the &apos;&apos;details&apos;&apos; action because it works on only one record at a time (it uses the &apos;&apos;-cursor&apos;&apos; parameter instead), when you click back on the &apos;&apos;list&apos;&apos; tab it will still show you 100 records per page.

Because of this, we call the &apos;&apos;-limit&apos;&apos; parameter a preserved parameter.  It is retained when navigating within the same table.  &apos;&apos;&apos;Note:&apos;&apos;&apos; parameters are retained in the HTTP Query string, not in sessions or cookies.  This ensures that there are no surprises when you enter a URL to your Xataface application.

===Unpreserved Parameters===

If you &apos;&apos;don&apos;t&apos;&apos; want Xataface to preserve one of your parameters, you should prefix two hyphens to the parameter name.  I.e. &quot;--&quot;.  One example of an unpreserved parameters throughout Xataface applications is the &apos;&apos;--msg&apos;&apos; parameter.  The value of this parameter will be displayed on the page as an info message to the user.  Clearly you don&apos;t want this parameter preserved across requests, as you only want the user to see a message once.  E.g.
 index.php?--msg=Record+Successfully+saved.
Would didsplay the mesage &quot;Record Successfully Saved&quot; at the top of the page.  If you click on any link in the application, it will not retain the &apos;&apos;--msg&apos;&apos; parameter so you will not see the message on subsequent requests.

This parameter is useful if you want to give feedback to the user about an action that has been carried out.

===Summary===

{| class=&quot;listing listing2&quot;
|-
! Parameter Type
! Prefix
! Examples
! Description
|-
| Preserved
| -
| -limit, -skip, -cursor, -action, -table
| Parameter value is preserved when user navigates away from the page (within the same table).
|-
| Unpreserved Parameters
| --
| --msg
| Parameter is &apos;&apos;NOT&apos;&apos; retrained with the user navigates away from the page.
|}





</content>
	<keywords>URL Conventions, GET Parameters, POST parameters, Request Parameters</keywords>
	<language>en</language>
	<original_page>0</original_page>
</wiki>
<wiki id="wiki?page_id=115">
	<page_name>Using_RecordGrid</page_name>
	<page_id>115</page_id>
	<page_title>Using RecordGrid</page_title>
	<content>==Xataface RecordGrid Class and Template==

Also see [http://lamp.weblite.ca/dataface-0.6/docs/index.php?-table=Classes&amp;-action=browse&amp;ClassID=30| RecordGrid in the API Doc].


[[toc collapse=0]]

===Introduction===
As we learned in &apos;&apos;&apos;[http://xataface.com/documentation/tutorial/getting_started/dataface_actions Actions I: The Basics]&apos;&apos;&apos;, we can retrieve custom data from the DB in action via queries. This site deals with showing data in tabular form, like it could be received from even such a query. It is done by using Dataface_RecordGrid.


===First Example===
&lt;code&gt;
class actions_testTableAction {

	// Will be called from Xataface, if this action is called
	function handle(&amp;$params){
		$this-&gt;app =&amp; Dataface_Application::getInstance();  // reference to Dataface_Application object

		// Custom query
		$result = mysql_query(&quot;select * from testTable&quot;, $this-&gt;app-&gt;db());
		$body = &quot;&lt;br /&gt;&lt;br /&gt;&quot;;
		
		if(!$result)
		{
			// Error handling
			$body .= &quot;MySQL Error ...&quot;;
		}else
		{
			while($row = mysql_fetch_assoc($result))	// Fetch all rows
			{
				// Maybe do something with the single rows
				$data[] = $row;	// Add singe row to the data
			}
			mysql_free_result($result); // Frees the result after finnished using it

			$grid = new Dataface_RecordGrid($data);	// Create new RecordGrid with the data
			
			$body .= $grid-&gt;toHTML();	// Get the HTML of the RecordGrid
		}

		// Shows the content (RecordGrid or error message) in the Main Template
		df_display(array(&apos;body&apos; =&gt; $body), &apos;Dataface_Main_Template.html&apos;);
	}
}
&lt;/code&gt;

You get your data from the query, fetch it into an associative array, create with it an RecordGrid and use the toHTML function. This is sure better than manually create the html tags around the data.

=====Screenshot: Blank RecordGrid=====
&lt;nowiki&gt;
&lt;img src=&quot;http://i89.photobucket.com/albums/k234/horchr/xataface/RecordGrid_blank.png?max_width=610&quot;/&gt;
&lt;/nowiki&gt;

=====Screenshot: ResultList=====

&lt;nowiki&gt;
&lt;img src=&quot;http://i89.photobucket.com/albums/k234/horchr/xataface/RecordList.png?max_width=713&quot;/&gt;
&lt;/nowiki&gt;


===Colored Example===

As you see above, the resultlist has colored rows, our First Example not. But you can easily change this, when you override the Dataface_RecordGrid.html template:

&lt;code&gt;
&lt;table id=&quot;{$id}&quot; class=&quot;listing {$class}&quot;&gt;
	&lt;thead&gt;
		&lt;tr&gt;
		{foreach from=$labels item=label}
		&lt;th&gt;{$label}&lt;/th&gt;
		{/foreach}
		&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
		{section name=row loop=$data}
		&lt;tr class=&quot;listing {cycle values=&quot;odd,even&quot;}&quot;&gt;
			{foreach from=$columns item=col}
			&lt;td&gt;{$data[row][$col]}&lt;/td&gt;
			{/foreach}
		&lt;/tr&gt;
		{/section}
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;/code&gt;

The magic happens in &lt;tr class=&quot;listing {cycle values=&quot;odd,even&quot;}&quot;&gt;
The {cycle values=&quot;odd,even&quot;} value cycles these two values and creates so the alternating row classes, like they are in the RecordList. By the way, {cycle ...} is a Smarty Function, see [http://www.smarty.net/docsv2/en/language.custom.functions.tpl| Smarty Doc].

(Find fruther information to template overriding in the tutorial and its links: [http://xataface.com/documentation/tutorial/getting_started/changing-look-and-feel| Changing the Look and Feel])

=====Screenshot: colored RecordGrid=====

&lt;nowiki&gt;
&lt;img src=&quot;http://i89.photobucket.com/albums/k234/horchr/xataface/RecordGrid_colored.png?max_width=610&quot;/&gt;
&lt;/nowiki&gt;


===Example completly imitating ResultList===

The Colored Example doesn&apos;t look like the ResulList? Its rows aren&apos;t as high as theres? That&apos;s a styling matter or rather in this case a cause of the checkboxes. Here an example with checkboxes and added (empty) links, so it looks completly like the ResultList:

Change the part in action.php
&lt;code&gt;
			while($row = mysql_fetch_assoc($result))	// Fetch all rows
			{
				// Maybe do something with the single rows
				$row[&apos;&lt;input type=&quot;checkbox&quot;&gt;&apos;] = &apos;&lt;input type=&quot;checkbox&quot;&gt;&apos;;
				$data[] = $row;	// Add singe row to the data
			}
			mysql_free_result($result); // Frees the result after finnished using it

			$grid = new Dataface_RecordGrid($data,	// Create new RecordGrid with the data
				  array(&apos;&lt;input type=&quot;checkbox&quot;&gt;&apos;, &apos;testID&apos;, &apos;name&apos;, &apos;description&apos;, &apos;number&apos;),	
				//Order and selection of the colums
				  null);	// No other labels defined -&gt; it uses keys of the associative array
			
			$body .= $grid-&gt;toHTML();	// Get the HTML of the RecordGrid
&lt;/code&gt;

Dataface_RecordGrid.html template
&lt;code&gt;
&lt;table id=&quot;{$id}&quot; class=&quot;listing {$class}&quot;&gt;
	&lt;thead&gt;
		&lt;tr&gt;
		{foreach from=$labels item=label}
		&lt;th&gt;&lt;a class=&quot;unmarked_link&quot;&gt;{$label}&lt;/a&gt;&lt;/th&gt;
		{/foreach}
		&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
		{section name=row loop=$data}
		&lt;tr class=&quot;listing {cycle values=&quot;odd,even&quot;}&quot;&gt;
			{foreach from=$columns item=col}
			&lt;td&gt;&lt;a class=&quot;unmarked_link&quot;&gt;{$data[row][$col]}&lt;/a&gt;&lt;/td&gt;
			{/foreach}
		&lt;/tr&gt;
		{/section}
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;/code&gt;

=====Screenshot: RecordGrid completly imitating ResultList=====

&lt;nowiki&gt;
&lt;img src=&quot;http://i89.photobucket.com/albums/k234/horchr/xataface/RecordGrid_colored_checkboxes_links.png?max_width=610&quot;/&gt;
&lt;/nowiki&gt;

=====Screenshot: ResultList=====

&lt;nowiki&gt;
&lt;img src=&quot;http://i89.photobucket.com/albums/k234/horchr/xataface/RecordList.png?max_width=713&quot;/&gt;
&lt;/nowiki&gt;

===Try it out===

Use the following code with static test data and any template in this article (or even without overriding it) to try it out.

&lt;code&gt;
class actions_testTableAction {

	// Will be called from Xataface, if this action is called
	function handle(&amp;$params){
		$this-&gt;app =&amp; Dataface_Application::getInstance();  // reference to Dataface_Application object

		$result_dummy = array(
			array(&apos;testID&apos; =&gt; &apos;1&apos;, &apos;name&apos; =&gt; &apos;testname&apos;, 
				&apos;description&apos; =&gt; &apos;a short description&apos;, &apos;number&apos; =&gt; &apos;258&apos;),
			array(&apos;testID&apos; =&gt; &apos;2&apos;, &apos;name&apos; =&gt; &apos;another name&apos;, 
				&apos;description&apos; =&gt; &apos;a bit longer description to this data set&apos;, &apos;number&apos; =&gt; &apos;946&apos;),
			array(&apos;testID&apos; =&gt; &apos;3&apos;, &apos;name&apos; =&gt; &apos;dummy name&apos;, 
				&apos;description&apos; =&gt; &apos;yea, a dummy data set!&apos;, &apos;number&apos; =&gt; &apos;1342&apos;),
			array(&apos;testID&apos; =&gt; &apos;4&apos;, &apos;name&apos; =&gt; &apos;not empty&apos;, 
				&apos;description&apos; =&gt; &apos;this data set isn\&apos;t empty ...&apos;, &apos;number&apos; =&gt; &apos;282&apos;),
			array(&apos;testID&apos; =&gt; &apos;5&apos;, &apos;name&apos; =&gt; &apos;your entry&apos;, 
				&apos;description&apos; =&gt; &apos;this entry is only for you&apos;, &apos;number&apos; =&gt; &apos;79&apos;),
			array(&apos;testID&apos; =&gt; &apos;6&apos;, &apos;name&apos; =&gt; &apos;no idea&apos;, 
				&apos;description&apos; =&gt; &apos;running out of ideas ...&apos;, &apos;number&apos; =&gt; &apos;203&apos;),
			array(&apos;testID&apos; =&gt; &apos;7&apos;, &apos;name&apos; =&gt; &apos;the last one&apos;, 
				&apos;description&apos; =&gt; &apos;the end&apos;, &apos;number&apos; =&gt; &apos;26841&apos;)
		);
		$body = &quot;&lt;br /&gt;&lt;br /&gt;&quot;;
		
		foreach($result_dummy as $row)	// Fetch all rows
		{
			// Maybe do something with the singe rows
			$row[&apos;&lt;input type=&quot;checkbox&quot;&gt;&apos;] = &apos;&lt;input type=&quot;checkbox&quot;&gt;&apos;;
			$data[] = $row;	// Add singe row to the data
		}

		$grid = new Dataface_RecordGrid($data,	// Create new RecordGrid with the data
			array(&apos;&lt;input type=&quot;checkbox&quot;&gt;&apos;, &apos;testID&apos;, &apos;name&apos;, &apos;description&apos;, &apos;number&apos;),	
			//Order and selection of the colums
			  null);	// No other labels defined -&gt; it uses keys of the associative array

		$body .= $grid-&gt;toHTML();	// Get the HTML of the RecordGrid

		// Shows the content (RecordGrid or error message) in the Main Template
		df_display(array(&apos;body&apos; =&gt; $body), &apos;Dataface_Main_Template.html&apos;);
	}
}
&lt;/code&gt;
</content>
	<keywords>RecordGrid, Dataface_RecordGrid, data in tabular form</keywords>
	<language>en</language>
	<original_page></original_page>
</wiki>
<wiki id="wiki?page_id=15">
	<page_name>validateRegistrationForm</page_name>
	<page_id>15</page_id>
	<page_title>validateRegistrationForm</page_title>
	<content>==validateRegistrationForm() hook==

A hook that validates the input into the user registration form to make sure that the input is valid.

===Signature===

function validateRegistrationForm( array $values ) : mixed

====Parameters====

{| class=&quot;listing listing2&quot;
! Name
! Description
|-
| $values
| An associative array of the input values of the registration form.
|-
| returns
| Mixed. If this method returns a PEAR_Error object then the validation will fail - and the user will be asked to correct his input.
|}

===Example===

&lt;code&gt;
&lt;?php
class conf_ApplicationDelegate {
    function validateRegistrationForm($values){
        if ( $values[&apos;age&apos;] &lt; 18 ){
            return PEAR::raiseError(&quot;Sorry you must be at least 18 years old to join this site.&quot;);
        }
        return true;
    }
}
&lt;/code&gt;

===Validation via the Users table Delegate class===

Note that since the registration form is just a &quot;new record form&quot; for the users table, it is also possible (and preferred) to do validation through the users [[table delegate class]].

===See Also===

* [[afterRegister]]
* [[beforeRegister]]
* [[sendRegistrationActivationEmail]]
* [[getRegistrationActivationEmailInfo]]
* [[getRegistrationActivationEmailSubject]]
* [[getRegistrationActivationEmailMessage]]
* [[getRegistrationActivationEmailParameters]]
* [[getRegistrationActivationEmailHeaders]]</content>
	<keywords></keywords>
	<language>en</language>
	<original_page>0</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>
<wiki id="wiki?page_id=5">
	<page_name>valuelists.ini_file</page_name>
	<page_id>5</page_id>
	<page_title>valuelists.ini_file</page_title>
	<content>==valuelists.ini file Reference==

[[toc]]

The valuelists.ini file stores value lists that can be used as [[vocabulary|vocabularies]] for select lists, checkbox groups, and other widgets the provide the user with options to choose from.

Each table can have an associated valuelists.ini file located in its [[table configuration directory]]. E.g. for a table named &quot;people&quot; its valuelists.ini file will be stored in &quot;tables/people/valuelists.ini&quot;.

In addition you can define an application-wide valuelists.ini file in the root of your application&apos;s directory, whose valuelists can be used by any table.

===Syntax===

The valuelists.ini file uses [[INI file syntax]], where a valuelist is defined by a single section of the INI file.  E.g.

&lt;code&gt;
[colors]
    r=Red
    b=Blue
    g=Green
&lt;/code&gt;

This example would define a single valuelist named &quot;colors&quot; with 3 values: r,g, and b (with corresponding labels &quot;Red&quot;, &quot;Green&quot;, and &quot;Blue).  The values (the left of the equals sign) are stored in the database, while the labels are rendered on screen for the user&apos;s convenience.

===Dynamic Valuelists===

It is often advantageous to load valuelists from the database rather than store them directly in the valuelists.ini file.  The __sql__ directive allows you to specify an SQL query which selects up to 2 columns (the first is the id and the second, the label).

E.g.

&lt;code&gt;
[colors]
    __sql__ = &quot;select colorCode, colorName from colors&quot;
&lt;/code&gt;


===Defining Valuelists in a Delegate Class===

If you require more flexibility with the definition of your valuelists than can be gained from the valuelists.ini file, you can define your valuelist using PHP inside a delegate class.  Essentially you just create a method that returns an associative array, where the keys are the IDs that are stored in the database, and the values are the values that are visible in the select list.

e.g.  In either the application delegate class or a table delegate class:

&lt;code&gt;
function valuelist__colors(){
    return array(
        &apos;r&apos;=&gt;&apos;Red&apos;,
        &apos;g&apos;=&gt;&apos;Green&apos;,
        &apos;b&apos;=&gt;&apos;Blue&apos;
    );
}
&lt;/code&gt;

This method is called each time the valuelist is about to be used, so if your method performs any sort of intensive processing, it is a good idea to use a caching scheme so that it only runs the critical code once per request.  For example, you could use a static variable as follows:

&lt;code&gt;
function valuelist__colors(){
    static $colors = -1;
    if ( !is_array($colors) ){
        $colors = array();
        $res = mysql_query(&quot;select colorCode, colorName from colors&quot;, df_db());
        if ( !$res ) throw new Exception(mysql_error(df_db()));
        while ($row = mysql_fetch_row($res) ) $colors[$row[0]] = $row[1];
    }
    return $colors;
}
&lt;/code&gt;

In this example the database query is only executed once per request to load the $colors variable.  The rest of the time it simply loads the cached value from $colors.</content>
	<keywords>valuelists, dynamic valuelists, programmatically defined valuelists</keywords>
	<language>en</language>
	<original_page>0</original_page>
</wiki></record>