svn: /pear/peardoc/trunk/en/package/html/ html-quickform2/controller-actions.xml html-quickform2.xml

[email protected] (Alexey Borzov) Sat, 22 Oct 2011 21:58:41 +0000
Newsgroups php.pear.doc
Message-ID <[email protected]>
avb                                      Sat, 22 Oct 2011 21:58:41 +0000

Revision: http://svn.php.net/viewvc?view=revision&revision=318327

Log:
Overview of Controller actions, boast about unit tests

Changed paths:
    A   pear/peardoc/trunk/en/package/html/html-quickform2/controller-actions.xml
    U   pear/peardoc/trunk/en/package/html/html-quickform2.xml
svn-diffs-318327.txt (text/x-diff, 13.5 KB)
Added: pear/peardoc/trunk/en/package/html/html-quickform2/controller-actions.xml
===================================================================
--- pear/peardoc/trunk/en/package/html/html-quickform2/controller-actions.xml	                        (rev 0)
+++ pear/peardoc/trunk/en/package/html/html-quickform2/controller-actions.xml	2011-10-22 21:58:41 UTC (rev 318327)
@@ -0,0 +1,271 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<refentry
+ xmlns="http://docbook.org/ns/docbook"
+ xmlns:phd="http://www.php.net/ns/phd"
+ version="lillet"
+ xml:id="package.html.html-quickform2.controller-actions"
+>
+ <refnamediv>
+  <refname>Controller action handlers</refname>
+  <refpurpose>Using available handlers and writing custom ones</refpurpose>
+ </refnamediv>
+ <refsection xml:id="package.html.html-quickform2.controller-actions.overview">
+  <info>
+   <title>Overview</title>
+  </info>
+  <para>
+   Action handlers in <classname>HTML_QuickForm2_Controller</classname> define what should happen
+   when request to a script containing the form is made. To make Controller execute a specific
+   action handler after form submit you <phd:pearapi phd:package="HTML_QuickForm2"
+    phd:linkend="HTML_QuickForm2_Controller_Page::getButtonName">give a special name</phd:pearapi>
+   to a form's submit button:
+   <programlisting role="php">
+<![CDATA[
+$form->addElement('submit', $this->getButtonName('foo'),
+                  array('value' => 'This button does foo!'));
+]]>
+   </programlisting>
+  </para>
+  <para>
+   Action handlers are called via <phd:pearapi phd:package="HTML_QuickForm2"
+    phd:linkend="HTML_QuickForm2_Controller_Page::handle"/>
+   <programlisting role="php">
+<![CDATA[
+$page->handle('foo');
+]]>
+   </programlisting>
+   which is usually done by <phd:pearapi phd:package="HTML_QuickForm2"
+    phd:linkend="HTML_QuickForm2_Controller::run"/> after finding page id and action name from
+   request, but can also be done manually. In fact, built-in handlers liberally call other action
+   handlers, the execution ending with either <literal>'display'</literal>,
+   <literal>'jump'</literal> or <literal>'process'</literal>.
+  </para>
+  <para>
+   Action handlers can be added either to the form Page or to the Controller:
+   <programlisting role="php">
+<![CDATA[
+$page->addHandler('foo', new SpecificActionFoo());
+$controller->addHandler('foo', new GenericActionFoo());
+]]>
+   </programlisting>
+   When Page's <phd:pearapi phd:package="HTML_QuickForm2"
+    phd:linkend="HTML_QuickForm2_Controller_Page::handle">handle()</phd:pearapi> method is called it
+   first checks for a handler added via <phd:pearapi phd:package="HTML_QuickForm2"
+    phd:linkend="HTML_QuickForm2_Controller_Page::addHandler"/> and calls its <phd:pearapi
+    phd:package="HTML_QuickForm2"
+    phd:linkend="HTML_QuickForm2_Controller_Action::perform">perform()</phd:pearapi> method if
+   present. If a handler is missing it calls Controller's <phd:pearapi phd:package="HTML_QuickForm2"
+    phd:linkend="HTML_QuickForm2_Controller_Controller::handle">handle()</phd:pearapi> which checks
+   for a handler added via <phd:pearapi phd:package="HTML_QuickForm2"
+    phd:linkend="HTML_QuickForm2_Controller_Controller::addHandler"/> and calls its
+   <function>perform</function> method. If a handler is missing here but its name is known and a
+   default handler is available (see below), it is loaded and added automatically, otherwise an
+   Exception is thrown.
+  </para>
+ </refsection>
+
+ <refsection xml:id="package.html.html-quickform2.controller-actions.builtin">
+  <info>
+   <title>Built-in action names and action handlers</title>
+  </info>
+  <table>
+   <title>Handlers that can be bound to submit buttons</title>
+   <tgroup cols="3">
+    <thead>
+     <row>
+      <entry>Built-in name</entry>
+      <entry>Default handler</entry>
+      <entry>Description</entry>
+     </row>
+    </thead>
+    <tbody>
+     <row valign="top">
+      <entry><literal>'back'</literal></entry>
+      <entry><phd:pearapi phd:package="HTML_QuickForm2"
+       phd:linkend="HTML_QuickForm2_Controller_Action_Back" /></entry>
+      <entry>This handler should be bound to the <literal>&quot;Back&quot;</literal> button of
+       (usually) a wizard-type multipage form, it redirects to the previous page whether current
+       page is valid or not.</entry>
+     </row>
+     <row valign="top">
+      <entry><emphasis>None</emphasis>, actual name should be equal to <varname>id</varname> of some
+       form page.</entry>
+      <entry><phd:pearapi phd:package="HTML_QuickForm2"
+       phd:linkend="HTML_QuickForm2_Controller_Action_Direct" /></entry>
+      <entry>Used to go to a specific page of the form, most useful for non-wizard forms,
+       obviously.</entry>
+     </row>
+     <row valign="top">
+      <entry><literal>'next'</literal></entry>
+      <entry><phd:pearapi phd:package="HTML_QuickForm2"
+       phd:linkend="HTML_QuickForm2_Controller_Action_Next" /></entry>
+      <entry>This handler should be bound to the <literal>&quot;Back&quot;</literal> button of
+       (usually) a wizard-type multipage form, it redirects to the next page if the current
+       one is valid (or the form is not wizard). On the last page of a multipage form it behaves
+       like <literal>'submit'</literal>.</entry>
+     </row>
+     <row valign="top">
+      <entry><literal>'submit'</literal></entry>
+      <entry><phd:pearapi phd:package="HTML_QuickForm2"
+       phd:linkend="HTML_QuickForm2_Controller_Action_Submit" /></entry>
+      <entry>This handler should be bound to a &quot;global&quot; submit button for a form. It can be
+       the &quot;submit&quot; button of a single-page or tabbed multi-page form, &quot;finish&quot;
+       button of a wizard. Default handler checks whether all the pages of the form are valid, then
+       either calls the <literal>&apos;process&apos;</literal> handler or displays the invalid
+       page.</entry>
+     </row>
+    </tbody>
+   </tgroup>
+  </table>
+
+  <table>
+   <title>Other handlers, only called explicitly</title>
+   <tgroup cols="3">
+    <thead>
+     <row>
+      <entry>Built-in name</entry>
+      <entry>Default handler</entry>
+      <entry>Description</entry>
+     </row>
+    </thead>
+    <tbody>
+     <row valign="top">
+      <entry><literal>'display'</literal></entry>
+      <entry><phd:pearapi phd:package="HTML_QuickForm2"
+       phd:linkend="HTML_QuickForm2_Controller_Action_Display" /></entry>
+      <entry>Displays the form using <phd:pearapi phd:package="HTML_QuickForm2"
+        phd:linkend="HTML_QuickForm2_Renderer_Default">Default renderer</phd:pearapi>. You should
+       subclass this handler and override its <phd:pearapi phd:package="HTML_QuickForm2"
+        phd:linkend="HTML_QuickForm2_Controller_Action_Display::renderForm">renderForm()</phd:pearapi>
+       method if you want to customize the form output.</entry>
+     </row>
+     <row valign="top">
+      <entry><literal>'jump'</literal></entry>
+      <entry><phd:pearapi phd:package="HTML_QuickForm2"
+       phd:linkend="HTML_QuickForm2_Controller_Action_Jump" /></entry>
+      <entry>Performs a HTTP redirect to a given page.</entry>
+     </row>
+     <row valign="top">
+      <entry><literal>'process'</literal></entry>
+      <entry><emphasis>None</emphasis>, application-specific</entry>
+      <entry>This is the action called by default <literal>&apos;submit&apos;</literal> and
+       <literal>&apos;next&apos;</literal> (on the last page of the wizard only) handlers after
+       successful (i.e. without validation errors) form submit. This action doesn&apos;t have a
+       default handler, you should define the custom one yourself and implement all the necessary
+       logic to process the form&apos;s values in it.</entry>
+     </row>
+    </tbody>
+   </tgroup>
+  </table>
+ </refsection>
+
+ <refsection xml:id="package.html.html-quickform2.controller-actions.custom">
+  <info>
+   <title>Writing a custom handler</title>
+  </info>
+  <para>
+   Basically you need to create a class implementing <phd:pearapi phd:package="HTML_QuickForm2"
+    phd:linkend="HTML_QuickForm2_Controller_Action" /> and add necessary logic to its <phd:pearapi
+    phd:package="HTML_QuickForm2"
+    phd:linkend="HTML_QuickForm2_Controller_Action::perform">perform()</phd:pearapi> method.
+  </para>
+  <para>
+   If you intend to bind this action to some submit button via <function>getButtonName</function>,
+   you should make sure that you store the submitted values in the session container. This is
+   most easily done via <phd:pearapi phd:package="HTML_QuickForm2"
+    phd:linkend="HTML_QuickForm2_Controller_Page::storeValues"/>.
+  </para>
+  <para>
+   As usual, see the built-in handlers&apos; source for the inspiration.
+  </para>
+ </refsection>
+
+ <refsection xml:id="package.html.html-quickform2.controller-actions.bind">
+  <info>
+   <title>Can actions be bound to something other than submit buttons?</title>
+  </info>
+  <para>
+   Controller is able to properly handle actions bound to <literal>&lt;input type=&quot;image&quot;
+   /&gt;</literal> controls, too. You don't have to do anything special, just set the
+   control&apos;s name via <function>getButtonName</function>.
+  </para>
+  <para>
+   If you want to bind an action to something like a hyperlink, you must consider the following:
+   <emphasis>the form must be submitted</emphasis> to be able to get its values, thus you need to
+   write some javascript that will submit the form and pass the action name to the controller
+   (possibly by setting a name of some hidden element to that name).
+  </para>
+ </refsection>
+
+ <refsection xml:id="package.html.html-quickform2.controller-actions.urls">
+  <info>
+   <title>URLs</title>
+  </info>
+  <para>
+   If an instance of <classname>HTML_QuickForm2</classname> is not provided with an explicit
+   <literal>'action'</literal> attribute it tries to guess it from environment using
+   <varname>$_SERVER['PHP_SELF']</varname>. This may not be a best guess when all requests are
+   routed through <filename>index.php</filename>.
+  </para>
+  <para>
+   Controller has even more problems since its <literal>'jump'</literal> handler has to build an
+   absolute URL for a redirect (per <link xmlns:xlink="http://www.w3.org/1999/xlink"
+    xlink:href="&url.rfc;2616">RFC 2616</link>). It uses various values from
+   <varname>$_SERVER</varname> array for this, but your server may be configured in such a way (e.g.
+   if you use reverse proxy) that an URL a user sees is quite different from the one a script can
+   guess.
+  </para>
+  <para>
+   Thus the only bulletproof solution sometimes will be to explicitly set the
+   <literal>'action'</literal> attribute of all <classname>HTML_QuickForm2</classname> instances in
+   Controller:
+   <programlisting role="php">
+<![CDATA[
+foreach ($controller as $page) {
+    $page->getForm()->setAttribute('action', 'http://example.com/pretty/url/of/my/form');
+}
+]]>
+   </programlisting>
+   Default handler for <literal>'jump'</literal> will use this absolute URL for redirects.
+  </para>
+ </refsection>
+
+ <refsection xml:id="package.html.html-quickform2.controller-actions.pretty-urls">
+  <info>
+   <title>Pretty URLs</title>
+  </info>
+  <para>
+   A common question is whether it is possible to get rid of &quot;ugly&quot; <literal>GET</literal>
+   parameters that appear when redirecting from one form page to the other:
+   <screen>
+<![CDATA[
+http://example.com/wizard.php?_qf_page2_display=true
+]]>
+   </screen>
+  </para>
+  <para>
+   The simplest solution will be to get rid of <literal>'jump'</literal> altogether and use
+   <literal>'display'</literal> in its place. However, this will completely break navigation with
+   browser's &quot;Back&quot; and &quot;Forward&quot; buttons, so don't do that.
+  </para>
+  <para>
+   It is possible to use an URL like
+   <screen>
+<![CDATA[
+http://example.com/wizard/page2
+]]>
+   </screen>
+   instead of the above one, but it'll be more difficult:
+   <orderedlist>
+    <listitem><simpara>Make sure that the &quot;pretty&quot; URL actually routes to a script
+     containing the Controller.</simpara></listitem>
+    <listitem><simpara>Create a custom <literal>'jump'</literal> handler that'll redirect to a
+     &quot;pretty&quot; URL instead of an &quot;ugly&quot; one.</simpara></listitem>
+    <listitem><simpara>Either change <phd:pearapi phd:package="HTML_QuickForm2"
+     phd:linkend="HTML_QuickForm2_Controller::getActionName" /> to be able to get action name from a
+     &quot;pretty&quot; URL or add a key with &quot;ugly&quot; action name to
+     <varname>$_REQUEST</varname>.</simpara></listitem>
+   </orderedlist>
+  </para>
+ </refsection>
+</refentry>

Modified: pear/peardoc/trunk/en/package/html/html-quickform2.xml
===================================================================
--- pear/peardoc/trunk/en/package/html/html-quickform2.xml	2011-10-22 21:44:05 UTC (rev 318326)
+++ pear/peardoc/trunk/en/package/html/html-quickform2.xml	2011-10-22 21:58:41 UTC (rev 318327)
@@ -25,6 +25,8 @@
    <para>
     Major advantages over PHP4 versions:
     <itemizedlist>
+     <listitem><simpara>Most of the package's functionality is covered by unit
+      tests.</simpara></listitem>
      <listitem><simpara>DOM-like API for building the form structure, new streamlined API for
       elements' values handling.</simpara></listitem>
      <listitem><simpara>Default rendering without tables (inspired by <link
@@ -43,6 +45,7 @@
   &package.html.html-quickform2.rules;
   &package.html.html-quickform2.controller-overview;
   &package.html.html-quickform2.controller-migration;
+  &package.html.html-quickform2.controller-actions;
  </chapter>
 </book>