Deleting entries requires a similar approach to adding, but with a couple of interesting features. First we
must construct a form to present the composers in a form that we can select one to delete. The content file
is:
/examples/sql/deleteComposer-1.xml
<page:content>
<t:heading level="1">SQL Delete Entry</t:heading>
<pf:form id="deleteComposerForm"
flow="deleteComposer"
continuation="{flow:continuation.id}"
session="{flow:__flowId}">
<pf:label>Select composer to delete:</pf:label>
<execute-query xmlns="http://apache.org/cocoon/SQL/2.0">
<query name="selectDeleteComposer" database="composers">select * from composer</query>
</execute-query>
<pf:submit class="button" id="next">
<pf:label>Next</pf:label>
<pf:hint>Check details</pf:hint>
</pf:submit>
</pf:form>
<t:p><link:link type="uri" ref="/examples/sql/sql.html">Return to SQL index</link:link></t:p>
<t:p><link:link type="uri" ref="/examples/sql/logout.html">Logout</link:link> from admin pages.</t:p>
</page:content>
The contents of the form are not known yet. The SQL query will bring back a list of the composers that can be
used as a selector by the form. In order to process this we need a flow script:
resources/scripts/DeleteComposer.php
class DeleteComposer extends Continuations {
/** Logger instance for this class */
private $gLogger;
private $gDeleteComposerModel = array (
"selectDeleteComposer" => "", // Should be same as the name in the form
);
// -*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-* -->
// -*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-* -->
/**
* Make a new instance of the continuation.
*
* @throws RunException if there is no current session in progress.
*/
function __construct()
{
$this->gLogger = Logger::getLogger( __CLASS__ );
parent::__construct( $this->gDeleteComposerModel );
}
// -*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-* -->
// -*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-* -->
/**
*/
function delete()
{
global $gModules;
$this->gLogger->debug( "Delete composer, continuation: " . $this->gContinuation );
$this->gViolations = array();
$finished = false;
while ( !$finished ) {
$this->gLogger->debug( "Processing: " . $this->gContinuation );
$errors = false;
switch ( $this->gContinuation ) {
case 0 :
$this->sendPage(
"deleteComposer-1.html", // The page to send to the client
$this->gDeleteComposerModel, // The current data model to send
++$this->gContinuation, // The continuation link for the next stage
$this->gViolations ); // Array of errors (keyed by data model keys)
$finished = true;
break;
case 1 :
...
break;
case 2 :
...
break;
} // switch
} // while
} // function delete()
The additions to the sitemap are similar to the add composer case
/examples/sql/sitemap
<map:flow language="php">
<map:script src="context://resources/scripts/AddComposer.php"/>
<map:script src="context://resources/scripts/DeleteComposer.php"/>
</map:flow>
...
<map:pipeline>
<map:match pattern="deleteComposer.html">
<map:call function="DeleteComposer::delete"/>
</map:match>
<map:match pattern="deleteComposer.kont">
<map:call function="DeleteComposer::delete"/>
</map:match>
</map:pipeline>
<!-- Only called from the add user script DeleteComposer::delete -->
<map:pipeline internal-only="true">
<map:match pattern="deleteComposer-*.html">
<map:aggregate element="root" label="aggr-content">
<map:part src="cocoon:/menus.xml" element="menus" strip-root="true"/>
<map:part src="cocoon:/deleteComposer-{1}.px" element="content" strip-root="true"/>
</map:aggregate>
<map:transform type="mysql" label="sql-content">
<map:parameter name="show-nr-of-rows" value="true"/>
</map:transform>
<map:transform src="context://resources/transforms/sql2pform.xsl"/>
<map:transform src="resource://resources/transforms/pforms-violations.xsl" label="pforms-violations">
<map:parameter name="formViolations" value="{session:__violations}"/>
</map:transform>
<map:transform src="resource://resources/transforms/pforms-default.xsl" label="pforms-default"/>
<map:transform src="resource://resources/transforms/pforms2html.xsl" label="pforms-html"/>
<map:call resource="outputPage"/>
</map:match>
</map:pipeline>
The returned data is processed by the transform sql2pform.xsl whose transforms
are:
resources/transforms/sql2pform.xsl
<xsl:template match="sql:row-set[ @name = 'selectDeleteComposer' ]">
<xsl:element name="pf:select1">
<xsl:attribute name="appearance">full</xsl:attribute>
<xsl:attribute name="ref">
<xsl:value-of select="@name"/>
</xsl:attribute>
<xsl:element name="pf:violations"/>
<xsl:element name="pf:choices">
<xsl:for-each select="sql:row">
<xsl:element name="pf:item">
<xsl:element name="pf:label">
<xsl:value-of select="sql:name"/>
<xsl:text>, </xsl:text>
<xsl:value-of select="sql:forenames"/>
</xsl:element>
<xsl:element name="pf:value">
<xsl:value-of select="sql:name"/>
</xsl:element>
</xsl:element>
</xsl:for-each>
</xsl:element>
</xsl:element>
</xsl:template>
<!-- -*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-* -->
<xsl:template match="sql:row-set[ @name = 'confirmDeleteComposer' ]">
<xsl:element name="pf:output">
<xsl:attribute name="appearance">full</xsl:attribute>
<xsl:attribute name="ref">
<xsl:value-of select="@name"/>
</xsl:attribute>
<xsl:element name="pf:label">Composer name:</xsl:element>
<xsl:element name="pf:value">
<xsl:value-of select="sql:row/sql:name"/>
<xsl:text>, </xsl:text>
<xsl:value-of select="sql:row/sql:forenames"/>
</xsl:element>
</xsl:element>
</xsl:template>
<!-- -*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-* -->
<xsl:template match="sql:row-set[ @name = 'getComposerId' ]">
<xsl:element name="pf:hidden">
<xsl:attribute name="ref">composerId</xsl:attribute>
<xsl:element name="pf:value">
<xsl:value-of select="sql:row/sql:id"/>
</xsl:element>
</xsl:element>
</xsl:template>
<!-- -*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-* -->
<xsl:template match="node()|@*" priority="-1">
<xsl:copy>
<xsl:apply-templates select="@*"/>
<xsl:apply-templates/>
</xsl:copy>
</xsl:template>
The purpose of this transform is to turn:
<default:row-set xmlns="http://apache.org/cocoon/SQL/2.0" nrofrows="4" name="selectDeleteComposer">
<default:row>
<default:id>16</default:id>
<default:name>Dvořák</default:name>
<default:forenames>Antonin</default:forenames>
<default:birth>1841-09-08</default:birth>
<default:death>1904-05-01</default:death>
</default:row>
<default:row>
<default:id>15</default:id>
<default:name>Mozart</default:name>
<default:forenames>Wolfgang Amadeus</default:forenames>
<default:birth>1756-01-27</default:birth>
<default:death>1791-12-05</default:death>
</default:row>
<default:row>
<default:id>13</default:id>
<default:name>Barber</default:name>
<default:forenames>Samuel</default:forenames>
<default:birth>1910-03-09</default:birth>
<default:death>1981-01-23</default:death>
</default:row>
<default:row>
<default:id>17</default:id>
<default:name>Elgar</default:name>
<default:forenames>Edward</default:forenames>
<default:birth>1857-06-02</default:birth>
<default:death>1934-02-23</default:death>
</default:row>
</default:row-set>
into
<pf:select1 appearance="full" ref="selectDeleteComposer">
<pf:violations/>
<pf:choices>
<pf:item>
<pf:label>Dvořák, Antonin</pf:label>
<pf:value>Dvořák</pf:value>
</pf:item>
<pf:item>
<pf:label>Mozart, Wolfgang Amadeus</pf:label>
<pf:value>Mozart</pf:value>
</pf:item>
<pf:item>
<pf:label>Barber, Samuel</pf:label>
<pf:value>Barber</pf:value>
</pf:item>
<pf:item>
<pf:label>Elgar, Edward</pf:label>
<pf:value>Elgar</pf:value>
</pf:item>
</pf:choices>
</pf:select1>
which is the appropriate PForm data to produce a select field:
The next section shows how to
process the selected choice for deleting a composer.
Copyright 2006 — 2010 Hugh Field-Richards. All Rights Reserved.