<?xml version="1.0"?>
<record><wiki id="wiki?page_id=183">
	<page_name>advmultiselect</page_name>
	<page_id>183</page_id>
	<page_title></page_title>
	<content></content>
	<keywords></keywords>
	<language>en</language>
	<original_page></original_page>
</wiki>
<wiki id="wiki?page_id=182">
	<page_name>column:legend</page_name>
	<page_id>182</page_id>
	<page_title></page_title>
	<content></content>
	<keywords></keywords>
	<language>en</language>
	<original_page></original_page>
</wiki>
<wiki id="wiki?page_id=60">
	<page_name>widget:type_textarea</page_name>
	<page_id>60</page_id>
	<page_title>widget:type_textarea</page_title>
	<content></content>
	<keywords></keywords>
	<language>en</language>
	<original_page>0</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=55">
	<page_name>blob</page_name>
	<page_id>55</page_id>
	<page_title>blob</page_title>
	<content></content>
	<keywords></keywords>
	<language>en</language>
	<original_page>0</original_page>
</wiki>
<wiki id="wiki?page_id=8">
	<page_name>Internet_Media_Manager</page_name>
	<page_id>8</page_id>
	<page_title>Internet Media Manager</page_title>
	<content>&apos;&apos;&apos;Manage your videos and photos all in one place&apos;&apos;&apos;

[[toc]]

===Watch the Guided Tour (6 minutes)===
&lt;nowiki&gt;
&lt;embed src=&quot;http://media.weblite.ca/lib/flvplayer.swf&quot; width=&quot;640&quot; height=&quot;448&quot; bgcolor=&quot;#FFFFFF&quot; type=&quot;application/x-shockwave-flash&quot; pluginspage=&quot;http://www.macromedia.com/go/getflashplayer&quot; flashvars=&quot;file=http%3A%2F%2Fs3.amazonaws.com%2Fweblite_media%2Fintro_video.flv&amp;image=http%3A%2F%2Fmedia.weblite.ca%2Ffiles%2Fphotos%2Fintro_video.flv.AbpY0Y.jpg&amp;showdigits=true&amp;autostart=false&quot; /&gt;
&lt;/nowiki&gt;

===Introduction===

The Internet Media Manager is a web-based database application that allows webmasters to centrally store their images and videos to be served on their website(s).  It provides a Youtube-like interface whereby users can simply copy and paste code snippets to embed images and videos into their web pages.  It also provides a photo gallery component that allows users to easily embed a gallery of images into their web pages by simply copying and pasting a snippet of javascript code.

===Purpose===

I created this application because:

# I didn&apos;t want to have to resize images in Photoshop anymore before uploading them to the web.
# I wanted to be able to embed videos, images, and photo galleries into my web pages without having to muck around with HTML code.

IMM (Internet Media Manager) allows you to resize your photos to any size you want, and embed these resized images in your web pages by copying and pasting a snippet of HTML.  Similarly it makes embedding videos and photo galleries into your website a snap.

===Features===

* Add/Edit/Delete/Categorize images and videos in a searchable database.
* Import multiple images or videos at once by uploading a ZIP file.
* Large file imports via FTP/SSH.
* Embed video and images directly into other web pages by copying and pasting HTML snippets (like Youtube).
* Resize images and videos.
* FLV video support (like Youtube).
* Search media by content type, category, keyword, etc..
* Includes javascript photo gallery component that can be embedded into any web page.
* Amazon Simple Storage Service (S3) integration.

===Requirements===

* [http://www.php.net|PHP] 5.2+
* [http://www.mysql.com|MySQL] 4.1+
* [http://ca.php.net/gd|GD_Image_Processing_Library]
* [http://ffmpeg.mplayerhq.hu/|FFMPEG] (optional - if you want to automatically generate poster images for videos).

===Download===

* [https://sourceforge.net/projects/immgr/files/|Internet Media Manager 0.3]

===Installation===

# Download the latest version from Sourceforge.
# Extract the files and copy to your web server.
# Point your web browser to the install.php and follow the instructions. 

===Screenshots===

&lt;nowiki&gt;
&lt;script language=&quot;javascript&quot; type=&quot;text/javascript&quot; src=&quot;http://media.weblite.ca/index.php?-action=gallery&amp;-table=files&amp;categories=3&amp;-cursor=0&amp;-skip=0&amp;-limit=30&amp;-mode=list&amp;-photo_max_width=500&amp;--format=js&quot;&gt;&lt;/script&gt;
&lt;div style=&quot;clear:both&quot;&gt;&lt;/div&gt;
&lt;/nowiki&gt;

===Screencasts===

How to import multiple images at once in a ZIP archive.

&lt;nowiki&gt;&lt;iframe title=&quot;YouTube video player&quot; width=&quot;640&quot; height=&quot;510&quot; src=&quot;http://www.youtube.com/embed/0gfRJ5HkRsI&quot; frameborder=&quot;0&quot; allowfullscreen&gt;&lt;/iframe&gt;&lt;/nowiki&gt;

===Support===

Visit the [http://xataface.com/forum/viewforum.php?f=12|Support_forum].
</content>
	<keywords>Internet Media Manager,resize photos,image gallery,photo gallery,video gallery</keywords>
	<language>en</language>
	<original_page>0</original_page>
</wiki>
<wiki id="wiki?page_id=38">
	<page_name>How_to_build_a_PHP_MySQL_Application_with_4_lines_of_code</page_name>
	<page_id>38</page_id>
	<page_title>How to build a PHP MySQL Application with 4 lines of code</page_title>
	<content>&apos;&apos;&apos;The [http://xataface.com Xataface Application Framework] allows you to convert your existing MySQL database into a full-fledged with as little as 4 lines of code.  And it&apos;s Not a code generator.&apos;&apos;&apos;

[[toc]]

This article is intended to spark interest in the [http://xataface.com Xataface Application Framework] amongst PHP developers by showing how easy it is to set up a full-featured front-end for your MySQL database.  If you are a PHP developer, surly you can identify with the situation where you&apos;ve built a snazzy website with PHP and MySQL but you need to create some way the website users to administer it.  I.e., you need to make an administrative back-end for your users.

You need to do this because PHP admin is too technical for your users, and it is an aweful lot of tedious work to create all of the necessary forms and lists for your users to edit the data themselves.

===Features for our Application===

* Create, edit and delete records using simple web forms.
* Browse through database and find records without any SQL.
* Lots of great widgets for editing records including html editors, select lists, grids, checkboxes, calendars and more.
* Sort records.
* Export result sets as CSV or XML.
* Fully configurable and extendable by you to implement more [[about|features]].

===Creating the Application===

Here are 6 steps to a full-featured front-end for your database:

# Create a directory for your application on your webserver.  Call it &apos;&apos;myapp&apos;&apos;.
# Download the latest version of [http://xataface.com Xataface] and copy it into your application directory that we just created.  (i.e. &apos;&apos;myapp/xataface&apos;&apos;.
# Create a configuration file named &apos;&apos;conf.ini&apos;&apos; inside your application directory (i.e. &apos;&apos;myapp/conf.ini&apos;&apos;) to store your database connection info:&lt;code&gt;
[_database]
    host=localhost
    name=mydb
    user=username
    password=mypass

[_tables]
    ;; This section lists the tables to include in your application menu
    table1=Label for table 1
    table2=Label for table 2
&lt;/code&gt;
# Create an .htaccess (i.e. &apos;&apos;myapp/.htaccess&apos;&apos;) file to prevent Apache from serving your &apos;&apos;conf.ini&apos;&apos; file:&lt;code&gt;
&lt;FilesMatch &quot;\.ini$&quot;&gt;
Deny from all
&lt;/FilesMatch&gt;
&lt;/code&gt;  &apos;&apos;&apos;Note:  If you are not using Apache as your web server you&apos;ll need to block access to the .ini files using a different mechanism.  E.g. On IIS you can create a Web.config file to block this access and place it inside your application&apos;s directory.&apos;&apos;&apos;  Download a sample Web.config file [http://weblite.ca/svn/dataface/core/trunk/site_skeleton/Web.config here].
# Create an index.php file (i.e. &apos;&apos;myapp/index.php&apos;&apos;) to serve as an access point for your application:&lt;code&gt;
&lt;?php
// Include the Xataface API
require_once &apos;xataface/dataface-public-api.php&apos;;

// Initialize Xataface framework
df_init(__FILE__, &apos;xataface&apos;)-&gt;display();
    // first parameter is always the same (path to the current script)
    // 2nd parameter is relative URL to xataface directory (used for CSS files and javascripts)
&lt;/code&gt;
# Create a &apos;&apos;templates_c&apos;&apos; directory to store cached smarty templates or your application (i.e. &apos;&apos;myapp/templates_c&apos;&apos;, and make sure that it is writable by the webserver:
 $ mkdir templates_c
 $ chmod 777 templates_c


That&apos;s all there is to it!  Point your web browser to the index.php file we just made, and check out your new app!

===Screenshots of Our App===

====Find Form====

[[Image:http://media.weblite.ca/files/photos/people-find.png?max_width=400]]

====New Record Form====

[[Image:http://media.weblite.ca/files/photos/people-new-record.png?max_width=400]]

====List View====

[[Image:http://media.weblite.ca/files/photos/people-list.png?max_width=400]]

===Where to go now===

# Sign up for the Xataface mailing list to receive exclusive development tips (see the left column for a signup form).
# Check out the [[about|About Xataface]] page for more information about features and requirements.
# Use the [http://xataface.com/documentation/getting_started Getting Started Tutorial] to get started making your own application.
# [http://xataface.com/videos Watch screencasts] showing Xataface in action.



</content>
	<keywords>tutorial, getting started, installation, first app, 4 lines of code</keywords>
	<language>en</language>
	<original_page>0</original_page>
</wiki>
<wiki id="wiki?page_id=45">
	<page_name>_output_cache</page_name>
	<page_id>45</page_id>
	<page_title>The Xataface Output Cache</page_title>
	<content>&lt;nowiki&gt;&lt;div class=&quot;portalMessage&quot;&gt;Note: There was a bug in the output cache affecting Xataface version 1.0 to 1.3rc1.  If you are using a version of Xataface older than 1.3rc2 then you should either disable the output cache, or replace the Dataface/OutputCache.php file with one from a newer version.&lt;/div&gt;&lt;/nowiki&gt;

[[toc]]

Xataface does quite a bit of heavy lifting on each page request.  If your application is getting a lot of traffic that is slowing your server down, you may want to look at enabling the Xataface output cache.

===Features===

* Improve speed of application dramatically - especially for seldom updated sites.
* Supports multiple languages.
* Supports multiple users (each user has own cache).
* Provides GZIP compression for improved performance.

===How it works?===

When you receive a request, Xataface will return a cached version of the page if the page has been accessed before.  If the page doesn&apos;t yet exist in the cache it generates the page, saves it to the cache and outputs it to the user transparently.  The cache is completely transparent to your users.

===Where is the cache stored?===

Xataface creates a table called &apos;&apos;__output_cache&apos;&apos; that stores all of the cached content for your application.  This table stores both a GZIPed and regular version of each page.  If the user&apos;s browser supports GZIP compression, Xataface will automatically return the GZIP version.  This results in further performance improvements.

===What if I make changes to the database?===

Xataface records which tables were in use when a page is cached.  If any of those tables are modified after the page is cached, Xataface will mark that cached page as &apos;&apos;out of date&apos;&apos; and regenerate it the next time that it is requested.

===What if I make changes to my configuration files and templates?===

The output cache will have to be manually cleared if you make any changes to your source files (e.g. PHP, templates, and INI files).  Clearing the cache is as easy as deleting or emptying the &apos;&apos;__output_cache&apos;&apos; table.

===How do I enable the Cache?===

Add the following to your [[conf.ini file]]:

&lt;code&gt;
[_output_cache]
    enabled=1
&lt;/code&gt;

===How do I disable the Cache?===

Simply comment out or remove the &apos;&apos;[_output_cache]&apos;&apos; section of your [[conf.ini file]].  E.g.
&lt;code&gt;
;[_output_cache]
;   enabled=1
&lt;/code&gt;

===Configuration Options===

The following directives can be added to the &apos;&apos;[_output_cache]&apos;&apos; section of your [[conf.ini file]] to customize how your output cache works.

{| class=&quot;listing listing2&quot;
|-
! Name
! Description
! Version
|-
| lifeTime
| Number of seconds before cached page is considered &apos;&apos;out of date&apos;&apos;.
| 0.7
|-
| tableName
| The name of the table to store the cached pages.  Default &apos;__output_cache&apos;.
| 0.7
|-
| ignoredTables
| A comma-delimited list of tables that don&apos;t affect the output cache (i.e. these tables can be changed without causing the output cache to be refreshed.
| 0.7
|-
| observedTables
| A comma-delimited list of tables that should affect the status of the output cache for every page (whether the table is explicitly used by the page or not).  This is a useful way to tell Xataface to refresh your cache.
| 0.7
|-
| exemptActions
| A comma-delimited list of actions that are exempt from the output cache (and thus should not be cached).
| 0.7
|}</content>
	<keywords>output cache</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=140">
	<page_name>init</page_name>
	<page_id>140</page_id>
	<page_title>init() Delegate Class Method</page_title>
	<content>== Synopsis ==

This method is called once, just after the table is loaded for the first time. It allows you to specify initialization details, such as [[setSecurityFilters|security filters]].

Note that it takes a single parameter: a Dataface_Table object of the table that is being initialized. 

== Example ==
&lt;code&gt;
function init(&amp;$table){

   ....
}
&lt;/code&gt;</content>
	<keywords></keywords>
	<language>en</language>
	<original_page></original_page>
</wiki>
<wiki id="wiki?page_id=11">
	<page_name>block__blockname</page_name>
	<page_id>11</page_id>
	<page_title>block__blockname</page_title>
	<content>===Available Blocks===

This is a grep to show the blocks that are defined in Xataface templates:

* Dataface_ActionsMenu.html:actions_menu_head
* Dataface_ActionsMenu.html:actions_menu_tail
* Dataface_Add_Existing_Related_Record.html:before_add_existing_related_record_form
* Dataface_Add_Existing_Related_Record.html:before_add_existing_related_`$ENV.relationship`_form
* Dataface_Add_Existing_Related_Record.html:after_add_existing_related_`$ENV.relationship`_form
* Dataface_Add_Existing_Related_Record.html:after_add_existing_related_record_form
* Dataface_Add_New_Related_Record.html:before_add_new_related_record_form
* Dataface_Add_New_Related_Record.html:before_add_new_related_`$ENV.relationship`_form
* Dataface_Add_New_Related_Record.html:after_add_new_related_`$ENV.relationship`_form
* Dataface_Add_New_Related_Record.html:after_add_new_related_record_form
* Dataface_AjaxEventDetails.html:before_event_details
* Dataface_AjaxEventDetails.html:after_event_details
* Dataface_Delete_Record.html:before_delete_record_form
* Dataface_Delete_Record.html:after_delete_record_form
* Dataface_Edit_Record.html:before_edit_record_form
* Dataface_Edit_Record.html:after_edit_record_form
* Dataface_FindForm.html:findform_before_`$element.field.name`_row
* Dataface_FindForm.html:findform_before_`$element.field.name`_widget
* Dataface_FindForm.html:findform_after_`$element.field.name`_widget
* Dataface_FindForm.html:findform_after_`$element.field.name`_row
* Dataface_FindForm.html:before_findform_table
* Dataface_FindForm.html:findform_before_`$element.field.name`_row
* Dataface_FindForm.html:findform_before_`$element.field.name`_widget
* Dataface_FindForm.html:findform_after_`$element.field.name`_widget
* Dataface_FindForm.html:findform_after_`$element.field.name`_row
* Dataface_FindForm.html:after_findform_table
* Dataface_Find_View.html:before_find_form
* Dataface_Find_View.html:after_find_form
* Dataface_Form_Section_Template.html:before_quickform_table
* Dataface_Import_RelatedRecords.html:before_import_related_records_form
* Dataface_Import_RelatedRecords.html:before_import_related_`$ENV.relationship`_form
* Dataface_Import_RelatedRecords.html:after_import_related_`$ENV.relationship`_form
* Dataface_Import_RelatedRecords.html:after_import_related_records_form
* Dataface_List_View.html:before_result_list
* Dataface_List_View.html:after_result_list
* Dataface_Login_Prompt.html:before_login_form
* Dataface_Login_Prompt.html:after_login_form
* Dataface_Main_Template.html:custom_stylesheets2
* Dataface_Main_Template.html:head
* Dataface_Main_Template.html:body_atts
* Dataface_Main_Template.html:before_body
* Dataface_Main_Template.html:before_header
* Dataface_Main_Template.html:after_header
* Dataface_Main_Template.html:before_search
* Dataface_Main_Template.html:after_search_form_submit
* Dataface_Main_Template.html:after_search
* Dataface_Main_Template.html:before_nav_menu
* Dataface_Main_Template.html:after_nav_menu
* Dataface_Main_Template.html:before_language_selector
* Dataface_Main_Template.html:after_language_selector
* Dataface_Main_Template.html:before_user_status_logged_in
* Dataface_Main_Template.html:after_user_status_logged_in
* Dataface_Main_Template.html:before_user_status_not_logged_in
* Dataface_Main_Template.html:after_user_status_not_logged_in
* Dataface_Main_Template.html:before_personal_tools
* Dataface_Main_Template.html:after_personal_tools
* Dataface_Main_Template.html:before_bread_crumbs
* Dataface_Main_Template.html:after_bread_crumbs
* Dataface_Main_Template.html:before_main_table
* Dataface_Main_Template.html:before_left_column
* Dataface_Main_Template.html:before_record_tree
* Dataface_Main_Template.html:after_record_tree
* Dataface_Main_Template.html:before_nav_menu
* Dataface_Main_Template.html:after_nav_menu
* Dataface_Main_Template.html:before_application_menu
* Dataface_Main_Template.html:after_application_menu
* Dataface_Main_Template.html:after_left_column
* Dataface_Main_Template.html:before_main_column
* Dataface_Main_Template.html:before_message
* Dataface_Main_Template.html:message
* Dataface_Main_Template.html:after_message
* Dataface_Main_Template.html:before_errors
* Dataface_Main_Template.html:error
* Dataface_Main_Template.html:after_errors
* Dataface_Main_Template.html:before_table_tabs
* Dataface_Main_Template.html:before_menus
* Dataface_Main_Template.html:after_menus
* Dataface_Main_Template.html:before_main_section
* Dataface_Main_Template.html:before_recently_viewed
* Dataface_Main_Template.html:after_recently_viewed
* Dataface_Main_Template.html:before_record_content
* Dataface_Main_Template.html:after_record_content
* Dataface_Main_Template.html:after_main_section
* Dataface_Main_Template.html:before_fineprint
* Dataface_Main_Template.html:after_fineprint
* Dataface_Main_Template.html:before_global_footer
* Dataface_Main_Template.html:after_global_footer
* Dataface_Main_Template.html:before_main_section
* Dataface_Main_Template.html:before_recently_viewed
* Dataface_Main_Template.html:after_recently_viewed
* Dataface_Main_Template.html:before_record_content
* Dataface_Main_Template.html:after_record_content
* Dataface_Main_Template.html:after_main_section
* Dataface_NavMenu.html:tables_menu_head
* Dataface_NavMenu.html:tables_menu_tail
* Dataface_NavMenu.html:tables_menu_head
* Dataface_NavMenu.html:tables_menu_tail
* Dataface_New_Record.html:before_new_record_form
* Dataface_New_Record.html:after_new_record_form
* Dataface_Record_Template.html:before_details_controller
* Dataface_Record_Template.html:after_details_controller
* Dataface_Record_Template.html:before_record_heading
* Dataface_Record_Template.html:after_record_heading
* Dataface_Record_Template.html:before_record_tabs
* Dataface_Record_Template.html:before_record_content
* Dataface_Record_Template.html:after_record_content
* Dataface_Record_Template.html:before_record_footer
* Dataface_Record_Template.html:after_record_footer
* Dataface_Registration.html:before_registration_form
* Dataface_Registration.html:after_registration_form
* Dataface_Related_Records_List.html:before_related_`$ENV.relationship`_records_list
* Dataface_Related_Records_List.html:after_related_`$ENV.relationship`_records_list
* Dataface_Remove_Related_Record.html:before_remove_related_record_form
* Dataface_Remove_Related_Record.html:before_remove_related_`$ENV.relationship`_record_form
* Dataface_Remove_Related_Record.html:after_remove_related_`$ENV.relationship`_record_form
* Dataface_Remove_Related_Record.html:after_remove_related_record_form
* Dataface_View_Record.html:before_view_tab_content
* Dataface_View_Record.html:before_record_actions
* Dataface_View_Record.html:after_record_actions
* Dataface_View_Record.html:after_view_tab_content
* Dataface_related_records_checkboxes.html:before_related_`$ENV.relationship`_records_checkboxes
* Dataface_related_records_checkboxes.html:before_related_records_checkboxes
* Dataface_related_records_checkboxes.html:after_related_records_checkboxes
* Dataface_related_records_checkboxes.html:after_related_`$ENV.relationship`_records_checkboxes
* Dataface_set_translation_status.html:before_details_controller
* Dataface_set_translation_status.html:after_details_controller

===Available Slots===

* Dataface_ActionsMenu.html:actions_menu
* Dataface_Add_Existing_Related_Record.html:add_existing_related_`$ENV.relationship`_form
* Dataface_Add_Existing_Related_Record.html:add_existing_related_record_form
* Dataface_Add_New_Related_Record.html:add_new_related_`$ENV.relationship`_form
* Dataface_Add_New_Related_Record.html:add_new_related_record_form
* Dataface_AjaxEventDetails.html:event_details
* Dataface_Delete_Record.html:delete_record_form
* Dataface_Edit_Record.html:edit_record_form
* Dataface_FindForm.html:findform_`$element.field.name`_row
* Dataface_FindForm.html:findform_`$element.field.name`_widget
* Dataface_FindForm.html:findform_`$element.field.name`_row
* Dataface_FindForm.html:findform_`$element.field.name`_widget
* Dataface_Find_View.html:find_form
* Dataface_Import_RelatedRecords.html:import_related_`$ENV.relationship`_form
* Dataface_Import_RelatedRecords.html:import_related_records_form
* Dataface_List_View.html:result_list
* Dataface_List_View_summary.html:result_list
* Dataface_Login_Prompt.html:login_form
* Dataface_Main_Template.html:doctype_tag
* Dataface_Main_Template.html:html_tag
* Dataface_Main_Template.html:html_head
* Dataface_Main_Template.html:html_title
* Dataface_Main_Template.html:dataface_stylesheets
* Dataface_Main_Template.html:custom_stylesheets
* Dataface_Main_Template.html:dataface_javascripts
* Dataface_Main_Template.html:custom_javascripts
* Dataface_Main_Template.html:head_slot
* Dataface_Main_Template.html:html_body
* Dataface_Main_Template.html:global_header
* Dataface_Main_Template.html:search_form
* Dataface_Main_Template.html:language_selector
* Dataface_Main_Template.html:user_status_logged_in
* Dataface_Main_Template.html:user_status_not_logged_in
* Dataface_Main_Template.html:personal_tools
* Dataface_Main_Template.html:bread_crumbs
* Dataface_Main_Template.html:main_table
* Dataface_Main_Template.html:left_column
* Dataface_Main_Template.html:application_menu
* Dataface_Main_Template.html:main_column
* Dataface_Main_Template.html:table_tabs
* Dataface_Main_Template.html:menus
* Dataface_Main_Template.html:main_section
* Dataface_Main_Template.html:record_content
* Dataface_Main_Template.html:fineprint
* Dataface_Main_Template.html:global_footer
* Dataface_Main_Template.html:main_section
* Dataface_Main_Template.html:record_content
* Dataface_Main_Templateold.html:doctype_tag
* Dataface_Main_Templateold.html:html_tag
* Dataface_Main_Templateold.html:html_head
* Dataface_Main_Templateold.html:html_title
* Dataface_Main_Templateold.html:dataface_stylesheets
* Dataface_Main_Templateold.html:custom_stylesheets
* Dataface_Main_Templateold.html:dataface_javascripts
* Dataface_Main_Templateold.html:custom_javascripts
* Dataface_Main_Templateold.html:head_slot
* Dataface_Main_Templateold.html:html_body
* Dataface_Main_Templateold.html:global_header
* Dataface_Main_Templateold.html:search_form
* Dataface_Main_Templateold.html:language_selector
* Dataface_Main_Templateold.html:user_status_logged_in
* Dataface_Main_Templateold.html:user_status_not_logged_in
* Dataface_Main_Templateold.html:personal_tools
* Dataface_Main_Templateold.html:bread_crumbs
* Dataface_Main_Templateold.html:main_table
* Dataface_Main_Templateold.html:left_column
* Dataface_Main_Templateold.html:application_menu
* Dataface_Main_Templateold.html:main_column
* Dataface_Main_Templateold.html:table_tabs
* Dataface_Main_Templateold.html:menus
* Dataface_Main_Templateold.html:main_section
* Dataface_Main_Templateold.html:record_content
* Dataface_Main_Templateold.html:fineprint
* Dataface_Main_Templateold.html:global_footer
* Dataface_Main_Templateold.html:main_section
* Dataface_Main_Templateold.html:record_content
* Dataface_NavMenu.html:tables_menu_options
* Dataface_NavMenu.html:tables_menu_options
* Dataface_New_Record.html:new_record_form
* Dataface_Record_Template.html:record_heading
* Dataface_Record_Template.html:record_content
* Dataface_Record_Template.html:record_footer
* Dataface_Registration.html:registration_form
* Dataface_Related_Records_List.html:before_related_list
* Dataface_Related_Records_List.html:related_`$ENV.relationship`_records_list
* Dataface_Related_Records_List.html:related_records_list
* Dataface_Related_Records_List.html:after_related_list
* Dataface_Remove_Related_Record.html:remove_related_`$ENV.relationship`_record_form
* Dataface_Remove_Related_Record.html:remove_related_record_form
* Dataface_View_Record.html:view_tab_content
* Dataface_View_Record.html:record_actions
* Dataface_View_Record.html:record_search
* Dataface_View_Record.html:`$section.name`_section_content
* Dataface_View_Record.html:record_view_main_section
* Dataface_View_Record.html:`$section.name`_section_content
* Dataface_related_records_checkboxes.html:related_`$ENV.relationship`_records_checkbox_form
* Dataface_related_records_checkboxes.html:related_records_checkbox_form
* global_header.html:site_logo

</content>
	<keywords></keywords>
	<language>en</language>
	<original_page>0</original_page>
</wiki>
<wiki id="wiki?page_id=84">
	<page_name>http://xataface.com/documentation/how-to/site_with_backoffice_How_to_build_a_site_with_a_backoffice_</page_name>
	<page_id>84</page_id>
	<page_title>A site with a backoffice</page_title>
	<content>==A site with a backoffice==
To create a site with a backoffice for the administrator, so that the visitors do not have to log in to read the pages, you add this code in the ApplicationDelegate.php file in the conf directory :
&lt;code&gt;

function getPermissions(&amp;$record){
    if ( isAdmin() ) return Dataface_PermissionsTool::ALL();
    else return Dataface_PermissionsTool::READ_ONLY();
}
 
&lt;/code&gt;
</content>
	<keywords></keywords>
	<language>en</language>
	<original_page></original_page>
</wiki>
<wiki id="wiki?page_id=36">
	<page_name>about</page_name>
	<page_id>36</page_id>
	<page_title>about</page_title>
	<content>==About Xataface==

[[toc]]

Xataface is a flexible and shapable skin that sits on top of MySQL, making it accessible to every-day users. It automatically generates the appropriate forms, lists, and menus for a user to interact with the database without having to know any SQL. 

It is a full-featured Web application framework, and gives developers the flexibility to customize the features and behavior of their application via configuration files (using the simple INI-file syntax), templates, and plug-ins. A generic application with no customizations is completely functional, but the developer is free to customize things at his leisure.

===Who is Xataface for?===

Xataface is for web developers and database administrators who would like to build a front-end for their MySQL database.  However the resulting applications are targeted at non-technical users such as secretaries.

===Requirements===

====Xataface 1.1.x and below:====

* MySQL 3.23+
* PHP 4+

Some advanced features require MySQL version 4.1 or higher.

====Xataface 1.2 and higher====

* MySQL 3.23+
* PHP 5+

Some advanced features require MySQL version 5 or higher.

===At a Glance: Your first App===

# Create a directory for your app.
# Copy the &apos;&apos;xataface&apos;&apos; directory inside your application directory.
# Create a configuration file named &apos;&apos;conf.ini&apos;&apos; in your application directory with your database settings:&lt;code&gt;
[_database]
    host=localhost
    name=mydb
    user=me
    password=mypass

[_tables]
    ; A list of tables to include in your application&apos;s menu
    ; These tables must already exist in your database
    people=Profiles
    news=News Articles
&lt;/code&gt;
# Create an .htaccess file in your application directory to prevent access to your &apos;&apos;conf.ini&apos;&apos; file:&lt;code&gt;
&lt;FilesMatch &quot;\.ini$&quot;&gt;
Deny from all
&lt;/FilesMatch&gt;
&lt;/code&gt;
# Create a PHP script in your application directory as an access point for your app.  We&apos;ll call it &apos;&apos;index.php&apos;&apos;:&lt;code style=&quot;php&quot;&gt;
&lt;?php
// Include the Xataface API
require_once &apos;xataface/dataface-public-api.php&apos;;

// Initialize Xataface framework
df_init(__FILE__, &apos;xataface&apos;);
    // first parameter is always the same (path to the current script)
    // 2nd parameter is relative URL to xataface directory (used for CSS files and javascripts)

// Create a new application
$app =&amp; Dataface_Application::getInstance();

// Display the application
$app-&gt;display()
&lt;/code&gt;
# You&apos;re done.  Your app is ready to use!

This is just the beginning, though.  There is no limit to the customizations you can make on your application.

Read the [http://xataface.com/documentation/tutorial/getting_started Getting Started Tutorial] for more information on developing applications with Xataface.


===Product Comparison===

Xataface fits a niche that is not well covered by existing apps/frameworks.  Xataface is &apos;&apos;&apos;NOT&apos;&apos;&apos;:

* A database administration system like PHPMyAdmin
* Simply a software library/Framework like PHPCake
* Simply a content management system like Drupal
* A code generator

Xataface is a framework, but it is not a typical framework.  Most frameworks require a substantial amount of development before you get a usable application.  Xataface, on the other hand, provides you with a fully-functional application with as little as 4 lines of PHP code.  It doesn&apos;t generate any code so it is easy to maintain your application and expand on it later.

As a development framework, Xataface most closely resembles Django, a python framework for building data-driven applications.  As an application, Xataface most closely resembles Filemaker, a popular relational database that makes it easy for the end user to create layouts and manage their data.

===Features===

====General====

* &apos;&apos;&apos;Out-of-the-box Database Front-end&apos;&apos;&apos; - With as little as 4 lines of PHP code, you can have a full-featured web application for your database.
* &apos;&apos;&apos;Simple, Intuitive User interface&apos;&apos;&apos; - Default application is consistent and simple to use.  There is a &apos;tables&apos; menu, to select a table, and each table has &quot;details&quot;, &quot;list&quot;, and &quot;find&quot; tabs.  Very easy to navigate.
* &apos;&apos;&apos;Powerful configuration options&apos;&apos;&apos; - You can configure your application details (such as widget types) using simple configuration files.
* &apos;&apos;&apos;Extendible&apos;&apos;&apos; - You can modify your application as you see fit using configuration files and PHP delegate classes.
* &apos;&apos;&apos;Hooks&apos;&apos;&apos; - By observing simple conventions you can extend Xataface&apos;s functionality with hooks, triggers, and events.  E.g. add a function that is called after a record is inserted.
* &apos;&apos;&apos;Permissions&apos;&apos;&apos; - Powerful, pluggable permissions system.
* &apos;&apos;&apos;Authentication&apos;&apos;&apos; - Provides login/logout ability.  You just specify which table your users are stored in.
* &apos;&apos;&apos;Relationships&apos;&apos;&apos; - Tell Xataface how your tables are related to one another and it will provide you with more logical functionality for managing your data.
* &apos;&apos;&apos;Themeable&apos;&apos;&apos; - Xataface uses the Smarty template engine as a base, but extends it with some powerful new features such as extendable templates and theming support.
* &apos;&apos;&apos;Modular&apos;&apos;&apos; - There are several add-on modules available to extend the features of Xataface even further, and a simple API for writing your own modules.


====Editing====

* &apos;&apos;&apos;Automatic Form Generation&apos;&apos;&apos; - Automatically generates appropriate web forms to add new records and edit existing records.
* &apos;&apos;&apos;Widgets&apos;&apos;&apos; - Support for many different widget types including text fields, text areas, checkboxes, select lists, html editors, grids, file uploads, and more.
* &apos;&apos;&apos;Configurable&apos;&apos;&apos; - Customize forms using configuration files and delegate classes.
* &apos;&apos;&apos;Personalizable&apos;&apos;&apos; - Show different forms to different users depending on their permissions and preferences.
* &apos;&apos;&apos;Add Related Records&apos;&apos;&apos; - Insert records and automatically track their relationships to other tables.
* &apos;&apos;&apos;Editable Data Grid&apos;&apos;&apos; - Manage your data like a spreadsheet using the DataGrid module.
* &apos;&apos;&apos;Copy&apos;&apos;&apos; - Copy sets of records.
* &apos;&apos;&apos;Update Found Set&apos;&apos;&apos; - Update multiple records with one swipe.
* &apos;&apos;&apos;Fine-grained Permissions&apos;&apos;&apos; - Assign editing permission based on table, record, or field. 
* &apos;&apos;&apos;File uploads&apos;&apos;&apos; - Support for file uploads with storage either in a BLOB field or on the file system.
* &apos;&apos;&apos;Delete&apos;&apos;&apos; - Delete single record or delete the current found set.

====Searching====

* &apos;&apos;&apos;Automatic Find Form&apos;&apos;&apos; - The Xataface find form allows you to search a table on any field.
* &apos;&apos;&apos;Range Searches&apos;&apos;&apos; - Search for records matching values in a certain range (e.g. find all people between the ages of 20 and 30).
* &apos;&apos;&apos;Exact Matching&apos;&apos;&apos; - Search for exact matches.
* &apos;&apos;&apos;Partial Matching&apos;&apos;&apos; - Search for fields that contain a keyword phrase.
* &apos;&apos;&apos;Multi-field search&apos;&apos;&apos; - There is always a simple search field accessible which searches all fields in the current table.  E.g. a search for &quot;Tom&quot; would match any record in the current table that contained the phrase &quot;Tom&quot; in any of its columns.
* &apos;&apos;&apos;Related Record Searches&apos;&apos;&apos; - Find records that contain related records matching a search term.  (E.g. find all people who got an &apos;A&apos; in a particular course).


====Browsing====

* &apos;&apos;&apos;Automatic Details View&apos;&apos;&apos; - Each record has user-friendly details page to browse the contents of the record.
* &apos;&apos;&apos;AJAX Record Tree&apos;&apos;&apos; - Provides optional AJAX record tree to browse the data in your database by relationships.
* &apos;&apos;&apos;Expand for More&apos;&apos;&apos; - Quickly expand a row in list view to see the full record details.
* &apos;&apos;&apos;Drag and Drop Reordering&apos;&apos;&apos; - The details view for a record can be broken up into related sections.  Users can reorder these sections via drag and drop.

====Exporting====

* &apos;&apos;&apos;RSS&apos;&apos;&apos; - Support for RSS 1.0, 2.0 and Atom feeds of any found set.
* &apos;&apos;&apos;XML&apos;&apos;&apos; - Export any found set as XML so that the data can be interchanged with other products (e.g. desktop publishing suites).
* &apos;&apos;&apos;CSV&apos;&apos;&apos; - Export any found set to CSV (comma-separated-value) to open in a spreadsheet application like Excel.
* &apos;&apos;&apos;JSON&apos;&apos;&apos; - Export any found set to JSON.  This feature makes Xataface a good choice for serving the next generation of Web 2.0 AJAX applications.

====Internationalization====

* &apos;&apos;&apos;String Internationalization&apos;&apos;&apos; - Xataface fully supports internationalizing your application.  It provides you with language files to provide translations of all of the strings and labels in your application.
* &apos;&apos;&apos;Dynamic Data Translation&apos;&apos;&apos; - Xataface even allows you to internationalize your existing database data without having to change your database structure.
* &apos;&apos;&apos;Templates&apos;&apos;&apos; - Includes a {translate} tag for Smarty templates to easily translate template text.
* &apos;&apos;&apos;In the background&apos;&apos;&apos; - You can use Xataface to internationalize any PHP/MySQL website without having to make any drastic changes to your existing code.  Just include Xataface as a library and use some of its useful internationalization functions to convert your application into multiple languages.
* &apos;&apos;&apos;Translation Form&apos;&apos;&apos; - If multiple languages are enabled, Xataface provides a simple translation form to translate content between languages.
* &apos;&apos;&apos;Translation Status Tracking&apos;&apos;&apos; - Track the status of translations to mark whether they need to be retranslated.

====Importing====

* &apos;&apos;&apos;Import Filter API&apos;&apos;&apos; - Using delegate classes, it is easy to define an import filter to import any type of data into the database.
* &apos;&apos;&apos;User Preview&apos;&apos;&apos; - User can preview imported data before confirming that he wants to import it.

====History====

* &apos;&apos;&apos;Optional History Support&apos;&apos;&apos; - If history is enabled, all changes made to any data are recorded.
* &apos;&apos;&apos;Undo/Redo Support&apos;&apos;&apos; - Easily revert to an earlier version of a record.
* &apos;&apos;&apos;View Snapshot&apos;&apos;&apos; - Browse previous versions of records.
* &apos;&apos;&apos;View Diffs&apos;&apos;&apos; - View differences/changes between versions of records, similar to a wiki.

====Caching====

* &apos;&apos;&apos;Output cache&apos;&apos;&apos; - Supports output cache that caches output of pages to improve performance dramatically for busy sites.  Cache is automatically refreshed whenever changes are made to tables that are used to generate the page.
* &apos;&apos;&apos;APC Support&apos;&apos;&apos; - If APC (Alternate PHP Cache) is installed, Xataface will automatically use it to cache table configuration information.  This tends to increase performance by about 20%.


====Security====

* &apos;&apos;&apos;Fine-grained permissions&apos;&apos;&apos; - Define permissions to the entire application, a single table, by the record, or by the field.  Each feature has an associated permission that can be allowed or disallowed on a per-user basis.
* &apos;&apos;&apos;Cascading Permissions&apos;&apos;&apos; - You can very restrictive permissions to the application as a whole and then apply more permission permissions to specific tables or fields that you want uses to be able to access.  Table permissions override application permissions.  Field permissions override field permissions.
* &apos;&apos;&apos;Role-based permissions&apos;&apos;&apos; - You can define &quot;&quot;&quot;roles&quot;&quot;&quot; which are sets of permissions that can be assigned to users.
* &apos;&apos;&apos;Extendable Permissions Model&apos;&apos;&apos; - You can easily define your own permissions and roles, extending existing roles, custom for your application.
* &apos;&apos;&apos;Built-in Authentication&apos;&apos;&apos; - It is easy to set up login/logout features for your application.  Just tell Xataface which table you store your user records in, and Xataface will do the rest.
* &apos;&apos;&apos;Password Encryption&apos;&apos;&apos; - Xataface supports and is compatible with most of the standard password encryptions including MD5, SHA1, and MySQL Password.
* &apos;&apos;&apos;Pluggable Authentication&apos;&apos;&apos; - Easy to create your own authentication plugins in case you want to implement your own custom authentication.
* &apos;&apos;&apos;CAS&apos;&apos;&apos; - Module available for the Yale CAS (Central Authentication Service).
* &apos;&apos;&apos;LDAP&apos;&apos;&apos; - LDAP authentication module available.
* &apos;&apos;&apos;HTTP&apos;&apos;&apos; - Optional HTTP login support.  Standard login uses a web-based login form, but you can also use HTTP headers for authentication.

====Relationships====

* &apos;&apos;&apos;Powerful Relationship Model&apos;&apos;&apos; - It is easy to define relationships between your tables using simple configuration files.  Syntax is simple, but the results are powerful.
* &apos;&apos;&apos;Add New Related Record&apos;&apos;&apos; - Create a new record and add it to a parent record&apos;s relationship at the same time. (E.g. create a new &quot;course&quot; record and add it to a teacher&apos;s list of taught courses).
* &apos;&apos;&apos;Add Existing Related Record&apos;&apos;&apos; - Add an existing record to a parent record&apos;s relationship. (e.g. Add an existing course record to a teacher&apos;s list of taught courses).
* &apos;&apos;&apos;Remove related record&apos;&apos;&apos; - Remove a record from a relationship. (e.g. remove a course record from a teacher&apos;s list of taught courses).

====API====

Xataface includes a powerful API to allow you to more efficiently work with your database.

* &apos;&apos;&apos;Data Objects&apos;&apos;&apos; - Provides a simple API to work with database records.  Searching, loading, saving, editing, and deleting records supported.

====Templates====

* &apos;&apos;&apos;Smarty Template Engine&apos;&apos;&apos; - Xataface uses the Smarty template engine as a base, one of the fastest PHP template engines available.
* &apos;&apos;&apos;Template Inheritance&apos;&apos;&apos; - You can create templates that inherit from other templates, and replace the content in specified &quot;slots&quot; of the original template.  This drastically increases template reuse and development productivity.
* &apos;&apos;&apos;Cascading Support&apos;&apos;&apos; - All system templates are stored in the Dataface/templates directory.  Your application can have its own templates directory where you can place templates to override system templates.  All parts of the system can be overridden without modifying the original templates themselves.

====Themes====

Xataface includes a powerful themes API.  You can create multiple looks for your application and switch between them with a simple configuration setting.

====REST Support====

Xataface&apos;s intelligent URL protocols make it a powerful platform for REST web services.  You can specify a query directly in the URL to obtain the exact found-set that you want.  This is also very useful in standard web applications because you can easily create links to desired parts of your application.  Or you can use Xataface to provide missing functionality in your existing applications and link only to the parts of your Xataface app that you need.

===History===

Xataface (formerly Dataface) was originally created by Steve Hannah in 2005 to increase productivity created data-driven applications for Simon Fraser University.  He came from faculty that used Filemaker extensively for their databases.  As a PHP developer he preferred open technologies like MySQL as they provided fewer &quot;road blocks&quot;, but it was hard to deny the benefits of filemaker when it came to providing users with an instant user interface for their databases.  It was difficult to justify spending 3 weeks building an administration console for a MySQL application when it could have been done in 3 hours had Filemaker been used.

Xataface was designed to:

# Increase developer productivity to the point where MySQL applications could be created as quickly as Filemaker applications without sacrificing usability and functionality.
# Add an abstraction over a database to make is accessible to non-technical users.  The secretary shouldn&apos;t need to know SQL in order to interact with a database.
# Test the limits of PHP and MySQL

As it was built with the intention of providing an alternative for Filemaker, many implementation details and concepts have been inspired by Filemaker.  For example, Xataface&apos;s implementation of relationships is very similar to Filemaker relationships; as are valuelists.  In addition the method of searching follows many Filemaker conventions.

The first application built with Xataface was a group content management system for the Faculty of Applied Sciences at Simon Fraser University.  This system was used by faculty to manage their research profiles and their research groups.  The database itself pre-existed the Xataface implementation.   Xataface was used to build a new administrative interface to the system.  Since then Xataface has been used to develop many systems for SFU including website content management systems, auctions, event registration systems, research databases, shopping carts, and more.

==Where to go from here==

* [http://xataface.com/documentation/tutorial/getting_started Getting Started Tutorial]
* [http://xataface.com/videos Watch Demonstration Videos of Xataface]
* Sign up for the Xataface Maillist to receive free updates and development tips.  (See sign-up form in upper left of the page).</content>
	<keywords></keywords>
	<language>en</language>
	<original_page>0</original_page>
</wiki>
<wiki id="wiki?page_id=6">
	<page_name>actions.ini_file</page_name>
	<page_id>6</page_id>
	<page_title>actions.ini_file</page_title>
	<content>==actions.ini file Reference==

[[toc]]

The actions.ini file stores information about the various [[action]]s that can be performed by your application.  An action may be manifested in two ways:

# As a web page
# As a menu item

And there is no reason why an action cannot serve in both capacities simultaneously.  All menu items and functions that Xataface performs are defined in the Xataface actions.ini file (in the root of the Xataface installation dirctory).  You can also create an actions.ini file in your application&apos;s root directory to override existing Xataface actions, or to create your own.  If you want to modify an existing action instead of overriding it, you can use this syntax.

&lt;code&gt;
[browse &gt; browse]
	label = Browse
&lt;/code&gt;

The &amp;gt; symbol simply means to inherit from the existing browse action.  All the attributes are the same, and we just override the label to Browse (originally was Details)

Additionally, for actions that pertain only to a single table, an actions.ini file may be placed in any [[table configuration directory]].

===Syntax===

As with the [[fields.ini file]] and the [[valuelists.ini file]], the actions.ini file uses the simple [[INI file syntax]] to define its actions.  Each action is defined in its own section, and can have a number of directives to specify the action&apos;s behavior.

Here is a snippet from the Xataface actions.ini file to give you an idea:

&lt;code&gt;
;; Show the details of the current record
[browse]
	label = Details
	category = table_tabs
	url = &quot;{$this-&gt;url(&apos;-action=view&apos;)}&quot;
	accessKey = &quot;b&quot;
	mode = browse
	permission = view
	order=0

;; Show a list of the records in the current found set
[list]
	label = List
	category = table_tabs
	url = &quot;{$this-&gt;url(&apos;-action=list&apos;)}&quot;
	accessKey = &quot;l&quot;
	mode = list
	template = Dataface_List_View.html
	permission = list
	order=0.5

;; Show a &quot;Find Record Form&quot;
[find]
	label = Find
	category = table_tabs
	url = &quot;{$this-&gt;url(&apos;-action=find&apos;)}&quot;
	accessKey = &quot;f&quot;
	mode = find
	permission = find
	template = Dataface_Find_View.html
	order=0.75
&lt;/code&gt;

This snippet shows the definition of the browse, list, and find actions - three of the most central actions in a Xataface application.  Notice how each action has its own section (according to [[INI file syntax]]) with a number of directives which specify how the action behaves.  For instance, each action has a &quot;category&quot; value of &quot;table_tabs&quot;, which tells Xataface to display the actions as part of the table tabs in the user interface.

===Directives===

{| class=&quot;listing listing2&quot;
|-
! Name
! Description
! Version
|-
| [[action allow_override|allow_override]]
| An optional directive to indicate that this action can be overridden by more specific directives in another ini file.  Currently there is only support for a value of &quot;relationships.ini&quot; indicating that the settings can be overridden in the relationships.ini file.  In order for this to work, related=1 must also be set.
| 1.3rc4
|-
| [[action label|label]]
| The label to display if the action is used as a menu item.
| all
|-
| [[action category|category]]
| The name of the action&apos;s category which can be used to group this action together with other similar actions to be used in a menu in the user interface.
| all
|-
| [[action url|url]]
| If the action appears as a menu item, this is the URL that the menu item points to.  This may contain PHP expressions inside curly braces.
| all
|-
| [[action accessKey|accessKey]]
| The key code to automatically select this action if it is included as a menu item.  I.e. ALT+accessKey calls the action.
| all
|-
| [[action mode|mode]]
| This indicates which tab of the table tabs (find, details, list, etc...) that this action should appear to be part of when the action is viewed as a web page.  If this is left undefined, or it does not match any existing visible action in the table tabs, then no tab will appear to be selected.
| all
|-
| [[action permission|permission]]
| The name of a permission required to both see the action as part of a menu and to access the action as a web page.
| all
|-
| [[action visible|visible]]
| A boolean value indicating whether the action should be visible as a menu item.
| all
|-
| [[action condition|condition]]
| A boolean value or a PHP expression evaluating to a boolean value to indicate whether the action should be visible as a menu item.
| all
|-
| [[action url_condition|url_condition]]
| A PHP expression evaluating to a boolean value to indicate whether the URL directive should be evaluated.  This basically checks to make sure that its OK to evaluate the &quot;url&quot; expression, just in case the current state of affairs would cause it to throw a fatal error.
| all
|-
| [[action order|order]]
| A numeric value indicating the order in which the action should be displayed as part of a menu.  Low numbers result in higher placement in the menu.
| all
|-
| [[action icon|icon]]
| The path to an icon that should be used when the action appears as a menu item.
| all
|-
| [[action template|template]]
| The path to the template that should be used when the action is displayed as a web page.
| all
|-
| [[action description|description]]
| Mouseover text for the action (when displayed as a menu item).
| all
|}

===PHP Expression Context===

Notice that the [[action url|url]], [[action condition|condition]], and [[action url_condition|url_condition]] directives allow you to use a PHP expression for their values.  In order for this to be helpful, you should know a little bit about the context and environment in which these expressions will be executed.  All expressions are evaluated immediately prior to being rendered, so the same action can be displayed multiple times in the same page, but have very different resulting values for their [[action url|urls]] and [[action condition|conditions]].

These expressions are all executed within the context of the Dataface_Application::parseString() method, with the following variables loaded in the local symbol table (i.e. you can use the following variables in your expressions).

{| class=&quot;listing listing2&quot;
|-
! Name
! Description
! Version
|-
| [[action context:site_url|$site_url]]
| The URL to the current application&apos;s directory (not including &quot;index.php&quot;)
| all
|-
| $site_href
| The URL to the current application including &quot;index.php&quot;
| all
|-
| $dataface_url
| The URL to the xataface installation directory.
| all
|-
| $table
| The name of the current table (i.e. the value of the &quot;-table&quot; request parameter&quot;
| all
|-
| $query
| An associative array of the current query variables.
| all
|-
| $app
| A reference to the current Dataface_Application object.  Alias of &quot;$this&quot;
| all
|-
| $resultSet
| A reference to the Dataface_QueryTool object for the current query.
| all
|-
| [[action context:record|$record]]
| A reference to the current Dataface_Record object.
| all
|-
| [[action context:context|$context]]
| An associative array of context variables that are passed to the action from the context in which the action is called.
| all
|}</content>
	<keywords></keywords>
	<language>en</language>
	<original_page>0</original_page>
</wiki>
<wiki id="wiki?page_id=14">
	<page_name>afterRegister</page_name>
	<page_id>14</page_id>
	<page_title>afterRegister</page_title>
	<content>==afterRegister() Trigger==

A trigger that can be implemented in the [[Application Delegate Class]] or the [[Table Delegate Class]], to be executed after the registration form is saved.  This can be used to perform some custom actions like emailing the administrator.

===Signature===

function afterRegister( Dataface_Record &amp;$record ) : mixed

====Parameters====

{| class=&quot;listing listing2&quot;
! Name
! Description
|-
| &amp;$record
| A Dataface_Record object encapsulating the record that is being inserted in the users table for this registration.
|-
| returns
| Mixed. If this method returns a PEAR_Error object, then registration will fail with an error.
|}

===Example===

&lt;code&gt;
&lt;?php
class conf_ApplicationDelegate {
    function afterRegister(&amp;$record){
        // mail the admin to let him know that the registration is occurring.
        mail(&apos;admin@example.com&apos;, &apos;New registration&apos;, &apos;A new user &apos;.$record-&gt;val(&apos;username&apos;).&apos; has registered);
    }
}
&lt;/code&gt;

===See Also===

* [[beforeRegister]]
* [[validateRegistrationForm]]
* [[sendRegistrationActivationEmail]]
* [[getRegistrationActivationEmailInfo]]
* [[getRegistrationActivationEmailSubject]]
* [[getRegistrationActivationEmailMessage]]
* [[getRegistrationActivationEmailParameters]]
* [[getRegistrationActivationEmailHeaders]]</content>
	<keywords></keywords>
	<language>en</language>
	<original_page>0</original_page>
</wiki>
<wiki id="wiki?page_id=33">
	<page_name>after_action_new</page_name>
	<page_id>33</page_id>
	<page_title>after_action_new</page_title>
	<content>==after_action_new trigger==

[[toc]]

This trigger is called after the &apos;&apos;&apos;new&apos;&apos;&apos; action is successfully completed.  This trigger can be defined in the table [[Delegate class methods|delegate class]] and is often used to redirect to a particular page after a new record is submitted.  This should not be confused with the [[afterInsert]] trigger, which is executed after a record is inserted into the database (this can occur multiple times per request).  The after_action_new trigger is only executed once after the &apos;new&apos; action has been successfully completed.  i.e. a maximum of once per request.

===Signature===

&lt;code&gt;
function after_action_new($params=array()){ ... } : return void
&lt;/code&gt;

====Parameters====

This method takes a single associative array as a parameter. This array includes the following keys:

* &apos;&apos;&apos;record&apos;&apos;&apos; - The [http://dataface.weblite.ca/Dataface_Record Dataface_Record] object that was just inserted.


===Examples===

====Example 1: Redirect to the view tab for the inserted record====

&lt;code&gt;
function after_action_new($params=array()){
    $record =&amp; $params[&apos;record&apos;];
    header(&apos;Location: &apos;.$record-&gt;getURL(&apos;-action=view&apos;).&apos;&amp;--msg=&apos;.urlencode(&apos;Record successfully inserted.&apos;));
    exit;
}
&lt;/code&gt;
</content>
	<keywords></keywords>
	<language>en</language>
	<original_page>0</original_page>
</wiki>
<wiki id="wiki?page_id=13">
	<page_name>beforeRegister</page_name>
	<page_id>13</page_id>
	<page_title>beforeRegister</page_title>
	<content>==beforeRegister() Trigger==

A trigger that can be implemented in the [[Application Delegate Class]] or the [[Table Delegate Class]], to be executed before the registration form is saved.  This can be used to perform some custom actions like emailing the administrator.

===Signature===

function beforeRegister( Dataface_Record &amp;$record ) : mixed

====Parameters====

{| class=&quot;listing listing2&quot;
! Name
! Description
|-
| &amp;$record
| A Dataface_Record object encapsulating the record that is being inserted in the users table for this registration.
|-
| returns
| Mixed. If this method returns a PEAR_Error object, then registration will fail with an error.
|}

===Example===

&lt;code&gt;
&lt;?php
class conf_ApplicationDelegate {
    function beforeRegister(&amp;$record){
        // mail the admin to let him know that the registration is occurring.
        mail(&apos;admin@example.com&apos;, &apos;New registration&apos;, &apos;A new user &apos;.$record-&gt;val(&apos;username&apos;).&apos; has registered);
    }
}
&lt;/code&gt;

===See Also===

* [[afterRegister]]
* [[validateRegistrationForm]]
* [[sendRegistrationActivationEmail]]
* [[getRegistrationActivationEmailInfo]]
* [[getRegistrationActivationEmailSubject]]
* [[getRegistrationActivationEmailMessage]]
* [[getRegistrationActivationEmailParameters]]
* [[getRegistrationActivationEmailHeaders]]</content>
	<keywords></keywords>
	<language>en</language>
	<original_page>0</original_page>
</wiki>
<wiki id="wiki?page_id=179">
	<page_name>Cached_permissions</page_name>
	<page_id>179</page_id>
	<page_title>Cached Permissions</page_title>
	<content>==Cached Permissions==

===Introduction===
When you insert a SQL query in your getPermissions function, this will slow down the app dramatically because this function is called by each query. To resolve this problem, it is better to use cached permissions in your /conf/ApplicationDelegate.php or table/table.php.

===Procedure===
Here is an example :
&lt;code&gt;
class tables_mytable {

    private $cachedPerms = null;
    private function _getCachedPerms($param1, $param2, ..., $paramN){
        if ( !isset($this-&gt;cachedPerms) ) {
            $this-&gt;cachedPerms = array();
            // do some stuff
            $res = mysql_query(&quot;select * from foo where bar=1 and param2=&apos;&quot;.addslashes($param2).&quot;&apos;&quot;);
            while ( $row = mysql_fetch_assoc($res) )  $this-&gt;cachedPerms[$row[&apos;fooid&apos;]] = $row;
        }
        return $this-&gt;cachedPerms;
    }

    function getPermissions($record){
        // do some stuff
        $perms = $this-&gt;getCachedPerms($param1, $param2, ..., $paramN);
        return $perms;
    }
}&lt;/code&gt;
Here, getPermissions() will run a db query on its first request, but subsequent requests will just load the cached value.</content>
	<keywords>permissions, cache, quick, query</keywords>
	<language>en</language>
	<original_page></original_page>
</wiki>
<wiki id="wiki?page_id=43">
	<page_name>Calendar_Action</page_name>
	<page_id>43</page_id>
	<page_title>Calendar_Action</page_title>
	<content>==Calendar Action==

[[toc]]

Xataface 1.0 includes a built-in calendar action that is disabled by default.  If enabled, it allows you to view the records in any found set as a calendar of events, as follows:

&lt;nowiki&gt;
&lt;div style=&quot;text-align:center;border: 1px solid #ccc; padding: 10px&quot;&gt;
&lt;img src=&quot;http://media.weblite.ca/files/photos/Picture -4.png?max_width=500&quot;
onmouseover=&quot;this.src=&apos;http://media.weblite.ca/files/photos/Picture -4.png&apos;;&quot;
onmouseout=&quot;this.src=&apos;http://media.weblite.ca/files/photos/Picture -4.png?max_width=500&apos;;&quot;/&gt;
&lt;/div&gt;
&lt;/nowiki&gt;

===Features===

* Monthly display
* Hourly schedule for any day by clicking on it.
* Show record details instantly by clicking on it in the calendar.
* Recognizes dates, start and end times for records when interpreted as calendar events.
* Respects searches (i.e. you can filter the records and the calendar will only show those records in the found set).

===Requirements===

Your table records should contain at least dates in order for them to be interpreted as events that can be placed in a calendar.

===Setting up the Calendar===

Suppose I have a table called &apos;&apos;Lessons&apos;&apos; that stores information about scheduled music lessons.  If I want to add the calendar to this table, then I would add an &apos;&apos;[[actions.ini file]]&apos;&apos; to the &apos;&apos;tables/Lessons&apos;&apos; directory with the following contents:&lt;code&gt;
[calendar &gt; calendar]
    condition=&quot;true&quot;
&lt;/code&gt;
This overrides the calendar action which is disabled by default, and enables it for the &apos;&apos;Lessons&apos;&apos; table.

Next I need to inform Xataface which fields store the event dates and times so that the records can be laid out in the calendar appropriately.  (Note that if you skip this step, Xataface will make a best guess based on column types and names - but it is better to specify these explicitly).

In the &apos;&apos;Lessons&apos;&apos; table I have the following fields that are relevant here:

* &apos;&apos;lesson_date&apos;&apos; - A date field containing the date and start time of the event.
* &apos;&apos;start_time&apos;&apos; - A time field with the start time of the lesson.

We can tell Xataface to treat these fields accordingly by adding the following directives to the appropriate field sections of the [[fields.ini file]] for the &apos;&apos;Lessons&apos;&apos; table:

* &apos;&apos;event.date=1&apos;&apos; - Specifies that the field stores the date of the event.
* &apos;&apos;event.start=1&apos;&apos; - Specifies that the field stores the start time of the event.

So in our case we&apos;ll modify the [[fields.ini file]] as follows:

&lt;code&gt;
[lesson_date]
    event.date=1

[start_time]
    event.start=1
&lt;/code&gt;

Now if we load up our application, we should now see a &apos;&apos;calendar&apos;&apos; tab along side &apos;&apos;list&apos;&apos;, &apos;&apos;details&apos;&apos;, and &apos;&apos;find&apos;&apos; for the &apos;&apos;Lessons&apos;&apos; table.  Click on this tab to see your records displayed in a calendar.

===Using a datetime field to store both date and start time===

You can also use a single field to store both the date and start time for an event.  In this case you just provide the &apos;&apos;event.date&apos;&apos; and &apos;&apos;event.start&apos;&apos; directives for the same field.  For example if the &apos;&apos;lesson_date&apos;&apos; was a datetime field that marked the date and time of the lesson, we would modify our [[fields.ini]] file as follows:

&lt;code&gt;
[lesson_date]
    event.date=1
    event.start=1
&lt;/code&gt;

===Available Fields===

The Calendar action will look for the following pieces of information in your records:

{| class=&quot;listing listing2&quot;
! Name
! Description
! Version
|-
| event.date
| Indicates that the field contains the date of the event.
| 1.0
|-
| event.start
| Indicates that the field contains the start time of the event.
| 1.0
|-
| event.end
| Indicates that the field contains the end time of the event.
| 1.0
|-
| event.location
| Indicates that the field contains the location of the event.
| 1.0
|-
| event.category
| Indicates that the field contains the category of the event.
| 1.0
|}</content>
	<keywords></keywords>
	<language>en</language>
	<original_page>0</original_page>
</wiki>
<wiki id="wiki?page_id=178">
	<page_name>Clean_the_html_for_the_export</page_name>
	<page_id>178</page_id>
	<page_title>Clean the HTML to export data</page_title>
	<content>==Clean HTML tags and entities to export your data==
#Override the display() of the field to strip the tags... but this would affect all parts of the application where the HTML fields are displayed.
#Create a grafted field, then override its display to show the stripped contents of the HTML area field.

e.g. in the fields.ini:

&lt;code&gt; 
    __sql__ = &quot;select t.*, null as stripped_field from mytable t&quot;
    [original_field]
       widget:type=htmlarea
       visibility:csv=hidden

    [stripped_field]
        visibility:csv = visible
        visibility:list=hidden
        visibility:browse=hidden
        visibility:find=hidden

&lt;/code&gt; 


Then in the delegate class:


&lt;code&gt; 
    function stripped_field__display($record){
        return html_entity_decode(strip_tags($record-&gt;val(&apos;original_field&apos;)), ENT_QUOTES, &apos;UTF-8&apos;);
    }
&lt;/code&gt; </content>
	<keywords></keywords>
	<language>en</language>
	<original_page></original_page>
</wiki>
<wiki id="wiki?page_id=25">
	<page_name>conf.ini_file</page_name>
	<page_id>25</page_id>
	<page_title>conf.ini_file</page_title>
	<content>==conf.ini File==

[[toc]]

The conf.ini file is where most of the application-level configuration information is stored for a Xataface application.  It contains information such as:

* database connection information
* which tables should appear in the tables menu.
* [[preferences|preference settings]]
* [[authentication]] settings
* which add-on [[modules]] are to be used
* output caching settings
* history/undo settings
* other misc settings.

Every conf.ini file must contain at least the following sections:


{| class=&quot;listing listing2&quot;
|-
! Name
! Description
! Version
|-
| _database
| Contains database connection info.
| all
|-
| _tables
| Contains a list of tables that are to be included in the navigation menu of the application.
| all
|}


The following optional sections may also be included:

{| class=&quot;listing listing2&quot;
|-
! Name
! Description
! Version
|-
| [http://xataface.com/documentation/how-to/disallow_tables _allowed_tables]
| Specifies tables that should be explicitly allowed to override disallowed tables listed or matched in the [http://xataface.com/documentation/how-to/disallow_tables _disallowed_tables] section.
| 0.7
|-
| [[_auth]]
| Contains information about [[authentication]].
| 0.6
|-
| [http://xataface.com/documentation/how-to/disallow_tables _disallowed_tables]
| A list of tables or patterns that match tables that should be blocked from being accessed directly through the application.  By default any table beginning with an underscore, &apos;dataface_&apos;, or ending in &apos;__history&apos; are blocked.  This prevents unintended access to some of the automatically created tables in Xataface.
| 0.7
|-
| _feed
| Configuration options for [[Introduction_to_RSS_Feeds_in_Xataface|RSS feeds]] that are generated by the application.
| 1.0
|-
| _history
| Settings pertaining to the [http://xataface.com/documentation/how-to/history-howto history feature] (e.g. whether it has been enabled).
| 0.7
|-
| _index
| Settings for the full site search indexing.
| 1.0
|-
| _modules
| A list of [[modules]] that are enabled for this application.
| 1.0
|-
| [[_output_cache]]
| Output cache settings.  Using output caching can dramatically improve performance for busier sites.
| 0.8
|-
| _themes
| A list of the themes that are to be applied to the application.
| 0.8
|}

===Stand-alone Attributes===

Stand-alone attributes for an INI file must appear at the beginning of the INI file (before any of the sections).  The conf.ini may contain the following stand-alone attributes.

{| class=&quot;listing listing2&quot;
|-
! Name
! Description
! Values
! Version
|-
| cache_queries
| Enables query caching.  Enabling this feature can yield drastic performance improvements especially on busy sites with large databases.
| boolean (0 or 1)
| 1.2

|-
| cache_queries_log
| Enables logging of query caching to the file /tmp/querylog.log so that you can tell whether your queries are being cached, and which ones are being cached.
| boolean (0 or 1)
| 1.2

|-
| default_action
| The default action to be performed if it is not explicitly specified in the query (e.g. &apos;list&apos;, &apos;find&apos;, &apos;edit&apos;).  Default is &apos;list&apos;.
| string
| 0.6
|-
| debug
| If this is set to 1, then the application will run in debug mode which displays the available slots and blocks on the screen, along with some other debug information.
| 0 or 1 (default is 0)
| 0.6

|-
| default_browse_action
| The default action to perform in the details tab.  E.g. When you click on the &quot;details&quot; tab there are a number of sub-tabs including &apos;view&apos;, &apos;edit&apos;, etc... .   The default value for this directive is &apos;view&apos;.  If you want to go directly to the edit form when clicking on a record in list view, you would set &apos;&apos;default_browse_action&apos;&apos; to &apos;edit&apos;.
| string
| 0.6
|-
| default_language
| The default language to use.  This is the 2-digit ISO language code.  If this value is not specified it defaults to the first language listed in the &apos;&apos;[languages]&apos;&apos; section.
| string (2-digit ISO language code)
| 0.6
|-
| default_limit
| The default limit (i.e. the number of records to show per page) if none is explicitly specified in the query.  Default is 30.
| int
| 0.6
|-
| default_table
| The default table to show if none is specified by the query.  If you do not define this value, then the first table in the &apos;&apos;[_tables]&apos;&apos; section is used.
| string
|0.6
|-
| disable_session_ip_check
| Default behaviour automatically tracks the IP address of the user when they log in.  If a request is made for a session from a different IP then the session is automatically destroyed and the user is logged out.
| boolean
| 1.3rc4

|-
| title
| A title for the application (appears in the browser title bar).
| string
| 0.6
|-
| usage_mode
| The usage mode of the application.  If this value is set to &apos;&apos;edit&apos;&apos;, then ajax inline editing is enabled (i.e. you can click on any value in the application to edit it inline.
| &apos;view&apos; or &apos;edit&apos;
| 0.6
|}

===Example 1: A simple conf.ini file===

&lt;code&gt;
[_database]
	host=&quot;localhost&quot;
	name=&quot;mydb&quot;
	user=&quot;mydbuser&quot;
	password=&quot;foo&quot;
	
[_tables]
webpage_sites=&quot;Websites&quot;
translations = &quot;Translations&quot;
packages=&quot;Packages&quot;
users=Users
proof_jobs=&quot;Jobs&quot;
webpage_status=&quot;Webpages Status&quot;

&lt;/code&gt;

===Example 2: A more complex conf.ini file===

&lt;code&gt;
;debug=1
;default_action=home
;google_translate_url=&quot;http://weblite-dns2.com/proxy.php&quot;
google_translate_url=&quot;http://ec2-75-101-244-123.compute-1.amazonaws.com/proxy.php&quot;
title=&quot;Web Lite Translate&quot;
default_price_per_word=0.15

;;Configuration settings for application
title=&quot;translation_weblite_ca&quot;
scriptUrl=&quot;http://translation.weblite.ca/index.php&quot;
multilingual_content=1


[_database]
	host=&quot;localhost&quot;
	name=&quot;mydb&quot;
	user=&quot;mydbuser&quot;
	password=&quot;foo&quot;
	
[_tables]
    webpage_sites=&quot;Websites&quot;
    translations = &quot;Translations&quot;
    packages=&quot;Packages&quot;
    users=Users
    proof_jobs=&quot;Jobs&quot;
    webpage_status=&quot;Webpages Status&quot;


[_auth]
	users_table=users
	username_column=username
	password_column=password
	secret_code=&quot;ljkasdfjkldsafliasdoiudsfoi&quot;
	allow_register=1
	session_timeout=999999999
	
[_modules]
	modules_ShoppingCart=&quot;modules/ShoppingCart/ShoppingCart.php&quot;

[ShoppingCart_taxes]
	;; This section is necessary to declare that we have NO taxes.
	
[metatags]
	keywords = &quot;translation, translate&quot;
	description = &quot;Good translation service&quot;
	
;[_output_cache]
;	enabled=1

[_mail]
	func=mail2
	
&lt;/code&gt;

</content>
	<keywords></keywords>
	<language>en</language>
	<original_page>0</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=57">
	<page_name>Creating_a_Dashboard</page_name>
	<page_id>57</page_id>
	<page_title>Creating_a_Dashboard</page_title>
	<content>==Creating a Dashboard for your Users==

[[toc]]

Xataface allows you to build powerful data-driven applications quickly, but these applications may be daunting to your users if they don&apos;t know what they can do with the application.  Most applications provide some sort of dashboard or control panel with some introductory instructions and links to commonly used actions in the application.  This makes the application more intuitive for users so that they can start using it right away, even without instruction from the developer.

===Characteristics of a Dashboard===

# Should be the default page when someone visits the application.
# Should be customized to show menus and content that are relevant to the current user.  (i.e. different users may see different links and content on their dashboard).
# Should contain at least some basic instructions so that the user understands what the application does when he visits the dashboard for the first time.
# Should contain links to frequently used actions.

===Strategies: 8 ways to skin the cat===

There are many viable strategies for adding a dashboard to your Xataface application.  This article presents only one.  It has been chosen because it satisfies all of the desired characteristics of a dashboard listed above, and it is easy to implement.

This strategy involves the following components:

# Create a dummy &apos;&apos;dashboard&apos;&apos; table.
# Create a dashboard action and associated template.
# Make sure our dashboard action is the default action for our application (more complex than just using the [[default_action]] directive in the [[conf.ini file]].

==Our Sample Application==

Consider our sample application, a publications management system for professors and research groups at a university.  It allows users to manage their publications using either BibTex format or a web-based form, and embed those publications into their webpage in a slick sortable format.  Currently, when the user accesses the application for the first time, they are shown the &apos;&apos;list&apos;&apos; tab of the &apos;&apos;bibliographies&apos;&apos; table.  This isn&apos;t all that informative and it may not be obvious to the user that their first step should be to create a new bibliography via the &apos;&apos;new record&apos;&apos; button.  Ideally we would like the user to go directly to a dashboard page with options to:

# Add New Bibliography
# Edit an Existing Bibliography
# Embed a Bibliography into their Webpage

And we want some basic instructions so that the user knows what to do when they first access the page.

==The Steps==

To create this dashboard we will follow the steps listed below (and mentioned above in the &apos;&apos;strategies&apos;&apos; section.

===Step 1: Create a dummy &apos;&apos;dashboard&apos;&apos; table===

This may seem unorthodox but it just happens to make our lives easier in the long run.  By creating a dummy table we are able to cause that table to be listed first in the &apos;&apos;_tables&apos;&apos; section of the [[conf.ini file]] and thus be the default table when users visit our application.

&lt;code&gt;
CREATE TABLE dashboard (
    dashboard_id int(11) not null auto_increment primary key
);
INSERT INTO dashboard values (1);
&lt;/code&gt;

===Step 2: Make &apos;&apos;dashboard&apos;&apos; table default===

We now modify the conf.ini file to list the &apos;&apos;dashboard&apos;&apos; table first:
&lt;code&gt;
[_tables]
    dashboard=Dashboard
    bibliographies=Bibliographies
&lt;/code&gt;

===Step 3: Create a Dashboard action and associated template===

This is the step where we actually create our dashboard action.  There are three parts to this story:

====Creating Action PHP Class====

The actual action will be located in the &apos;&apos;actions/dashboard.php&apos;&apos; file of our application, and looks like:

&lt;code&gt;
&lt;?php
class actions_dashboard {
    function handle(&amp;$params){
        $bibs = df_get_records_array(&apos;bibliographies&apos;, array());
        df_display(array(&apos;bibliographies&apos;=&gt;$bibs), &apos;dashboard.html&apos;);
    }
}
&lt;/code&gt;

All this does is loads the &apos;&apos;bibliographies&apos;&apos; records owned by the current user. Elsewhere we are using security filters so that the user can only see &apos;&apos;his&apos;&apos; bibliographies, which is why we don&apos;t need to specify any query here in the &apos;&apos;df_get_records_array&apos;&apos; function.

It then passes those bibliographies to the &apos;&apos;dashboard.html&apos;&apos; template that we create next.

====Creating the Action&apos;s Template====

The template for our action is located in the &apos;&apos;templates/dashboard.html&apos;&apos; file:
&lt;code&gt;
{use_macro file=&quot;Dataface_Main_Template.html&quot;}
    {fill_slot name=&quot;main_column&quot;}
        &lt;h1&gt;Welcome to the BibTeX Publication Management System (BPMS)&lt;/h1&gt;
        
        &lt;p&gt;This system allows you to manage your publications and publish
        them on the web.  Some common actions you may perform with this system
        include:
            &lt;ul&gt;
                &lt;li&gt;&lt;img src=&quot;{$ENV.DATAFACE_URL}/images/add_icon.gif&quot;/&gt;
                    &lt;a href=&quot;{$ENV.DATAFACE_SITE_HREF}?-table=bibliographies&amp;-action=new&quot;&gt;
                        Create New Bibliography&lt;/a&gt;
                &lt;/li&gt;
                &lt;li&gt;&lt;img src=&quot;{$ENV.DATAFACE_URL}/images/edit.gif&quot;/&gt; 
                   Edit existing bibliography: 
                   &lt;select onchange=&quot;window.location.href=this.options[this.selectedIndex].value&quot;&gt;
                    &lt;option value=&quot;&quot;&gt;Select ...&lt;/option&gt;
                    {foreach from=$bibliographies item=bibliography}
                        &lt;option value=&quot;{$bibliography-&gt;getURL(&apos;-action=edit&apos;)}&quot;&gt;
                            {$bibliography-&gt;getTitle()}
                        &lt;/option&gt;
                    
                    {/foreach}
                &lt;/select&gt;
                &lt;/li&gt;
                &lt;li&gt;&lt;img src=&quot;{$ENV.DATAFACE_URL}/images/file.gif&quot;/&gt; 
                    Embed your bibliography in a webpage:
                    &lt;select onchange=&quot;window.location.href=this.options[this.selectedIndex].value&quot;&gt;
                    &lt;option value=&quot;&quot;&gt;Select ...&lt;/option&gt;
                    {foreach from=$bibliographies item=bibliography}
                        &lt;option value=&quot;{$bibliography-&gt;getURL(&apos;-action=view&apos;)}#embed&quot;&gt;
                            {$bibliography-&gt;getTitle()}
                        &lt;/option&gt;
                    
                {/foreach}
                &lt;/select&gt;
                &lt;/li&gt;
                
            &lt;/ul&gt;
    {/fill_slot}
{/use_macro}
&lt;/code&gt;

A few key things to notice in this template:

# It extends the &apos;&apos;Dataface_Main_Template.html&apos;&apos; template placing its content in the &apos;&apos;main_column&apos;&apos; slot.  This allows our action to still display within the header and footer of our application.
# It makes use of the {$ENV.DATAFACE_SITE_URL} and {$ENV.DATAFACE_SITE_HREF} variables to refer to the site&apos;s base url and create links to the desired common actions.
# It provides a direct link to the &apos;&apos;new bibliography record&apos;&apos; form.
# It uses some slick javascript combined with select lists to allow the user to select any of his current bibliogaphies and edit them, or embed them into a webpage.

====Adding entry to the actions.ini file====

Currently our dashboard action has no permissions attached to it so users can see it whether they are logged in or not.  In this particular application we want to require users to log in, and we have set permissions for all logged in users to NO_ACCESS().  Unfortunately this permission setting is only helpful if our action requires a particular permission to access it.  We&apos;ll require the &apos;view&apos; permission for this action, by adding the following to the actions.ini file:

&lt;code&gt;
[dashboard]
    permission=view
&lt;/code&gt;


===Step 4: Specify permissions===

We still want to specify permissions for our &apos;&apos;dashboard&apos;&apos; table to ensure that only logged in users can access the dashboard.  So we create a delegate class for the &apos;&apos;dashboard&apos;&apos; table at &apos;&apos;tables/dashboard/dashboard.php&apos;&apos; with the following contents:

&lt;code&gt;
&lt;?php
class tables_dashboard {
    function getPermissions(&amp;$record){
        if ( getUser() ){
            return Dataface_PermissionsTool::ALL();
        }
        return null;
    }
}
&lt;/code&gt;

&apos;&apos;&apos;Note that we have defined the getUser() function elsewhere as a means of obtaining the current user and checking if a user is indeed logged in.&apos;&apos;&apos;

Notice that this [[getPermissions]] method returns all permissions only if the user is logged in.  Otherwise it returns null, which means that it should use the same permissions as the rest of the application as defined in the [[Application Delegate Class]].

===Step 6: Make &apos;&apos;dashboard&apos;&apos; the default action for the &apos;&apos;dashboard&apos;&apos; table===

Now we just have one more detail that needs to be taken care of.  We want the &apos;&apos;dashboard&apos;&apos; action to be the default action for the &apos;&apos;dashboard&apos;&apos; table only.  By default we would see the &apos;&apos;list&apos;&apos; action which isn&apos;t helpful at all, so we will want to add a rule in our application delegate class to ensure that the user only sees our custom &apos;&apos;dashboard&apos;&apos; action if they access the &apos;&apos;dashboard&apos;&apos; table.  We define a beforeHandleRequest() method in our conf/ApplicationDelegate.php (the application delegate class) file for this purpose:

&lt;code&gt;
&lt;?php
class conf_ApplicationDelegate {
    
...
    function beforeHandleRequest(){
        ...
        $app =&amp; Dataface_Application::getInstance();
	$query =&amp; $app-&gt;getQuery();
	if ( $query[&apos;-table&apos;] == &apos;dashboard&apos; and ($query[&apos;-action&apos;] == &apos;browse&apos; or $query[&apos;-action&apos;] == &apos;list&apos;) ){
	    $query[&apos;-action&apos;] = &apos;dashboard&apos;;
	}
        
        
    }
    
    ...
}
&lt;/code&gt;

This simply checks to see if the table is &apos;&apos;dashboard&apos;&apos; and changes the current action to &apos;&apos;dashboard&apos;&apos; if so.

===Step 7: Try it out===

At this point, we are ready to try out our new dashboard to see how it works.  When we load our application it should now go to the dashboard action that we created.  We should also see &apos;&apos;Dashboard&apos;&apos; listed as the first table in the tables menu.

This dashboard presents a major improvement to our application as it is now much more user friendly.

&lt;nowiki&gt;
&lt;img src=&quot;http://media.weblite.ca/files/photos/pub-dashboard.png?max_width=640&quot;/&gt;
&lt;/nowiki&gt;</content>
	<keywords>dashboard</keywords>
	<language>en</language>
	<original_page>0</original_page>
</wiki>
<wiki id="wiki?page_id=82">
	<page_name>Creating_Printable_Reports</page_name>
	<page_id>82</page_id>
	<page_title>Creating a Custom Printable Report</page_title>
	<content>==Creating a Printable Report==

[[toc]]

It is often useful to provide your users with a printable report that is generated from your database.  Although Xataface doesn&apos;t include an explicit reporting module to allow the end users to create their own reports, you (the developer) can still quite easily produce a report by creating a custom action.  

This report will be subject to the user&apos;s sorting and searching preferences.  E.g. if the user searches for only books about &quot;frogs&quot;, then when he clicks on your printable report it will only display those records that match the query (i.e. only books about frogs).

===Requirements for our report===

# Report will be run against the &quot;products&quot; table (using the WebAuction application).
# Report should be accessible by clicking an icon in the top right of the list view (i.e. the resultlist actions).
# Report should display the product ID, product name, photo, and description.  One product per page.


===Adding the Icon to our Application===

We&apos;ll start out by finding an appropriate icon to use for our action.  There are loads of free icons that you can download (please observe and respect the license agreement of any icon library that you use).  Two good free icon libraries include:

# [http://www.famfamfam.com/lab/icons/silk/ FamFamFam Silk Icons]
# [http://tango.freedesktop.org/Tango_Icon_Library Tango Icon Library]

Once you have found the icon you want to use, just upload it somewhere inside your application&apos;s directory.  It might be a good idea to create a directory to store your images if you haven&apos;t already.  An appropriate name might by &apos;&apos;images&apos;&apos;.  For this example, we&apos;ll use the [[Image:http://dev.weblite.ca/phpimageserver/photos/icons/printer.png]] icon from the FamFamFam icon library.  So we upload this icon to
 %APPLICATION_PATH%/images/printer.png

Next we need to create an entry in our application&apos;s [[actions.ini file]] so that Xataface knows about our action, and where we want its icon to be displayed.  We&apos;ll start out with a basic definition that just specifies the icon for the action, and the &apos;&apos;category&apos;&apos; of the action.

&lt;code&gt;
[printable_report]
    icon=&quot;{$site_url}/images/printer.png&quot;
    category=result_list_actions
    description=&quot;See this product list in a printable format&quot;
&lt;/code&gt;

The &apos;&apos;result_list_actions&apos;&apos; category setting means that the icon for our action will be included along with the result list actions, which are located in the top right corner in the list tab.  Now if we reload our application and look at the &quot;list&quot; tab, you&apos;ll see that the icon group in the top right now includes our icon:

[[Image:http://media.weblite.ca/files/photos/Picture%20-5.png?max_width=640]]

If you don&apos;t see this icon, but see the text &quot;printable_report&quot; instead, then you have entered an incorrect path to the icon in the &apos;&apos;icon&apos;&apos; directive.  If you don&apos;t see an icon at all or any text, then your &apos;&apos;category&apos;&apos; directive may be incorrect.  Check that it is exactly &quot;result_list_actions&quot;.

If you mouse over your icon you&apos;ll see the text that you specified as your &apos;&apos;description&apos;&apos; directive for the action:

[[Image:http://media.weblite.ca/files/photos/Picture%20-6.png?max_width=640]]

You&apos;ll notice, if you try to click on your icon, that nothing happens.  This is because we haven&apos;t yet specified a URL for your action.  We&apos;ll wait to specify our URL, until we&apos;ve built the back-end of our action (i.e. the actual report).

===Creating the Actual Report===

Most reports involve the following pieces:

# Fetch the found set of records from the database.
# Loop through the found set and output some information about each record.
# Optionally use a template to integrate the report into your application&apos;s look and feel.

All reports will be placed in the framework of a custom Xataface action.  In our case we add a file to our application &apos;&apos;actions&apos;&apos; directory named after our action:
 %APPLICATION_PATH%/actions/printable_report.php

with the following contents:

&lt;code&gt;
&lt;?php
class actions_printable_report {
    function handle(&amp;$params){
    	echo &quot;Hello world!!!&quot;;
    }
}
&lt;/code&gt;

Please note the following about this snippet:

# The action was placed in a file &apos;&apos;actions/printable_report.php&apos;&apos; because the action is named &apos;&apos;printable_report&apos;&apos; (referring to our definition in the &apos;&apos;[[actions.ini file]]&apos;&apos;.  If the action was named &apos;&apos;foo&apos;&apos;, then we would place our action in file &apos;&apos;actions/foo.php&apos;&apos;.
# The &apos;&apos;printable_report.php&apos;&apos; file contains a single class named &apos;&apos;actions_printable_report&apos;&apos; after the name of the action.
# The action class contains a single method &apos;&apos;handle&apos;&apos; which handles the request for the action (i.e. outputs the report the way we like).  This method must exist and me named exactly &apos;&apos;handle&apos;&apos;.
# The &apos;&apos;handle&apos;&apos; method takes a single &apos;&apos;&amp;$params&apos;&apos; parameter which contains some parameters that may be passed to the action.  We won&apos;t be dealing with these in this example.


Before proceeding, let&apos;s try accessing our action just to make sure that we&apos;re on the right track.  Point your browser to 
 http://example.com/yourapplication/index.php?-action=printable_report

Note that you don&apos;t point our web browser directly to your action php file (in the &apos;&apos;actions&apos;&apos; directory.  Rather you point it to your application&apos;s entry point (index.php file), and specify the action via the &apos;&apos;-action&apos;&apos; GET parameter.  Your web browser should display something like:

[[Image:http://media.weblite.ca/files/photos/Picture%204.png?max_width=640]]

If you get a blank white screen, then you should check your error log to see where the error is occuring.  See [[Troubleshooting]] for general Xataface troubleshooting strategies in this case.

Now that we have all of the formalities out of the way, we can proceed to meat of our report.

====Retrieving the Found Set====

Let&apos;s build onto our action now.  First we will load the found set of records as follows:

&lt;code&gt;
&lt;?php
class actions_printable_report {
    function handle(&amp;$params){
    	$app =&amp; Dataface_Application::getInstance();
    	$query =&amp; $app-&gt;getQuery();
    	
    	if ( $query[&apos;-table&apos;] != &apos;products&apos; ){
    		return PEAR::raiseError(&apos;This action can only be called on the Products table.&apos;);
    	}
    	
    	$products = df_get_records_array(&apos;products&apos;, $query);
    	
    }
}
&lt;/code&gt;

Things to note in this snippet:

# We start be loading a reference to the &apos;&apos;Dataface_Application&apos;&apos; object.
# We then use the &apos;&apos;Dataface_Application&apos;&apos; object to load the current query.  This is essentially an associative array of all of the GET parameters, but with some guaranteed attributes such as &apos;&apos;-table&apos;&apos; and &apos;&apos;-action&apos;&apos;.
# In our particular action we are designing it to only work for the &apos;&apos;products&apos;&apos; table so we do a check on the query parameters to make sure that this is the case.  If someone tries to run this action from outside the products table (e.g. if -action=foo) then an error will be displayed.
# We use the df_get_records_array() function to return all matching records on the products table.  It returns an array of [[Dataface_Record]] objects.


====Overriding -skip and -limit====

Xataface allows the user to specify the number of records to display and the position in the found set to start from by adding the &apos;&apos;-skip&apos;&apos; and &apos;&apos;-limit&apos;&apos; GET parameters to a request.  If these are omitted, then default values of 0 and 30 are used respectively.  You may notice that if you click &quot;Next&quot; in list view, you see &apos;-skip&apos; and &apos;-limit&apos; parameters automatically added to the URL.

&apos;&apos;df_get_records_array&apos;&apos; respects the -limit and -skip parameters that are specified in the query.  I.e. if -skip and -limit are omitted it will return only the first 30 records from the found set.  If -skip=1 and -limit=10 then it will return 10 records starting from the 2nd record (2nd becuase -skip=0 would point to the first record).  This may be desired behavior for your report, but in some reports you may want to print off the entire found set.  If this is the case, you will want to explicitly set the -skip and -limit parameters in the &apos;&apos;$query&apos;&apos; array before passing it to &apos;&apos;df_get_records_array&apos;&apos;.  E.g.:

&lt;code&gt;
$query =&amp; $app-&gt;getQuery();
$query[&apos;-skip&apos;] = 0;
$query[&apos;-limit&apos;] = 10000;
$products = df_get_records_array(&apos;products&apos;, $query);
&lt;/code&gt;


====Looping through and Printing Product Info====

Now comes the fun part.  We&apos;re just going to loop through our found set and print off the product information:

&lt;code&gt;


foreach ($products as $p){
	

	echo &apos;&lt;table&gt;&apos;
		.&apos;&lt;tr&gt;&lt;th&gt;Product ID&lt;/th&gt;&lt;td&gt;&apos;.$p-&gt;htmlValue(&apos;product_id&apos;).&apos;&lt;/td&gt;&lt;/tr&gt;&apos;
		.&apos;&lt;tr&gt;&lt;th&gt;Product Name&lt;/th&gt;&lt;td&gt;&apos;.$p-&gt;htmlValue(&apos;product_name&apos;).&apos;&lt;/td&gt;&lt;/tr&gt;&apos;
		.&apos;&lt;tr&gt;&lt;th&gt;Description&lt;/th&gt;&lt;td&gt;&apos;.$p-&gt;htmlValue(&apos;product_description&apos;).&apos;&lt;/td&gt;&lt;/tr&gt;&apos;
		.&apos;&lt;tr&gt;&lt;th&gt;Photo&lt;/th&gt;&lt;td&gt;&apos;.$p-&gt;htmlValue(&apos;product_image&apos;).&apos;&lt;/td&gt;&lt;/tr&gt;&apos;
		.&apos;&lt;/table&gt;&apos;;
}

&lt;/code&gt;


The entire action at this point will look like:

&lt;code&gt;

&lt;?php
class actions_printable_report {
    function handle(&amp;$params){
    	$app =&amp; Dataface_Application::getInstance();
    	$query =&amp; $app-&gt;getQuery();
    	$query[&apos;-skip&apos;] = 0;
		$query[&apos;-limit&apos;] = 10000;
		
    	if ( $query[&apos;-table&apos;] != &apos;products&apos; ){
    		return PEAR::raiseError(&apos;This action can only be called on the Products table.&apos;);
    	}
    	
    	$products = df_get_records_array(&apos;products&apos;, $query);
    	foreach ($products as $p){
	

			echo &apos;&lt;table&gt;&apos;
				.&apos;&lt;tr&gt;&lt;th&gt;Product ID&lt;/th&gt;&lt;td&gt;&apos;.$p-&gt;htmlValue(&apos;product_id&apos;).&apos;&lt;/td&gt;&lt;/tr&gt;&apos;
				.&apos;&lt;tr&gt;&lt;th&gt;Product Name&lt;/th&gt;&lt;td&gt;&apos;.$p-&gt;htmlValue(&apos;product_name&apos;).&apos;&lt;/td&gt;&lt;/tr&gt;&apos;
				.&apos;&lt;tr&gt;&lt;th&gt;Description&lt;/th&gt;&lt;td&gt;&apos;.$p-&gt;htmlValue(&apos;product_description&apos;).&apos;&lt;/td&gt;&lt;/tr&gt;&apos;
				.&apos;&lt;tr&gt;&lt;th&gt;Photo&lt;/th&gt;&lt;td&gt;&apos;.$p-&gt;htmlValue(&apos;product_image&apos;).&apos;&lt;/td&gt;&lt;/tr&gt;&apos;
				.&apos;&lt;/table&gt;&apos;;
		}
    	
    }
}
&lt;/code&gt;

Now we refresh our action in the web browser, or point the browser again to:
 http://example.com/yourapplication/index.php?-action=printable_report&amp;-table=products
 
It should display something like:

[[Image:http://media.weblite.ca/files/photos/Picture%205.png?max_width=640]]

If you get a blank white screen, please check out the [[Troubleshooting]] section for general Xataface troubleshooting strategies.

====Adding a Little Style====

It is a good idea to at least provide the proper HTML HEAD and BODY tags for your report.  And to help make things a little nicer looking we&apos;re going to add some CSS styles to:

# Make the table field labels vertically aligned to the top.
# Change the font to helvetica.

This is easy to do with simple echo statements:

&lt;code&gt;
echo &apos;&lt;html&gt;&lt;head&gt;&apos;
	.&apos;&lt;title&gt;Printable Report&lt;/title&gt;&apos;
	.&apos;&lt;style type=&quot;text/css&quot;&gt;&apos;
	.&apos;	th { vertical-align: top}&apos;
	.&apos;&lt;/style&gt;&apos;
	.&apos;&lt;/head&gt;&apos;
	.&apos;&lt;body&gt;&apos;;
	
	//...
	


&lt;/code&gt;

So our finished action looks like:


&lt;code&gt;
&lt;?php
class actions_printable_report {
    function handle(&amp;$params){
    	$app =&amp; Dataface_Application::getInstance();
    	$query =&amp; $app-&gt;getQuery();
    	$query[&apos;-skip&apos;] = 0;
		$query[&apos;-limit&apos;] = 10000;
		
    	if ( $query[&apos;-table&apos;] != &apos;products&apos; ){
    		return PEAR::raiseError(&apos;This action can only be called on the Products table.&apos;);
    	}
    	
    	$products = df_get_records_array(&apos;products&apos;, $query);
    	
    	
    	
    	echo &apos;&lt;html&gt;&lt;head&gt;&apos;
			.&apos;&lt;title&gt;Printable Report&lt;/title&gt;&apos;
			.&apos;&lt;style type=&quot;text/css&quot;&gt;&apos;
			.&apos;	th { vertical-align: top}&apos;
			.&apos;&lt;/style&gt;&apos;
			.&apos;&lt;/head&gt;&apos;
			.&apos;&lt;body&gt;&apos;;
    	foreach ($products as $p){
	

			echo &apos;&lt;table&gt;&apos;
				.&apos;&lt;tr&gt;&lt;th&gt;Product ID&lt;/th&gt;&lt;td&gt;&apos;.$p-&gt;htmlValue(&apos;product_id&apos;).&apos;&lt;/td&gt;&lt;/tr&gt;&apos;
				.&apos;&lt;tr&gt;&lt;th&gt;Product Name&lt;/th&gt;&lt;td&gt;&apos;.$p-&gt;htmlValue(&apos;product_name&apos;).&apos;&lt;/td&gt;&lt;/tr&gt;&apos;
				.&apos;&lt;tr&gt;&lt;th&gt;Description&lt;/th&gt;&lt;td&gt;&apos;.$p-&gt;htmlValue(&apos;product_description&apos;).&apos;&lt;/td&gt;&lt;/tr&gt;&apos;
				.&apos;&lt;tr&gt;&lt;th&gt;Photo&lt;/th&gt;&lt;td&gt;&apos;.$p-&gt;htmlValue(&apos;product_image&apos;).&apos;&lt;/td&gt;&lt;/tr&gt;&apos;
				.&apos;&lt;/table&gt;&apos;;
		}
		
		echo &apos;&lt;/body&gt;&lt;/html&gt;&apos;;
    	
    }
}
&lt;/code&gt;



===Connecting the Icon to the Action===

FInally it is time to connect our Icon to our Action.  We do this by adding a &apos;&apos;url&apos;&apos; directive for the action in the &apos;&apos;[[actions.ini file]]&apos;&apos;:


&lt;code&gt;
[printable_report]
    icon=&quot;{$site_url}/images/printer.png&quot;
    category=result_list_actions
    description=&quot;See this product list in a printable format&quot;
    url=&quot;{$app-&gt;url(&apos;-action=printable_report&apos;)}&quot;
&lt;/code&gt;

Explanation of the &apos;&apos;url&apos;&apos; directive in this snippet:

* The &apos;&apos;url&apos;&apos; method of the &apos;&apos;[[Dataface_Application]]&apos;&apos; object is used to generate a URL with the user&apos;s current query settings, but with the &apos;&apos;-action&apos;&apos; parameter set to &apos;&apos;printable_report&apos;&apos;.

Now if we reload our application, go to the list tab of the &apos;&apos;products&apos;&apos; table and click on our icon, it should take us to our action:

[[Image:http://media.weblite.ca/files/photos/Picture%207.png?max_width=640]]

===Trying out the action on different found sets with different sort orders===

One of the cool things about this action is that it is tied directly into the Xataface find settings so that th user is able to search for a subset of products and run our report on only those products that were found.  The user can also perform a sort on any column and this sort will be respected by our report.

===Hiding Icon from Other Tables===

Since our action is only intended to operate on the &apos;&apos;products&apos;&apos; table it probably isn&apos;t a good idea to make the icon visible for every other table.  For example, if you go to the list view of the &apos;&apos;users&apos;&apos; table, you&apos;ll see the printer icon in the top right just like it appears for the &apos;&apos;products&apos;&apos; table.  Clicking on it should display our error:

[[Image:http://media.weblite.ca/files/photos/Picture%206.png?max_width=640]]

We will use a &apos;&apos;condition&apos;&apos; directive for our action to hide it from tables other than the &apos;&apos;products&apos;&apos; table as follows:

 condition=&quot;$query[&apos;-table&apos;] == &apos;products&apos;&quot;
 
So our action will now look like:

&lt;code&gt;
[printable_report]
    icon=&quot;{$site_url}/images/printer.png&quot;
    category=result_list_actions
    description=&quot;See this product list in a printable format&quot;
    url=&quot;{$app-&gt;url(&apos;-action=printable_report&apos;)}&quot;
    condition=&quot;$query[&apos;-table&apos;] == &apos;products&apos;&quot;
&lt;/code&gt;

Now if you reload the list for the &apos;&apos;users&apos;&apos; table you&apos;ll notice that the printer icon is now gone.  But returning to the &apos;&apos;products&apos;&apos; table shows our action still alive and well.

===Locking Down our Action with Permissions===

In our case we don&apos;t want our action to be accessible to all users.  Only administrators.  Xataface permissions and all its possibilities are beyond the scope of this tutorial, but we still want to demonstrate how to lock down this action.  The WebAuction application into which this action is being installed defines a permission called &apos;&apos;reports&apos;&apos; which only administrators have.  We will use this permission to limit access to this action as follows in the actions.ini file:
 permission=reports

So the actions.ini file will now look like:
&lt;code&gt;
[printable_report]
    icon=&quot;{$site_url}/images/printer.png&quot;
    category=result_list_actions
    description=&quot;See this product list in a printable format&quot;
    url=&quot;{$app-&gt;url(&apos;-action=printable_report&apos;)}&quot;
    condition=&quot;$query[&apos;-table&apos;] == &apos;products&apos;&quot;
    permission=reports
&lt;/code&gt;

Now only administrators will see our icon, and if non-administrators attempt to access out action by typing in its URL directly, they will receive an &quot;Access Denied&quot; message.

</content>
	<keywords></keywords>
	<language>en</language>
	<original_page></original_page>
</wiki>
<wiki id="wiki?page_id=74">
	<page_name>GettingStarted:first_application</page_name>
	<page_id>74</page_id>
	<page_title>Creating your First Application</page_title>
	<content>==Creating Your First Application==

Build a simple Xataface application.

For our first Xataface application we will try to build a web site for Faculty of Widgetry (From the example in the &quot;Why Use Xataface&quot; page). The web site needs to store information about programs and courses. An entity-relationship diagram (ERD) for this website is included below:

[[Image:http://xataface.com/documentation/tutorial/getting_started/er-diagram.png]]

As the ERD shows, our database will need 2 tables (Course and Program). Our next step is to build this database. You can use any MySQL database administration tool to builld the database. My personal tool of choice is PHPMyAdmin.

===Step 1: Creating the database using PHPMyAdmin===

The following steps describe the procedure for creating this database using PHPMyAdmin.

# At the main menu of PHPMyAdmin, type &apos;FacultyOfWidgetry&apos; into the &apos;Create new database field&apos; as follows: &lt;nowiki&gt;&lt;br/&gt;&lt;/nowiki&gt;[[Image:http://xataface.com/documentation/tutorial/getting_started/new_database.gif]] &lt;nowiki&gt;&lt;br/&gt;&lt;/nowiki&gt;Then click &apos;Create&apos;.
# First we will create the &apos;Course&apos; table to hold course information. In the &apos;FacultyOfWidgetry&apos; page, fill in the &apos;Create new table text field as follows: &lt;nowiki&gt;&lt;br/&gt;&lt;/nowiki&gt;[[Image:http://xataface.com/documentation/tutorial/getting_started/create_table.gif]] &lt;nowiki&gt;&lt;br/&gt;&lt;/nowiki&gt; Then click &apos;Go&apos;.
# This should bring up a form to specify the fields for the course table: &lt;nowiki&gt;&lt;br/&gt;&lt;/nowiki&gt;[[Image:http://xataface.com/documentation/tutorial/getting_started/course-table-def-small.gif]] &lt;nowiki&gt;&lt;br/&gt;&lt;/nowiki&gt; Then click &quot;Save&quot;. The resulting SQL to create the Course table is as follows:&lt;code&gt;
CREATE TABLE `Course` (
 `CourseID` int(11) NOT NULL auto_increment,
 `ProgramID` int(11),
 `CourseTitle` varchar(64) NOT NULL default &apos;&apos;,
 `CourseDescription` text NOT NULL,
 `HTMLOutline` text NOT NULL,
 `PDFOutline` longblob NOT NULL,
 `PDFOutline_mimetype` varchar(64),
 `Subject` varchar(128) NOT NULL default &apos;&apos;,
 `CourseNumber` varchar(10) NOT NULL default &apos;&apos;,
 `Credits` int(5) NOT NULL default &apos;0&apos;,
 `LastModified` timestamp NOT NULL default CURRENT_TIMESTAMP,
 PRIMARY KEY (`CourseID`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 COMMENT=&apos;Store courses&apos; AUTO_INCREMENT=1 ;
&lt;/code&gt;
#In a similar fashion, create the Program table. The resulting SQL for this table is:&lt;code&gt;
CREATE TABLE `Program` (
 `ProgramID` int(11) NOT NULL auto_increment,
 `ProgramName` varchar(64) NOT NULL default &apos;&apos;,
 `ProgramDescription` text NOT NULL,
 `HTMLOutline` text NOT NULL,
 `PDFOutline` longblob NOT NULL,
 `PDFOutline_mimetype` varchar(32),
 `AdmissionDeadline` date NOT NULL default &apos;0000-00-00&apos;,
 `LastModified` timestamp NOT NULL default CURRENT_TIMESTAMP,
 PRIMARY KEY (`ProgramID`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 COMMENT=&apos;Academic Program&apos; AUTO_INCREMENT=1 ;
&lt;/code&gt;
# The database has been created with 2 tables: Program and Course. We can now move on to building the Xataface application.

===Step 2: Create Xataface Application===

Our Xataface application will provide a user-friendly front-end to our database. A basic application consists of a directory with a configuration file and an entry page (PHP file). Xataface comes with a PHP setup script (called makesite) to create the skeleton for your application. Alternatively you can set up the application manually.

Note: For the following instructions and examples, my Daface installation is located at /Users/shannah/Sites/dataface and the URL for the installation is http://localhost/~shannah/dataface.

====Method 1: Setting up application with the &apos;makesite&apos; script====

# From the command prompt, navigate to the dataface directory. (in my case &apos;&apos;/Users/shannah/Sites/dataface&apos;&apos;).
# This directory contains a file named &apos;makesite&apos;. It is a PHP script that can be used to build a website powered by Xataface. To find out the usage options for this script you can simply call the script with no parameters. E.g.,&lt;code&gt; 
stevepbook:~/Sites/dataface shannah$ ./makesite
&lt;/code&gt;
# This will give you usage instructions for the script as follows:&lt;code&gt;
makesite: invalid options entered.

 Usage: makesite &lt;site_path&gt; &lt;db_user&gt;:&lt;db_pass&gt;@&lt;db_host&gt;/&lt;db_name&gt; &lt;dataface_url&gt;
 or
 php makesite &lt;site_path&gt; &lt;db_user&gt;:&lt;db_pass&gt;@&lt;db_host&gt;/&lt;db_name&gt; &lt;dataface_url&gt;
 where 
 &lt;site_path&gt; = The path (absolute or relative) to your application directory.
 &lt;db_user&gt; = The MySQL username to connect to the database
 &lt;db_pass&gt; = The User&apos;s password to connect to the database
 &lt;db_host&gt; = The MySQL host name.
 &lt;db_name&gt; = The name of the mysql database for the application.
 &lt;dataface_url&gt; = The URL to the Xataface installation

 Examples:

 makesite ../FacultyOfWidgetry root:password@localhost/FacultyOfWidgetry /dataface

 The above command would create a site at ../FacultyOfWidgetry (i.e., the Faculty of 
 Widgetry directory in the parent directory. The database used for this site is 
 located at localhost, and the database name is FacultyOfWidgetry. The username
 to connect to the database is root and his password is password.
&lt;/code&gt;
# We create our FacultyOfWidgetry site using the following command:&lt;code&gt;
./makesite ../FacultyOfWidgetry \
    root@localhost/FacultyOfWidgetry \
    http://localhost/~shannah/dataface
&lt;/code&gt;
# This will create our application in the FacultyOfWidgetry folder if everything worked ok. The contents of the folder will look like: &lt;nowiki&gt;&lt;br/&gt;&lt;/nowiki&gt;[[Image:http://xataface.com/documentation/tutorial/getting_started/directory-structure-1.gif]]

You may be wondering what these files. Here is the short version (Read the next section &quot;Creating applications manually&quot; for more detailed information about the contents of these files.

The index.php file is the entry point for your application (i.e., you point the web browser at this file to use the application. 
The conf.ini file contains database connection settings and some other minor settings, like what should appear in the navigation menu.
The tables/Program (tables/Course) directory can contain configuration files specific to the Program (Course) table. More on that later. 

# Point your web browser to the FacultyOfWidgetry directory to see the application: &lt;nowiki&gt;&lt;br/&gt;&lt;/nowiki&gt;[[Image:http://xataface.com/documentation/tutorial/getting_started/basic-application-1.gif]]
#Your application is now created. It will enable you to add, edit, delete, and find records in either the Course table or the Program table. There will be more on the basics of using this application in the next section.	

====Method 2: Setting up application manually====

Using the makesite script as described above is the recommended way to set up an application because it saves time. However, it is very easy to set up the application manually. Just follow these steps:

# Create a directory for the application somewhere in your web site (preferably outside your xataface directory). We will call our directory &apos;FacultyOfWidgetry&apos;. ):&lt;code&gt;
mkdir FacultyOfWidgetry
&lt;/code&gt;
# Create a PHP file to serve as the access point for the application. Generally we will name this file &apos;index.php&apos;, but you can name it anything. Place the following contents in the index.php file:&lt;code&gt;
&lt;?
require_once &apos;/path/to/dataface/dataface-public-api.php&apos;;
df_init(__FILE__, &apos;http://yourdomain.com/dataface&apos;);
$app =&amp; Dataface_Application::getInstance();
$app-&gt;display();
&lt;/code&gt;&lt;nowiki&gt;&lt;p&gt;OK, I guess some explanations are in order.&lt;/p&gt;&lt;p&gt;
The first line imports the all of the public functions for dataface from the dataface-public-api.php file.&lt;/p&gt;&lt;p&gt;
The second line initializes the application for the current directory and specifies the URL to the dataface installation.&lt;/p&gt;&lt;p&gt;
The third line obtains an instance to the Application object - the core of your Dataface application.&lt;/p&gt;&lt;p&gt;
The fourth line simply displays the application.&lt;/p&gt;&lt;/nowiki&gt;
# Create a file named &apos;conf.ini&apos; to contain database connection information. Its contents should be:&lt;code&gt;
[_database]
	host = &quot;localhost&quot;
	user = &quot;dbuser&quot;
	password = &quot;secret&quot;
	name = &quot;FacultyOfWidgetry&quot;

[_tables]
	Course = &quot;Course&quot;
	Program = &quot;Program&quot;
&lt;/code&gt;&lt;nowiki&gt;&lt;p&gt;&lt;b&gt;Explanations:&lt;/b&gt;&lt;/p&gt;&lt;p&gt;There are 2 sections in this INI file: &apos;_database&apos;, and &apos;_tables&apos;.&lt;/p&gt;&lt;p&gt;
The &apos;_database&apos; section specifies the database connection information for the MySQL database.&lt;/p&gt;&lt;p&gt;
The &apos;_tables&apos; section specifies which tables will be included in the navigation menu for the application.&lt;/p&gt;&lt;/nowiki&gt;
# At this point, the application is functional. However there is one more thing that should be done for security reasons. The conf.ini file contains sensitive password information and should not be served to the web. We will create an .htaccess file to tell Apache NOT to serve this (or any) .ini file. The .htaccess file should contain:&lt;code&gt;
&lt;FilesMatch &quot;\.ini$&quot;&gt;
	Deny from all
&lt;/FilesMatch&gt;&lt;/code&gt;
# The directory structure of your application will now look like: &lt;nowiki&gt;&lt;br/&gt;&lt;/nowiki&gt;[[Image:http://xataface.com/documentation/tutorial/getting_started/basic-app-dir-structure-manual-1.gif]]&lt;nowiki&gt;&lt;p&gt;
Note, however, that there is also an .htaccess file that is hidden from this image.&lt;/p&gt;&lt;p&gt;You may be wondering why there is no &apos;tables&apos; directory like the directory structure that was generated by the makesite script. The &apos;tables&apos; directory is not required for the application to be functional. It will be required later on when we start to decorate the database.&lt;/p&gt;&lt;/nowiki&gt;
# The application is now ready to go. Point your web browser to the index.php file that you created. It will look like:&lt;nowiki&gt;&lt;br/&gt;&lt;/nowiki&gt;[[Image:http://xataface.com/documentation/tutorial/getting_started/basic-application-1.gif]]

===Download source files===

[[File:http://xataface.com/documentation/tutorial/getting_started/facultyofwidgetry-4-tar.gz|Download the source files]] for this application at a tar.gz archive.
These files reflect the state of the application at this point of the tutorial. As later sections make changes to the application you will be able to download those versions also.</content>
	<keywords>htaccess first application installation</keywords>
	<language>en</language>
	<original_page></original_page>
</wiki>
<wiki id="wiki?page_id=76">
	<page_name>GettingStarted:customizing</page_name>
	<page_id>76</page_id>
	<page_title>Customizing Field labels, descriptions, and widgets</page_title>
	<content>==Customizing Field labels, descriptions, and widgets==

Using simple INI configuration files, you can customize the look and feel of your application. You can change widgets, labels, field descriptions, and more.
In the previous 2 sections we learned how to create a simple application by desiging a database and then installing the basic directory structure to make our application operational. Now it is time to &quot;decorate&quot; the application a little bit. Decoration occurs by way of simple configuration files that are placed in strategic locations in the application. We can customize such things as:

* Widget types (e.g., use a select list for a field rather than a text field)
* Labels (e.g., The ProgramName field&apos;s label can say &quot;Program Name&quot; instead of just &quot;ProgramName&quot;)
* Field Descriptions . You can add descriptions to fields to help explain their meaning and how to use the application.
* HTML attributes. (e.g., Make a text field 50 characters wide)

===Table Configuration Directories===

You will recall, that when we used the &apos;makesite&apos; script to generate the directory structure for our web application, it created a directory named &apos;tables&apos;, with subdirectories named after each of the tables in our database. The directory structure of the application looked like:

[[Image:http://xataface.com/documentation/tutorial/getting_started/directory-structure-1.gif]]

The &apos;tables/Program&apos; and &apos;tables/Course&apos; are refered to as &quot;table configuration directories&quot; . All of the configuration files a table in a Xataface application are stored in its associated table configuration directory. For example all configuration files for the &apos;Program&apos; table are located in the &apos;tables/Program&apos; directory.

There are 4 main files that are generally contained in a table&apos;s configuration directory:

* &apos;&apos;&apos;fields.ini&apos;&apos;&apos; - Contains configuration for the fields of the table (e.g., field labels, descriptions, widget types, etc...)
* &apos;&apos;valuelists.ini&apos;&apos;&apos; - Contains value lists (vocabularies) that can be used in the table to limit input into certain fields like select lists.
* &apos;&apos;&apos;relationships.ini&apos;&apos;&apos; - Defines the relationships between this table and other tables in the application.
* &apos;&apos;&apos;&lt;TableName&gt;.php&apos;&apos;&apos; (where &lt;TableName&gt; is the name of the table. - A delegate PHP class that allows you to further customize the behavior of the application with respect to this table. May contain custom fields, importing/exporting functionality, permissions information, and more...

===Customizing Labels and Descriptions===

We will start off by adding custom labels and descriptions to the &apos;Program&apos; table of our &apos;FacultyOfWidgetry&apos; application. This sort of customization settings are placed in a file named &apos;fields.ini&apos; inside the table&apos;s configuration directory.

# Create the &apos;fields.ini&apos; file in the Program table configuration directory (i.e., tables/Programs/fields.ini).
# Add the following to this file:&lt;code&gt;
[ProgramName]
	widget:label = &quot;Program Name&quot;
	widget:description = &quot;Enter the name of the program&quot;
&lt;/code&gt;&lt;nowiki&gt;&lt;br&gt;&lt;/nowiki&gt;Now look at the &quot;Edit Record&quot; form in the Xataface application:

[[Image:http://xataface.com/documentation/tutorial/getting_started/program-name-label-1.gif]]


Notice how the label for the &quot;ProgramName&quot; now says &quot;Program Name&quot; (note the space between &quot;Program&quot; and &quot;Name&quot;). And its description matches the description specified in the fields.ini file.

The widget:label and widget:description attributes can be defined for any field in any table of the application.

===Using different widgets===

If no widgets are defined in the fields.ini file, a Xataface application will make a best guess at the type of widget that should be used to edit the value in a field. In general, the widgets used by default are as follows:

* VARCHAR, CHAR, INT : html text field
* DATE, DATETIME fields: calendar widget
* TEXT fields : html text area
* BLOB fields : html file upload field
* INT Fields with &quot;AUTO INCREMENT&quot; : html hidden field
* VARCHAR or CHAR fields with &quot;Password&quot; or &quot;password&quot; as part of the name : html password field
* ENUM fields : html select list
* SET fields : html checkbox group (not yet supported as of this writing).

You can change the widget that is used to edit a field by specifying a &quot;widget:type&quot; attribute for the field in the fields.ini file. For more information about the available widgets, see [[widget:type]].

====Example: Using HTML Editor to edit the HTMLOutline field====

Clearly the HTMLOutline field in the Program table is intended to store HTML content. By default our application only provides a text area to do the editing so the user is expected to enter the HTML markup by hand. It would be much better to provide the user with a WYSIWYG (What you see is what you get) HTML editor widget. That is exactly what we are going to do.
We will add a section to the fields.ini file so that it now looks like: &lt;code&gt;
[ProgramName]
	widget:label = &quot;Program Name&quot;
	widget:description = &quot;Enter the name of the program&quot;

[HTMLOutline]
	widget:type = &quot;htmlarea&quot;
&lt;/code&gt;

Now refresh the Xataface application in your web browser and look at the edit form for a record of the Program table:

[[Image:http://xataface.com/documentation/tutorial/getting_started/htmlarea-1.gif]]

As you can see, the HTMLOutline field now has an HTML Editor widget for editing. Most users will find this much nicer to work with than a normal text area. Xataface uses FCKEditor for its html editor widget.

There are a number of widgets that can be specified in the [[widget:type]] parameter:

* &apos;&apos;&apos;[[checkbox]]&apos;&apos;&apos; - An HTML checkbox (or checkbox group depending on context).
* &apos;&apos;&apos;[[date]]&apos;&apos;&apos; - Month/Day/Year select lists for selecting dates.
* &apos;&apos;&apos;[[calendar]]&apos;&apos;&apos; - A text field with a button that opens a small calendar widget when clicked.
* &apos;&apos;&apos;[[group]]&apos;&apos;&apos; - A complex widget type for editing multiple values as a group (useful for XML fields)
* &apos;&apos;&apos;[[hidden]]&apos;&apos;&apos; - a hidden field
* &apos;&apos;&apos;[[password]]&apos;&apos;&apos; - An HTML password widget
* &apos;&apos;&apos;[[select]]&apos;&apos;&apos; - An HTML select list (requires the &apos;vocabulary&apos; attribute)
* &apos;&apos;&apos;[[static]]&apos;&apos;&apos; - an uneditable field
* &apos;&apos;&apos;[[table]]&apos;&apos;&apos; - A complex widget type for editing multiple values in a tabular format (Useful for XML fields)
* &apos;&apos;&apos;[[text]]&apos;&apos;&apos; - an html text field
* &apos;&apos;&apos;[[textarea]]&apos;&apos;&apos; - an html text area

===Changing HTML attributes of widgets===

Sometimes you may want even finer grained control of your widgets&apos; appearance than to just specify the type, label, and desription. Perhaps you want to make a text field 50 characters wide, or to set the CSS class of the html element. This can be done using the &apos;widget:atts:&apos; parameter for a field. A short example is the easiest way to explain how this works.

Modify the fields.ini for the Program table so it looks like:&lt;code&gt;
[ProgramName]
widget:label = &quot;Program Name&quot;
widget:description = &quot;Enter the name of the program&quot;
widget:atts:size = 50
widget:atts:style = &quot;font-size: 24pt; font-family: Apple Chancery&quot;

[HTMLOutline]
widget:type = htmlarea
&lt;/code&gt;

We have added 2 lines:&lt;code&gt;
widget:atts:size = 50
widget:atts:style = &quot;font-size: 24pt; font-family: Apple Chancery&quot;
&lt;/code&gt;

What this does is add the html attributes size=&quot;50&quot; and style=&quot;font-size: 24pt; font-family: Apple Chancery&quot; to the html text field that is used to edit the ProgramName field.
Look at the results:

[[Image:http://xataface.com/documentation/tutorial/getting_started/widget-atts-1.gif]]

The HTML tag for the text field now looks like:&lt;code&gt;
&lt;input class=&quot;default&quot; id=&quot;ProgramName&quot; name=&quot;ProgramName&quot; 
	type=&quot;text&quot; size=&quot;50&quot; 
	style=&quot;font-size: 24pt; 
		font-family: Apple Chancery&quot; 
	value=&quot;Basic Widgetry&quot; 
/&gt;	
&lt;/code&gt;
In fact you can add arbitrary attributes to any of the fields using the same convention. Some useful examples are:

* &apos;&apos;&apos;[[widget:atts:rows]]&apos;&apos;&apos; for text areas to set the number of rows of text they should display.
* &apos;&apos;&apos;[[widget:atts:cols]]&apos;&apos;&apos; for text areas to set the number of columns (1 character = 1 column)
You can even use javascript calls in here if you like:
* &apos;&apos;&apos;[[widget:atts:onclick]]&apos;&apos;&apos; = &quot;doJsFunction();&quot;

===Download source files===

[http://xataface.com/documentation/tutorial/getting_started/facultyofwidgetry-6-tar.gz Download the source files] for this application as a tar.gz archive
These source files reflect the state of the application at the current point of the tutorial. As changes are made to the application in later sections, downloads of those versions are made available for download also.

===Summary===
In this section we learned how to change the labels, descriptions, and widgets for fields. We also learned how to add HTML attributes to the widgets to achieve very fine-grained control over the display of our forms.</content>
	<keywords>widget labels descriptions onclick handlers</keywords>
	<language>en</language>
	<original_page></original_page>
</wiki>
<wiki id="wiki?page_id=7">
	<page_name>Delegate_class_methods</page_name>
	<page_id>7</page_id>
	<page_title>Delegate_class_methods</page_title>
	<content>==Delegate Class Reference==

[[toc]]

A delegate class is a PHP class that complements a particular table with custom bahaviors.  Basic table metadata can be supplied using the [[fields.ini file]], however some things are better customized using PHP.

===Delegate Class Location===

The delegate class should be located in a file named TABLENAME.php (where TABLENAME is the name of the table with which the delegate class is associated) inside the table&apos;s [[table configuration directory|configuration directory]].  E.g. given a table named &quot;people&quot;, you would place the delegate class in the file &quot;tables/people/people.php&quot;

===Basic Delegate Class===

&lt;code&gt;
&lt;?php
class tables_people {}
?&gt;
&lt;/code&gt;

===Available Methods===

====Table Settings====

{| class=&quot;listing listing2&quot;
! Name
! Description
! Version
|-
| [[sql delegate method|__sql__]]
| Defines the SQL query that can be used to fetch records of this table.  This is identical to the [[fields.ini file]] [[__sql__]] directive, except that by defining it in the delegate class you have more flexibility.
| 1.0
|}

====Permissions====

{| class=&quot;listing listing2&quot;
! Name
! Description
! Version
|-
| [[getPermissions]]
| Returns the permissions available for a given record.
| 0.6
|-
| getRoles
| Returns the roles allowed for a given record.
| 1.0
|-
| [[__field__permissions]]
| Returns the default permissions for a field of a given record.
| 1.0
|-
| __field__roles
| Returns the default roles for a field of a given record.
| 1.0
|-
| [[fieldname__permissions]]
| Returns the permissions that are allowed for the field &quot;fieldname&quot; on a given record.
| 0.7
|-
| fieldname__roles
| Returns the roles that are allowed for the field &quot;fieldname&quot; on a given record.
| 1.0
|-
| rel_relationshipname__permissions
| Returns the permissions pertaining to the relationship &apos;&apos;relationshipname&apos;&apos; on a given record.
| 1.0
|-
| rel_relationshipname__roles
| Returns the role or roles pertaining to the relationship &apos;&apos;relationshipname&apos;&apos; on a given record.
| 1.0
|}

====Triggers====

{| class=&quot;listing listing2&quot;
! Name
! Description
! Version
|-
| [[after_action_edit]]
| Trigger called after the edit action is succesfully completed.
| 0.7
|-
| [[after_action_new]]
| Trigger called after the new action is successfully completed.
| 0.7
|-
| [[after_action_delete]]
| Trigger called after the delete action is successfully completed.
| 0.7
|-
| [[afterAddExistingRelatedRecord]]
| Trigger called after an existing related record is added.
| 0.5
|-
| [[aftereAddNewRelatedRecord]]
| Trigger called after a new related record is added.
| 0.5
|-
| [[afterCopy]]
| Trigger called after a record is copied.
| 1.3
|-
| [[afterDelete]]
| Trigger called after a record is deleted.
|0.5
|-
| [[afterAddRelatedRecord]]
| Trigger called after a related record of this table is added (either an existing record or a new record).
| 0.5
|-
| [[afterRemoveRelatedRecord]]
| Trigger called after a related record is removed from a relationship.
| 1.1.6
|-
| [[afterInsert]]
| Trigger called after a given record is inserted.
| 0.5
|-
| [[afterSave]]
| Trigger called after a given record is saved (insert or update).
| 0.5
|-
| [[afterUpdate]]
| Trigger called after a given record is updated.
| 0.5
|-
| [[beforeAddExistingRelatedRecord]]
| Trigger called before an existing related record is added.
| 0.5
|-
| [[beforeAddNewRelatedRecord]]
| Trigger called before a new related record is added.
| 0.5
|-
| [[beforeAddRelatedRecord]]
| Trigger called before a related record of this table is added (either an existing record or a new record).
| 0.5
|-
| [[beforeCopy]]
| Trigger called before a record is copied.
| 1.3
|-
| [[beforeDelete]]
| Trigger called before a record is deleted.
| 0.5
|-
| [[beforeRemoveRelatedRecord]]
| Trigger called before a related record is removed.
| 1.1.6
|-
| [[beforeSave]]
| Trigger called before a given record is saved (insert or update).
| 0.5
|-
| [[beforeInsert]]
| Trigger called before a given record is inserted.
| 0.5
|-
| [[beforeUpdate]]
| Trigger called before a given record is updated.
| 0.5
|-
| [[init]]
| This method is called the first time the table is loaded.  It allows you to specify initialization details.
| 0.8
|}


====Field Filters====

{| class=&quot;listing listing2&quot;
! Name
! Description
! Version
|-
| fieldname__htmlValue
| Returns the value of the field &quot;fieldname&quot; for a given record as HTML.
| 0.5
|-
| fieldname__display
| Returns the value of the field &quot;fieldname&quot; appropriate for displaying.
| 0.5
|-
| [[fieldname__default]]
| Returns the default value for the field &apos;&apos;fieldname&apos;&apos;.  New record forms will be prepopulated with this value.
| 0.7
|-
| [[fieldname__validate]]
| Validates the input for the field &apos;&apos;fieldname&apos;&apos;.
| 0.6
|-
| fieldname__parse
| Parses the input value for the field &apos;&apos;fieldname&apos;&apos;.  This is called by Xataface inside the setValue() method or each record to normalize input values before they are stored in the object (not the database).
| 0.5
|-
| fieldname__toString
| Converts the value of the field &apos;&apos;fieldname&apos;&apos; to a string.  This string representation is used as the basis for most higher level data retrieval methods (such as serialize and display).  This could be treated as an inverse to the [[fieldname__parse]] method.
| 0.5
|-
| fieldname__serialize
| Converts a value of the field &apos;&apos;fieldname&apos;&apos; to be saved in the database.  This should return a string representation of the value that is suitable for database storage.
| 0.5
|-
| fieldname__link
| A link that appears beside the field &apos;&apos;fieldname&apos;&apos; on the edit form.
| 0.6
|-
| [[field__pushValue]]
| Converts form input for field &apos;&apos;fieldname&apos;&apos; to be ready to store in a Dataface_Record.
| 0.6
|-
| [[field__pullValue]]
| Converts a value for field &apos;&apos;fieldname&apos;&apos; in a Dataface_Record object to be ready to be inserted as a value on an HTML form.
| 0.6
|-
| [[field__fieldname]]
| Effectively creates a calculated field named &quot;fieldname&quot; available on the given record.
| 0.6
|-
| [[no_access_text]]
| Replace the default NO ACCESS permission text with another text.
| 1.1.6
|-
| [[no_access_link]]
| Replace the default link of the NO ACCESS permission link with another link.
| 1.1.6
|}

====Template Customization====
{| class=&quot;listing listing2&quot;
! Name
! Description
! Version
|-
| [[block__blockname]]
| Outputs content that is meant to override a slot or a block named &quot;blockname&quot;.
| 0.6
|}

====List Tab Customization====

{| class=&quot;listing listing2&quot;
! Name
! Description
! Version
|-
| css__tableHeaderCellClass
| Returns a custom CSS class for a table header cell (th tag) in the list view.  Takes the name of a table column as a parameter.
| 2.0alpha2
|-
| css__tableRowClass
| Returns a custom CSS class for a table row (tr tag) in list view.  Takes a Dataface record as a parameter.
| 1.2
|-
| fieldname__renderCell
| Overrides the table cell content for the &quot;fieldname&quot; field in list view with custom HTML.
| 1.0
|-
| renderRow
| Overrides the the html used for a row in list view for the given record.
| 0.7
|-
| renderRowHeader
| Overrides the header for the table in list view.
| 0.7
|-
| renderRelatedRow
| Overrides the html used for a row in a related record list for a given related record.
| 1.0 beta 4
|-
| renderRelatedRowHeader
| Overrides the html used for the header in a related list.
| 1.0 beta 4
|}

====Record Metadata====
{| class=&quot;listing listing2&quot;
! Name
! Description
! Version
|-
| [[getBreadCrumbs]]
| Returns the bread crumbs (i.e. you are here) for a given record as an associative array of path parts.
| 0.6
|-
| [[getChildren]]
| Returns a list of Dataface_Record objects that are to be considered children of the given record.
| 0.8
|-
| [[getCreated]]
| Returns a unix timestamp marking the date that a record was created. 
| 0.9
|-
| getDescription
| Returns a string description summary of this record.  This is used for indexing, RSS feeds, and anywhere that a brief summary of a record is appropriate.
| 0.7
|-
| getPublicLink
| Returns the public URL of this record (in case it is different than the standard URL).
| 0.8
|-
| getTitle
| Returns the title for a given record.  The title is used in various parts of the application to represent the record.
| 0.5
|-
| [[getURL]]
| Overrides the getURL() method for a record.  Returns the URL that should be used to display the given record.
| 0.6
|-
| titleColumn
| Returns a string SQL select expression that is used to describe the title of records.
| 0.5
|}

====View Tab Customization====

{| class=&quot;listing listing2&quot;
! Name
! Description
! Version
|-
| [[How_to_Add_Custom_Sections_to_View_Tab|section__sectionname]]
| Defines a section to be displayed in the view tab for the given record.
| 0.7
|}


====Search Setup====
{| class=&quot;listing listing2&quot;
! Name
! Description
! Version
|-
| getSearchableText
| If [[_index|Indexing]] is turned on, then this returns the text that should be stored in the index for this record for searchability.
| 1.0
|}

====RSS Feed Customization====
{| class=&quot;listing listing2&quot;
! Name
! Description
! Version
|-
| [[getFeedItem]]
| For RSS Feeds, overrides the defaults and returns an associative array with feed elements for a particular record
| 1.0
|-
| [[getFeed]]
| For RSS feeds, overrides the default feed for a query, returning an array of feed items.
| 1.0
|-
| getFeedSource
| Overrides the default feed source parameter for an RSS feed.
| 1.0
|-
| [[getRelatedFeed]]
| For RSS feeds, overrides the default feed for a related feed.
| 1.0
|-
| getRSSDescription
| Overrides the default generated RSS description for a record.
| 1.0
|}

===XML Output Customization===
{| class=&quot;listing listing2&quot;
! Name
! Description
! Version
|-
| [[toXML]]
| Overrides the default XML produced for a record in the [[export xml]] action.  Returns an XML string.
| 1.2.7
|-
| [[getXMLHead]]
| Returns a string to be included at the beginning of XML output for a particular record. (just inside the opening tag).
| 1.2.7
|-
| [[xmlTail]]
| Returns a string to be included at the end of XML output for a particular record. (just inside the closing tag).
| 1.2.7
|}

====Valuelist Customization====
{| class=&quot;listing listing2&quot;
! Name
! Description
! Version
|-
| [[valuelist__valuelistname]]
| Defines a valuelist named &apos;&apos;valuelistname&apos;&apos;.
| 0.7
|}


====Importing Records====
{| class=&quot;listing listing2&quot;
! Name
! Description
! Version
|-
| [[__import__filtername]]
| Defines an import filter to named &apos;&apos;filtername&apos;&apos; which is used to import records into the table.
| 0.7
|}
</content>
	<keywords>RSS,Feeds,delegate classes, triggers</keywords>
	<language>en</language>
	<original_page>0</original_page>
</wiki>
<wiki id="wiki?page_id=80">
	<page_name>GettingStarted:delegate_classes</page_name>
	<page_id>80</page_id>
	<page_title>Delegate Classes</page_title>
	<content>==Delegate Classes==

Use Delegate classes to add permissions, custom serialization, display filters, calculated fields, import/export functionality, and other custom functionality to your application.

For many applications, the configuration files provide sufficient to make them fit the requirements. However, in some cases you may feel the need to &quot;extend&quot; or &quot;bend&quot; your application even more. For these situations, there are delegate classes.

===What is a delegate class?===

A delegate class is a PHP class that defines custom behavior, functions, and fields for a table in a Xataface application. A table may have only 1 delegate class.

What kinds of things can a delegate class do?

* Define permission rules for tables, records, and relationships.
* Define calculated fields.
* Define custom serialization/deserialization of fields (useful for XML storage)
* Define custom event handlers (actions to be performed when certain events take place)
* Define import / export filters.
* Define custom titles for records
* more ...

===How to create a delegate class===

I will describe the creation process with an example. 

Referring back to our FacultyOfWidgetry application, let&apos;s add a delegate class for the &apos;Program&apos; table. This is done as follows:

# Create a file named &apos;Program.php&apos; in the Program table configuration directory (i.e., &apos;tables/Program/Program.php). Your application directory structure should now look like:&lt;nowiki&gt;&lt;br/&gt;&lt;/nowiki&gt;[[Image:http://framework.weblite.ca/documentation/tutorial/getting_started/delegate-class-fs-1.gif]]
# Add the following contents to your newly created &apos;Program.php&apos; file:&lt;code&gt;&lt;?
class tables_Program {}
&lt;/code&gt;&lt;nowiki&gt;&lt;p&gt;
In other words, you are creating a class named &apos;tables_Program&apos;. The above delegate class doesn&apos;t do anything yet, but it is a start.
The fun part doesn&apos;t start until you start defining methods in your delegate class. There are prescribed interfaces that you will need to implement to make this work.&lt;/p&gt;&lt;/nowiki&gt;


===Example 1: Creating a custom title for records===
The &quot;Title&quot; of a record is a string that represents the record. It is used by Xataface in the navigation controller (forward and back buttons) and in the &quot;Jump&quot; menu as well as various places around the interface for referring to that record. As an example, take a look at this partial screen shot of the &apos;details&apos; tab in a Xataface application.

[[Image:http://framework.weblite.ca/documentation/tutorial/getting_started/getTitle-1.gif]]

I have circled the parts of the interface that use a record&apos;s title in some way. (1), (2), and (4) show the title of the current record and (3) shows the title of the next record in the found set. You will notice that the title is just the value of the first field in the Program record. In fact, the way that Xataface generates titles is by selecting the first VARCHAR or CHAR field in the table to be the Title for records of that table. In the above example this seems like a good choice, but it may not always be what you want.

We can use our delegate class to customize the way that these titles are generated. By defining a method named getTitle(), we can customize the way that titles are generated. Let&apos;s add such a method to our delegate class as follows:
&lt;code&gt;
&lt;?
class tables_Program {

	function getTitle(&amp;$record){
		return $record-&gt;val(&apos;ProgramName&apos;).&apos; Program&apos;;
	}
}
&lt;/code&gt;

OK, you are probably wondering what this $record object is. The $record object is a Dataface_Record object that represents a record of the &apos;Program&apos; table (if you want to take a look at the source code for this class it can be found in the &apos;Dataface/Record.php&apos; file). This object allows you to access all of the information about the record so that you can generate a title for the record. 

The &apos;val&apos; method simply returns the value of a field in the record.
In the above example, we are telling Xataface that the title of all records of the &apos;Program&apos; table is the value of the ProgramName field with the string &apos;Program&apos; appended to it. For example, if the ProgramName of a record was &apos;Foo&apos;, then its title woud be &apos;Foo Program&apos;.

Lets take a look at our application now to see the changes that we have made.

[[Image:http://framework.weblite.ca/documentation/tutorial/getting_started/getTitle-2.gif]]

Notice that the (1) now has &apos;Program&apos; appended to the end of the title, but (2) and (3) do not. This is because (2) and (3) are part of the result controller (for navigating through results in the table) and it needs to be able to load hundreds of record titles at a time, but the getTitle() method requires that the entire record be loaded into memory for it to work which would be unfeasible when we need the title of hundreds of records. The result controller titles can also be customized, however, using the titleColumn() method, which simply returns the name of the column that should be used as the title. It can also return MySQL clauses that are equivalent to a column name (e.g., CONCAT(&apos;FirstName&apos;, &apos; &apos;, &apos;LastName&apos;) would be valid).

Okay, let&apos;s add a titleColumn() method to our delegate class so that we can customize the way our records are represented in the result controller:

&lt;code&gt;
&lt;?
class tables_Program {

	function getTitle(&amp;$record){
		return $record-&gt;val(&apos;ProgramName&apos;).&apos; Program&apos;;
	}
	
	function titleColumn(){
		return &apos;AdmissionDeadline&apos;;
	}
}
&lt;/code&gt;


All that the titleColumn method does is return the name of a column to be used as the title for records of the &apos;Program&apos; table. In this case, we making the &apos;AdmissionDeadline&apos; field the title column which results in the result controller looking like this:

[[Image:http://framework.weblite.ca/documentation/tutorial/getting_started/titleColumn-1.gif]]


This was a simple example, but it is possible to do more with the titleColumn() method than just specify the name of a column. Any valid MySQL calculation that can be placed in a SELECT list can be returned here. For example, we can make use of the MySQL &apos;CONCAT&apos; function to append the string &apos;Program&apos; to the &apos;ProgramName&apos; field and achieve the same results as our previous getTitle() method:

&lt;code&gt;
&lt;?
class tables_Program {

	function getTitle(&amp;$record){
		return $record-&gt;val(&apos;ProgramName&apos;).&apos; Program&apos;;
	}
	
	function titleColumn(){
		return &quot;CONCAT(ProgramName, &apos; Program&apos;)&quot;;
	}
}

&lt;/code&gt;

And now we can see the changes in our application:

[[Image:http://framework.weblite.ca/documentation/tutorial/getting_started/titleColumn-2.gif]]

It may seem a little bit inconvenient to have to define 2 methods to effectively customize the title of a record. Future versions may attempt to address this issue so that one or the other can be implemented, but for now, both methods must be implemented to effectively customize the title. In addition, future versions will likely add the &apos;titleColumn&apos; functionality to an INI file since it is more or less static.

===Summary===

In this section we learned how to add a delegate class to our tables to customize the behavior of our applications. Delegate class become more important when you need very fine-grained customizations to your application, as you will see in later sections. One important feature of delegate classes is the ability to add security permissions to tables and records to limit who can view, edit, and delete certain records. This will be covered in the next section.

</content>
	<keywords>delegate classes,getTitle,getPermissions</keywords>
	<language>en</language>
	<original_page></original_page>
</wiki>
<wiki id="wiki?page_id=1">
	<page_name>index_page</page_name>
	<page_id>1</page_id>
	<page_title>index_page</page_title>
	<content>==Documentation==

[[toc]]

===Introductory===

* [[about|About Xataface]]
* [http://xataface.com/documentation/tutorial/getting_started Getting Started Tutorial]
* [[How to build a PHP MySQL Application with 4 lines of code]]
* [[Troubleshooting]]

===Reference===

* [http://dataface.weblite.ca API Docs]
* [[conf.ini file]] directives
* [[fields.ini file]] directives
* [[valuelists.ini file]] directives
* [[relationships.ini file]] directives
* [[Delegate class methods]]
* [[Application Delegate Class]]
* [[permissions.ini file]] directives
* [[actions.ini file]] directives
* [[preferences|User Preferences]] - options for customizing the application further via the getPreferences() method.
* [[xataface templates|templates]]
* &apos;&apos;&apos;[[URL Conventions]]&apos;&apos;&apos; - Learn how to use Xataface&apos;s URL conventions to form URLs that return exactly the result set that you want.
* &apos;&apos;&apos;[[Roadmap]]&apos;&apos;&apos; - What is planned for the next releases of Xataface

===Cook Book===

* [[Customizing Theme Based on IP Address]] - An article on storing IP addresses in the database and showing users a different theme depending on which range of IP addresses they are connecting from.

===By Topic===

====Installation====

* &apos;&apos;&apos;[http://xataface.com/documentation/tutorial/getting_started/installation Xataface Installation Instructions]&apos;&apos;&apos; - This document explains how to install Xataface on your system.  It does not describe how to create an application with Xataface.
* &apos;&apos;&apos;[http://xataface.com/documentation/tutorial/getting_started/first_application Creating your first App]&apos;&apos;&apos; - How to create an application using Xataface (from the Getting Started Tutorial)
* &apos;&apos;&apos;[[about|About Xataface]]&apos;&apos;&apos; - Quick overview of Xataface.  Includes a 6 step example of creating an application with Xataface.

====Configuration====

* &apos;&apos;&apos;[http://xataface.com/documentation/tutorial/getting_started/customizing Customizing field labels, descriptions, and widgets]&apos;&apos;&apos; - This document explains how to customize some basic aspects of your application&apos;s edit forms. (From the Getting Started tutorial).
* &apos;&apos;&apos;[http://xataface.com/documentation/tutorial/getting_started/valuelists Using Valuelists]&apos;&apos;&apos; - How to use valuelists to set up options for your select lists and checkbox groups.
* &apos;&apos;&apos;[http://xataface.com/documentation/how-to/list_tab Configuring and customizing the list tab]&apos;&apos;&apos; -     This document explains how to customize the display of the list tab using INI files, templates, and delegate classes.


====Internationalization====

* &apos;&apos;&apos;[[Contribute to Xataface Translation Project]]&apos;&apos;&apos; - We need translators to help us keep the Xataface translations up to date.  This page shows how you can help.
* &apos;&apos;&apos;[http://xataface.com/documentation/tutorial/internationalization-with-dataface-0.6 Internationalization with Xataface]&apos;&apos;&apos; (tutorial)
* &apos;&apos;&apos;[http://xataface.com/documentation/how-to/how-to-internationalize-your-application How to internationalize your application]&apos;&apos;&apos; (how to) - Xataface 0.6 contains a LanguageTool class that allows your applications to be presented in multiple languages
* &apos;&apos;&apos;[http://xataface.com/documentation/how-to/use-translations How to use other translations]&apos;&apos;&apos; - Xataface 0.7 includes German and French translations. This document explains how to allow your application to use these and other translations, rather than the default English translation.
* &apos;&apos;&apos;[http://xataface.com/documentation/how-to/unicode How to enable unicode support]&apos;&apos;&apos; -     As of Xataface 0.6, unicode is fully supported so that your dataface application will work with any and multiple languages simultaneously.
* &apos;&apos;&apos;[http://weblite.ca/svn/dataface/core/trunk/lang Download latest language files out of SVN]&apos;&apos;&apos; - If you want to make sure that you have the latest translations, you can download them from SVN and place them into your xataface lang directory.


====User Interface Customization====

* &apos;&apos;&apos;[[preferences|User Preferences]]&apos;&apos;&apos; - You can hide, show, enable, and disable features of the application selectively.
* &apos;&apos;&apos;[http://xataface.com/documentation/tutorial/getting_started/changing-look-and-feel Changing the Look and Feel]&apos;&apos;&apos; - Change the way your application looks by adding custom headers, footers, and sections, and by overriding the default templates with your own custom templates.  (From the Getting Started tutorial).
* [[xataface templates|templates]]
* &apos;&apos;&apos;[http://xataface.com/documentation/tutorial/customizing-the-dataface-look-and-feel Customizing the Xataface look and feel]&apos;&apos;&apos; tutorial
* &apos;&apos;&apos;[[Customizing the look and feel of a row or a cell| Customizing the look and feel of an element in the list view]]&apos;&apos;&apos; - Personnalize the aspect of each part of your list according to its content.
* &apos;&apos;&apos;[http://xataface.com/documentation/how-to/custom_javascripts How to include custom javascripts and stylesheets]&apos;&apos;&apos; - Use the custom_javascripts and custom_stylesheets blocks to include your own custom javascript and CSS files in your application.
* &apos;&apos;&apos;[http://xataface.com/documentation/how-to/hide_search How to hide the search box]&apos;&apos;&apos; -     The full-text search box that appears in the upper right can easily be removed.
* &apos;&apos;&apos;[http://xataface.com/documentation/how-to/list_tab Configuring and customizing the list tab]&apos;&apos;&apos; -     This document explains how to customize the display of the list tab using INI files, templates, and delegate classes.
* &apos;&apos;&apos;[[How to Add Custom Sections to View Tab]]&apos;&apos;&apos; - The &apos;&apos;View&apos;&apos; tab in a Xataface application can be configured in many ways.  This tutorial shows you how to add your own custom sections to the view tab.
* &apos;&apos;&apos;[[Creating a Dashboard]]&apos;&apos;&apos; - Create a dashboard action for your users to so that they have a logical starting point in your application.
* &apos;&apos;&apos;[[Grafted fields]]&apos;&apos;&apos; - Add a grafted field to your table for user convenience. You can use it also to be able to sort columns with relative tables content.
* &apos;&apos;&apos;[[Clean the html for the export]]&apos;&apos;&apos; - Clean the HTML tags and entities for the export in CSV or XML.

====Using the API====

* &apos;&apos;&apos;[[Introduction to the Xataface API]]&apos;&apos;&apos; - A short introduction to the classes, methods, and functions available in the Xataface API.
* &apos;&apos;&apos;[http://xataface.com/documentation/how-to/how-to-define-custom-serialization-for-fields How to define custom serialization for fields]&apos;&apos;&apos;

====Security====

* &apos;&apos;&apos;[[authentication]]&apos;&apos;&apos; - Overview of Xataface Authentication
* &apos;&apos;&apos;[[registration form]]&apos;&apos;&apos; - Enabling User Registration in Xataface
* &apos;&apos;&apos;[[permissions.ini file]]&apos;&apos;&apos; - Reference of the permissions.ini file directives.
* &apos;&apos;&apos;[http://xataface.com/documentation/tutorial/getting_started/permissions Permissions]&apos;&apos;&apos; - Use sessions and delegate classes to define permissions at the record and field level. (From the Getting Started tutorial).
* &apos;&apos;&apos;[[Cached permissions]]&apos;&apos;&apos; - Use cached perms for complex queries inside getPermissions()
* &apos;&apos;&apos;[[Delegate_class_methods#toc5|Delegate class methods]]&apos;&apos;&apos; - Permissions-related functions
* &apos;&apos;&apos;[[Relationship Permissions]]&apos;&apos;&apos; - Guide to permissions on related records.
* &apos;&apos;&apos;[http://xataface.com/documentation/how-to/disallow_tables How to disallow access to tables]&apos;&apos;&apos;
* &apos;&apos;&apos;[[site_with_backoffice]]&apos;&apos;&apos; - A site with a backoffice without obligation to log in
* &apos;&apos;&apos;[http://xataface.com/documentation/how-to/security_filters Security Filters]&apos;&apos;&apos; - Use security filters to block users from seeing certain records.
* &apos;&apos;&apos;[[How to granulate permissions on each field]]&apos;&apos;&apos; - Decide for each field who can edit, read...
** &apos;&apos;&apos;[[no_access_text]]&apos;&apos;&apos; - Replace the default NO ACCESS permission text with another text.
* &apos;&apos;&apos;[[LDAP or Active Directory]]&apos;&apos;&apos; - How to authenticate users with LDAP or Active Directory...

====Performance====

* &apos;&apos;&apos;[http://xataface.blogspot.com/2009/06/using-query-caching-in-xataface.html Using Query Caching]&apos;&apos;&apos; - Query caching can drastically improve performance of busy applications with large databases.  This article explains how to enable this caching in your Xataface application.
* &apos;&apos;&apos;[[_output_cache]]&apos;&apos;&apos; - Xataface does quite a bit of heavy lifting on each page request. If your application is getting a lot of traffic that is slowing your server down, you may want to look at enabling the Xataface output cache.

====Modules====

* [[modules]] - Available Xataface Modules.  This includes such things as CAPTCHA validation, editable javascript grids, and more.
* [[Module Developers Guide]] - A guide / Tutorial on how to develop your own Xataface modules.

====Preferences====

====Relationships====

* &apos;&apos;&apos;[http://xataface.com/documentation/tutorial/getting_started/relationships Relationships]&apos;&apos;&apos; - Xataface allows you to define relationships between tables using the relationships.ini file. (From the Getting Started Tutorial)
* &apos;&apos;&apos;[http://xataface.com/documentation/how-to/how-to-assign-order-to-related-records How to assign order to related records]&apos;&apos;&apos; -     Sometimes it is desirable for the records in a relationship to take on a particular default order. Dataface 0.6 makes this easy if you follow a few conventions.
* &apos;&apos;&apos;[[Drag and Drop Reordering of Relationships]]&apos;&apos;&apos; - A more in-depth tutorial about adding ordering to relationships.
* &apos;&apos;&apos;[[relationships.ini file]] reference
* &apos;&apos;&apos;[[Relationship Permissions]]


====Forms====

* &apos;&apos;&apos;[http://xataface.com/documentation/how-to/DisableEnterKeyInFields How to disable the enter key in forms]&apos;&apos;&apos;
* &apos;&apos;&apos;[http://xataface.com/documentation/tutorial/getting_started/customizing Customizing field labels, descriptions, and widgets]&apos;&apos;&apos; - This document explains how to customize some basic aspects of your application&apos;s edit forms. (From the Getting Started tutorial).
* &apos;&apos;&apos;[http://xataface.com/documentation/tutorial/getting_started/valuelists Using Valuelists]&apos;&apos;&apos; - How to use valuelists to set up options for your select lists and checkbox groups. (From the Getting Started tutorial)
* &apos;&apos;&apos;[http://xataface.com/documentation/tutorial/getting_started/validation Form Validation]&apos;&apos;&apos; - Xataface allows you to add validation rules to fields using the fields.ini file.  (From the Getting Started tutorial).
* &apos;&apos;&apos;[http://xataface.com/documentation/how-to/how-to-handle-file-uploads How to handle file uploads]&apos;&apos;&apos; -     Xataface allows you to store file uploads in BLOB fields or on the file system.
* &apos;&apos;&apos;[http://xataface.com/documentation/how-to/custom_validation How to add custom validation with delegate classes]&apos;&apos;&apos; - If the standard validators (e.g., required, email, regex, etc..) don&apos;t quite cut it for your validation rules, Xataface allows you to define custom validation methods in the delegate class.
* &apos;&apos;&apos;[http://xataface.com/documentation/how-to/regex_validation Validating with regular expressions]&apos;&apos;&apos; - How to validate input into a field using regular expressions.
* &apos;&apos;&apos;[[Dynamic select boxes]]&apos;&apos;&apos; -     How to create two dynamic javascript select boxes from the valuelists.

====Importing====

* &apos;&apos;&apos;[http://xataface.com/documentation/how-to/import_filters Import Filters]&apos;&apos;&apos; - It is common to need to import records en masse into a database. This is what import filters are for. (Since 0.7).

====Actions====

* &apos;&apos;&apos;[http://xataface.com/documentation/tutorial/getting_started/dataface_actions Actions I: The Basics]&apos;&apos;&apos; - Web Lite&apos;s actions framework allows you to customize existing actions (e.g. new, edit, find) and create your own new actions. (From the Getting Started Tutorial).
* &apos;&apos;&apos;[http://xataface.com/documentation/how-to/after_action_triggers Adding triggers to actions]&apos;&apos;&apos; -     Xataface 0.6.1 adds some triggers to actions so that the developer can define custom functionality to be performed after an action has successfullly taken place.
* &apos;&apos;&apos;[[Calendar Action]]&apos;&apos;&apos; - Using the built-in calendar action to add a full-fledged event calendar to your application.
* &apos;&apos;&apos;[[Creating a Dashboard]]&apos;&apos;&apos; - Create a dashboard action for your users to so that they have a logical starting point in your application.
* &apos;&apos;&apos;[[Selected Records Actions]]&apos;&apos;&apos; - Create custom actions that are performed on records that have been selected in the list tab.
* &apos;&apos;&apos;[[Creating Printable Reports]]&apos;&apos;&apos; - Create a custom printable report using a custom action.
* &apos;&apos;&apos;[[Using RecordGrid]]&apos;&apos;&apos; - Using Dataface_RecordGrid to print data in tabular form.

====History====

* &apos;&apos;&apos;[http://xataface.com/documentation/how-to/history-howto How to activate history logging]&apos;&apos;&apos; -     Xataface 0.6.9 comes with support for managing the history of your records. This how-to shows you how to enable and use this feature.

====RSS Feeds====

* &apos;&apos;&apos;[[Introduction to RSS Feeds in Xataface]]&apos;&apos;&apos; - Xataface provides RSS feeds to any found set in your application.  This tutorial shows how it works and how you can configure these feeds to get your desired results.

====Event Calendar====

* &apos;&apos;&apos;[[Calendar Action]]&apos;&apos;&apos; - Introduction to the Xataface calendar action which can be used to convert your application into a full-fledged event calendar.
</content>
	<keywords></keywords>
	<language>en</language>
	<original_page>0</original_page>
</wiki>
<wiki id="wiki?page_id=39">
	<page_name>Drag_and_Drop_Reordering_of_Relationships</page_name>
	<page_id>39</page_id>
	<page_title>Drag_and_Drop_Reordering_of_Relationships</page_title>
	<content>==Drag and Drop Reordering of Related Records in Xataface==

One powerful aspect of Xataface is its abstraction of relationships between tables.  Once you define a relationship users can browse related records, add new and existing related records, and delete related records to or from the relationship.  For example, suppose you have a &apos;&apos;people&apos;&apos; table and a &apos;&apos;publications&apos;&apos;, you could define a relationship from &apos;&apos;people&apos;&apos; to &apos;&apos;publications&apos;&apos; to identify publications that belong to a particular person.  The table&apos;s might look something like:

===people table===

{| class=&quot;listing listing2&quot;
! person_id
! person_name
|-
| 1
| John Smith
|-
| 2
| Ben Stein
|-
| 3
| Harley Davidson
|-
| 4
| Trevor Linden
|}


===publications table===

{| class=&quot;listing listing2&quot;
! publication_id
! owner_id
! pub_title
|-
| 1
| 2
| Introduction to widgetry
|-
| 2
| 2
| Intermediate Widgetry
|-
| 3
| 2
| Advanced Widgetry
|-
| 4
| 3
| How to play the violin
|}


See http://xataface.com/documentation/tutorial/getting_started/relationships for an introduction to relationships in Xataface, and how to define them.

Our relationship definition in the  &apos;&apos;people&apos;&apos; table&apos;s [[relationships.ini file]] might look something like:

&lt;code&gt;
[my_pubications]
    publications.owner_id=&quot;$person_id&quot;
&lt;/code&gt;

This indicates that any publication whose &apos;&apos;owner_id&apos;&apos; column matches the current &apos;&apos;people&apos;&apos; record&apos;s &apos;&apos;person_id&apos;&apos; field is considered part of the relationship.  Using our example data above, this would mean that Ben Stein&apos;s &apos;&apos;my_publications&apos;&apos; relationship would contain 3 records: &quot;Introduction to Widgetry&quot;, &quot;Intermediate Widgetry&quot;, and &quot;Advanced Widgetry&quot;.  In our Xataface application this means that in the &quot;Details&quot; tab for the &quot;Ben Stein&quot; record, we would see a sub-tab &apos;&apos;My Publications&apos;&apos; which would contain a list of Ben Stein&apos;s publications.

===Adding Publication Order===

Now that we have our relationship, what if Ben Stein wants his publications to appear in a particular order whenever they are displayed to the user.  Xataface allows us to specify an &quot;order&quot; column for our relationship, which will cause the related records to be orderable by drag and drop (if the user has appropriate permissions).

# Add a field to the &apos;&apos;publications&apos;&apos; table named &quot;pub_order&quot;
# Change the relationship definition in the people table&apos;s [[relationships.ini file]] to tell Xataface to use the pub_order field for sorting:&lt;code&gt;
[my_pubications]
    publications.owner_id=&quot;$person_id&quot;
    metafields:order=&quot;pub_order&quot;
&lt;/code&gt;

Now load up your application and navigate to the &quot;My Publications&quot; tab for the &quot;Ben Stein&quot; record. Now you&apos;re able to drag and drop rows in your application to reorder them.

===Permission to Reorder Records===

Only users who have been assigned the &apos;&apos;reorder_related_records&apos;&apos; permission for a record&apos;s relationship are allowed to reorder records of that relationship.  By default the &apos;&apos;EDIT&apos;&apos; role contains this permission, as does any role that permits the user to edit the parent record of the relationship.  The &apos;&apos;READ ONLY&apos;&apos; role does not contain this permission.  If you want to explicitly deny this permission for all relationships in a record, you can simply set this permission to 0 in the associated role within your application&apos;s [[permissions.ini file]]:

&lt;code&gt;
[MY ROLE]
     reorder_related_records=0
&lt;/code&gt;

For more information about permssions see:

* [[permissions.ini file|The Permissions.ini file reference]]
* [http://xataface.com/documentation/tutorial/getting_started/permissions Introduction to Permissions]

===Loading Related Records using the Xataface API===

The ordering that is set via this drag and drop method is also honoured by the Xataface API when fetching related records.  You can load related records using the [http://dataface.weblite.ca/getRelatedRecordObjects getRelatedRecordObjects] method of the [http://dataface.weblite.ca/Dataface_Record Dataface_Record] class. E.g.

&lt;code&gt;
$benStein = df_get_record(&apos;people&apos;, array(&apos;person_id&apos;=&gt;2));
$pubs = $benStein-&gt;getRelatedRecordObjects(&apos;my_publications&apos;);
foreach ($pubs as $pub){
    echo $pub-&gt;val(&apos;pub_title&apos;).&apos;&lt;br/&gt;&apos;;
}
&lt;/code&gt;
This will list up to the first 30 publications of Ben stein in the order prescribed by our drag and drop ordering scheme.
</content>
	<keywords></keywords>
	<language>en</language>
	<original_page>0</original_page>
</wiki></record>