Deleting Composers

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 Flow Script

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()

Extending the Sitemap

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:

Processing Returned Data

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.