1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 1804 1805 1806 1807 1808 1809 1810 1811 1812 1813 1814 1815 1816 1817 1818 1819 1820 1821 1822 1823 1824 1825 1826 1827 1828 1829 1830 1831 1832 1833 1834 1835 1836 1837 1838 1839 1840 1841 1842 1843 1844 1845 1846 1847 1848 1849 1850 1851 1852 1853 1854 1855 1856 1857 1858 1859 1860 1861 1862 1863 1864 1865 1866 1867 1868 1869 1870 1871 1872 1873 1874 1875 1876 1877 1878 1879 1880 1881 1882 1883 1884 1885 1886 1887 1888 1889 1890 1891 1892 1893 1894 1895 1896 1897 1898 1899 1900 1901 1902 1903 1904 1905 1906 1907 1908 1909 1910 1911 1912 1913 1914 1915 1916 1917 1918 1919 1920 1921 1922 1923 1924 1925 1926 1927 1928 1929 1930 1931 1932 1933 1934 1935 1936 1937 1938 1939
|
\documentclass[11pt]{report}
\usepackage{times}
\usepackage{fixunder}
\setlength{\topmargin}{-.25in}
\setlength{\oddsidemargin}{0.0in}
\setlength{\evensidemargin}{0.0in}
\setlength{\textheight}{9in}
\setlength{\textwidth}{6.5in}
\newcommand{\pagesep}{\hfil********\hfil}
\newcommand{\code}[1]{{\it #1}}
\newcommand{\literal}[1]{\noindent{\tt #1}}
\newcommand{\br}{\vspace{10 pt}}
\newcommand{\tab}{\hspace{12 pt}}
\newcommand{\tag}[3]{\noindent\bf $<$#1 \rm#2\bf $>$\\
\it #3 \\
\bf $<$/#1$>$\rm}
\newcommand{\tagnop}[2]{\noindent \bf $<$#1$>$\\
\it #2 \\
\bf $<$/#1 $>$\rm}
\newcommand{\stag}[2]{\noindent \bf $<$#1 \rm#2\bf$>$\rm}
\newcommand{\func}[3]{\vspace{10pt}\noindent #2 {\bf #1} (#3)}
\begin{document}
\begin{titlepage}
\hbox{}
\vfil
\begin{center}
\large\bf
PSP-Parser 0.5 Programming Interface\\
\smallskip
\end{center}
\medskip
\begin{center}
Copyright (c) 2000, FundsXpress Financial Network, Inc.
%This library is free software released "AS IS WITH ALL FAULTS"
%and WITHOUT ANY WARRANTIES under the terms of the GNU Lesser
%General Public License, Version 2.1, a copy of which can be
%found in the "COPYING" file of this distribution.
%$Id: parser.tex,v 1.1.1.2 2003/12/06 19:47:25 hartmans Exp $
\end{center}
\noindent
James Jurach\\
Sam Hartman\\
Charles Lowell\\
Zane Rockenbaugh\\
\end{titlepage}
\pagestyle{headings}
\markboth{PSP-Parser Interface Specification}{PSP-Parser Interface Specifications}
\begin{abstract}
Re-address:
PSP, or Perl Server Pages, is a system meant to simplify Web
interface design. PSP allows the embedding of Perl code and special
PSP tags into an otherwise normal HTML document. The PSP code is then
(com)piled by PSP to produce what is known as a pile (a partial CGI
script) which is run via a pile driver.\footnote{The pile is a partial
CGI script because it is not runnable by itself and requires a
piledriver for execution.}
One central idea of PSP is to take the awkward HTML out of CGI and put
the power of CGI into HTML. This is accomplished by providing
HTML-like tags to control page look and data presentation and provide
all the functionality of CGI scripting in a simpler, more familiar
environment. PSP can be thought of as a tool for creating dynamic HTML
pages. In fact, PSP pages (HTML pages with PSP code) can be viewed
directly in a standard HTML browser and they will produce sensible,
though probably not very pretty, results.
There are many other advantages that PSP has over standard CGI
scripting. These include automation of security, field propagation and
other features that built into PSP.
\end{abstract}
\subsection*{Using This Document}
This document is meant to be used as both a reference guide and a
tutorial. If you are just learning PSP, you might find many of the
concepts in this document a bit opaque at first.
It is recommended that new users of the system first skim the examples
found at the end and, then read the Overview chapter, skim over the
Using PSP chapter (the PSP style guidlines provide much useful
insight) and the Conceptual PSP chapter. Skimming the suggested
interface chapter (\ref{psp-suggested interfaces}) is also a good
idea, as long as the new user takes note of the introduction to this
section. Then, one should familiarize themselves with the various PSP
tags and then return for a more in depth reading of the document.
Experienced users will find the document more helpful as a reference
manual. The PSP Tags chapter has the syntax and a short description of
each of the Tags. The Cross Interface chapter might be useful, but is
meant primarily as an implementation guide for the sub systems
utilized by PSP and is not really a user interface spec as it is a PSP
interface spec.
\tableofcontents
\chapter{Overview}
\section{What does PSP Parser Do?}
Blah blah.
Blah blah.
Blah blah.
Blah blah.
Blah blah.
Blah blah.
Blah blah.
Blah blah.
Blah blah.
Blah blah.
Blah blah.
Blah blah.
Blah blah.
\section{Components of PSP}
\subsection{The Parser}
To create a PSP pile, one creates a series of PSP-HTML pages, which
may or may not have PSP-specific tags. All these pages must be under
an arbitrary directory which we will call the root-pile
directory. When it is time to compile, the path to the root-pile
directory is given to the PSP-compliant piler and it will then
recursively process all pages under this directory which have an html,
HTML, psp, PSP, fs or FS extension. Be aware that all other pages will
be ignored unless explicity included in a parsed file (by use of the
psp:include tag).
\subsubsection{The Tag Extension Mechanism}
blah blah.
blah blah.
blah blah.
blah blah.
\subsection{The Compiler}
The syntax for compiling a PSP pile is:
\begin{verbatim}
piler [-I <absolute include path from machine root>]
<pile name> <output file name> <root of the pile source>
\end{verbatim}
The optional -I argument specifies the directory to look for PSP
included files (see \ref{tags: psp:include}) when they are not found in
the proper place in the pile source.
The name of the pile is used internally, but, for convention sake,
should be related to the output file's name (which may be specified in
a relative fashion). The output file name should generally be the pile
name with a `.pile' appended to it. The `.pile' is the recommended
extension used by servers to redirect proccessing to the piledriver
(or a similiar script to handle the running of piles).
Finally, one must specify the root of the pile source. The compiler
will start at this point (which may be specified relative to the
current directory) and recursively traverse the subdirectories
proccessing all files ending in `.html,' `.psp,' or `.fs'.
Compilers may take further options. See the compiler documentation for
additional information.
\chapter{Tag Specifications}
\section{General Information}
Obsolete:
By (enforced) convention, most PSP-specific tags begin with
`PSP.'\footnote{If a form tag has the fieldspace parameter, then it
will be specially processed by PSP; it is not prepended, however,
since it is not PSP specific tag.} The few tags which do not begin
with PSP are only found and are only valid within other PSP container
tags. This helps to ensure that they will not be overrun by future
HTML or browser extensions. There are basically three types of PSP
tags. The first, a code snippet tag, is the only one that does not
emulate HTML tag syntax and look. A second tag, the psp:script tag, is
for general purpose coding. There a number of other tags, however,
that perform functions that could be coded directly in Perl, but which
are so common as to be supported directly by PSP in order to maintain
HTML consistency and ease the task of PSP markups.
Of these tags, some control program flow and page logic, such as
psp:if. Others are used within forms to display values or set up submit
buttons.
\section{Special Tags}
\subsection{Perl Snippets}
\subsubsection{Syntax}
\begin{tabular}{p{4in}l}
{\bf[$+$ \code{arbitrary evaluatable Perl token} $+$]} & (HTML-escapes) \\
{\bf[$-$ \code{arbitrary evaluatable Perl token} $-$]} & (URI-escapes) \\
{\bf[$=$ \code{arbitrary evaluatable Perl token} $=$]} & (verbatim) \\
\end{tabular}
\subsubsection{Description}
The Perl snippet mark is really not a tag, but simply declares a place
to insert some arbitrary Perl code. The code cannot be greater than
one line in length; that is, any code that requires a `;' must go in a
psp:script and not a snippet. In fact, the `;' is optional in the
snippet.
Most generally, the snippet is used to print some value to the
page. This value may or may not be viewed by the final user. That is,
it could be used in an HTML link or what not. The three tags differ in
their output. The first ( [+ ... +] ) will HTML-escape the result of the
Perl code; it is therefore almost always the right thing to use except
in links. The second ( [- ... -] ) will URI-escape, so it is almost
always the right thing to use in links (and not elsewhere). The third
( [= ... =] ) does not process the code's output and is rarely if ever
appropriate.
Normally, code snippets will be inserted within an HTML document where
it is advantageous to maintain the look of the document, yet there is
some variable fragment which needs to be resolved at run-time (when a
user actually views the page). For example, one might have something
like:\\
\begin{verbatim}
Hello [+ $name +], how are you doing today?
\end{verbatim}
or
\begin{verbatim}
<a href=http://[- $server || $default -]/face.html?flag=[- $flag -]>
\end{verbatim}
Two notable limitations of the snippet are that commenting them out in
any fashion will not prevent the code within from being executed,
and that each snippet must be contained entirely on one line.
Note that since the [- ... -] snippet will URI escape, it cannot be
used for the entire value of an href tag as it will likely screw
up. `?' and `\&' specifically will both be messed up.
\subsection{psp:script}
\subsubsection{Syntax}
\tagnop{psp:script}{arbitrary script}
\subsubsection{Description}
The psp:script tag defines a section of the HTML document as Perl
code. It allows coders to integrate complex data gathering and
processing functions directly into an HTML document. It functions much
the same as the JavaScript tag in Netscape, except that it does not
rely on a proprietary language.
The psp:script tag is the preferred tag for any code over a line or so in
length, or for any code not meant to print to the HTML page. It might
be used to query databases, perform calculations or anything else Perl
is capable of.
The psp:script tag contains script of the appropriate language.
(Currently, only perl is supported), and does not contain HTML.
Obsolete: Only Perl code, and not PSP code, should appear within a psp:script.
Note also that psp:script should not attempt to change the contents of
the page\footnote{Contained in the \$content variable} as there is no
guarantee that this will work as expected since the compiler will be
unaware of changes made from within the psp:script container tags. Also
be aware that psp:script tags are part of the re-evaluation process when
pages are verified (see \ref{error handling: page verification}), and
this fact needs to be taken into account since if a psp:vpage is used, the
code will be run twice.\footnote{That is why the use of psp:vpage is
discouraged in favor of vinstatiated.}
\subsection{psp:declare}
\subsubsection{Syntax}
\tagnop{psp:declare}{arbitrary script}
\subsubsection{Description}
blah blah.
blah blah.
blah blah.
\subsection{psp:comment}
\subsubsection{Syntax}
\tagnop{psp:comment}{arbitrary script}
\subsubsection{Description}
blah blah.
blah blah.
blah blah.
\subsection{psp:nop}
\subsubsection{Syntax}
\tagnop{psp:nop}{arbitrary markup language}
\subsubsection{Description}
blah blah.
blah blah.
blah blah.
\subsection{psp:include}
\label{tags: psp:include}
\subsubsection{Syntax}
\stag{psp:include}{src=\code{a PSP-HTML file name}}
\subsubsection{Description}
This command is used to include repeated code or text. This command
specifies a document or part of a document to include
verbatim\footnote{Or effectively so.} at the point at which the tag is
included. You could think of it as simply dropping in the text of the
file. Note that the psp:include statement is evaluated at compile time,
meaning that you cannot have variables in the src attribute.
The file is specified in an pile-absolute manner meaning that it is
not relative to the current page, but relative to the root of the site
to be compiled. The file is specified with path information, so if the
'hello' was in directory '/bob/micsite/branch' where pspsite is the
root of the site to be compiled, then you would say
`src="branch/hello".' Note also that you never have a leading `/' in
the path information.\footnote{The syntax src="branch::hello" would
also be acceptable.}
To support files that are meant to be included in several different
piles (and therefore cannot be strictly contained under a single pile
root), one may use the -I option at compile time to specify an include
directory (see \ref{compiling}). In this case, the pile-root relative
file is first looked for and if net found, then the file is looked
relative to the include directory. So, from above, if there were no
file `/bob/micsite/branch/hello,' and the pile was compiled with `-I
/bob/include,' then the compiler would search
`/bob/include/branch/hello.' Note the search order above.
Note that because they are already included, files with the extension
.html, .psp or .fs that are within the site should never be
psp:included. By convention, included files should have a `.inc'
extensions.
It may be possible to psp:include files which are external to the site
(i.e., src="../style.inc"), but the feature is unsupported at the
time of this writing.
\subsection{psp:if}
\subsubsection{Syntax}
\tag{psp:if}{test="\code{Perl conditional code}"}{arbitrary PSP-HTML code}
\subsubsection{Description}
The psp:if is a special tag which allows for parts of a page to be
conditionally constructed or proccessed\footnote{The psp:if tag, and
all logic tags, are, in fact, strictly potent at runtime.}. This tag
helps to maintain consistency in HTML look and avoids always having to
use the psp:script tag.
The psp:if tag should be used whenever there are sections of the page
or control code which should only be conditionally processed and/or
constructed. As mentioned earlier, this tag could be subsumed into
psp:script (in certain cases), but that would break the HTML look and
simplicity, which is the goal of psp:. Compare:
\begin{verbatim}
<psp:script>
if ($sufficient_funds){
</psp:script>
<h2>You have enough money</h2>
<psp:script>
}
else{
</psp:script>
<h2>Sorry, insufficient funds.</h2>
<psp:script>
}
</psp:script>
\end{verbatim}
to:
\begin{verbatim}
<psp:if test="$sufficient_funds">
<h2>You have enough money</h2>
</psp:if>
<psp:else>
<h2>Sorry, insufficient funds.</h2>
</psp:else>
\end{verbatim}
The PSP code (which may include a psp:script) contained within the
opening and closing psp:if tags constitutes a lexical block of
code. This is true of all the PSP native logic tags.
psp:if tags ar only potent at runtime, however. A psp:fieldspace within
a psp:if, for instance, is legal, but will actually have no effect. The
psp:fieldspace will be read at compile time and the fieldspace will end
up being defined.
\subsection{psp:else}
\subsubsection{Syntax}
\tag{psp:else}{[test="\code{arbitrary test code}"]}{arbitrary PSP-HTML code}
\subsubsection{Description}
The psp:else tag subsumes the functions of an elsif (else if) and
else. For a complete understanding of psp:else, be sure and reference
the psp:if section.
When given the optional argument, psp:else acts as an elsif
statement. Otherwise, it will default to an else (essentially,
\literal{elsif(true)...}). This allows one to test for multiple
possibilities and also provides the ability to hand control over a
default section of code.
Note that a psp:else tag must immediately follow a psp:if or another
psp:else. There cannot be PSP-HTML between the end of one and the
beginning of another. In fact, the only thing allowed between
\begin{verbatim}</psp:if>\end{verbatim} and \begin{verbatim}<psp:else>\end{verbatim} is whitespace.
\subsection{psp:list}
\subsubsection{Syntax}
\tag{psp:list}{list="\code{list or code to return a list}" iterator=\code{var
to map items to}}{arbitrary PSP-HTML code}
\subsubsection{Description}
psp:list is analogous to a `foreach' command. psp:list is used to
iterate over a list and perform operation on or display each
element. The `list' parameter defines how the list is to be generated,
or may even specify a literal Perl list which is currently in
scope. The `iterator' parameter defines the name of the variable which
shall contain each of the elements of the list. This variable will be
lexically scoped to the block containing the psp:list. Example:
\begin{verbatim}
<table>
<psp:list list="&get_accounts" iterator="$account">
<tr><td>Name: [+ $account->name; +] </td>
<td>Acc. Number: [+ $account->number; +]</td>
<td>Balance: [+ $account->balance; +]</td>
</tr>
</psp:list>
<!-- $account is now out of scope -->
</table>
\end{verbatim}
might produce output something like:
\begin{verbatim}
Name: Mr. PSP Acc. Number: ad192381 Balance: $12,000.00
Name: Hojo McMorman Acc. Number: 918231 Balance: $0.27
\end{verbatim}
\subsection{psp:while}
\subsubsection{Syntax}
\tag{psp:while}{test="\code{arbitrary Perl code}"}{arbitrary PSP-HTML code}
\subsubsection{Description}
psp:while provides a PSP native while loop that will iterate over the
PSP-HTML code enclosed within the psp:while environenment until the
conditional fails.
Generally, there will be some Perl within a psp:script or snippet which
will cause the loop to eventually terminate. For example:
\begin{verbatim}
<psp:script>my $test = 0;</psp:script>
<psp:while test="$test < 4">
Iteration: [+ ++$test; +]<br>
</psp:while>
\end{verbatim}
would produce something like:
\begin{verbatim}
Iteration: 1
Iteration: 2
Iteration: 3
Iteration: 4
\end{verbatim}
Like all the other PSP native logic tags, the PSP code between the
opening and closing psp:while tags constitute a lexical block.
\section{Message Tags}
\subsection{psp:message}
\subsubsection{Syntax}
\tagnop{psp:message}{arbitrary markup language}
\subsubsection{Description}
blah blah.
blah blah.
blah blah.
\subsection{psp:message_def}
\subsubsection{Syntax}
\tagnop{psp:message_def}{arbitrary markup language}
\subsubsection{Description}
blah blah.
blah blah.
blah blah.
\subsection{psp:throw}
\subsubsection{Syntax}
\tagnop{psp:throw}{arbitrary markup language}
\subsubsection{Description}
blah blah.
blah blah.
blah blah.
\subsection{psp:errorreport}
\subsubsection{Syntax}
\tag{psp:errorreport}{}{PSP-HTML}
\subsubsection{Description}
This is used to iterate over all the error-packaging objects. Within
the tag, the special variable \$error is made available within the
opening and closing tags. This variable can then be used to output
those things which an error report should have.
At the time of this draft, the only real requirement to be a
PSP-compliant error-packaging object are those methods necessary to
create and iterate. For this reason, one must look to the
documentation for the error packaging object to figure out how to do
what one wants. Later versions of PSP will likely have a more
integrated and user friendly interface.
\subsection{psp:handle}
\subsubsection{Syntax}
\tagnop{psp:handle}{arbitrary markup language}
\subsubsection{Description}
blah blah.
blah blah.
blah blah.
\section{Form Tags}
\label{form tags}
Forms tags have been separated, because much of the complexity of PSP
is introduced by forms.
\subsection{psp:form}
\subsubsection{Syntax}
\tag{psp:form}{{\tt ...} [psp:fieldspace=\code{some legal name string}]
[errorpage=\code{a PSP-HTML page name}]}
{PSP-HTML code}
\subsubsection{Description}
PSP defines a necessary extension to the standard form tag. Each form
that will contain psp:inputs, psp:hiddens psp:displays, or that part of a
page that is in a chain of pages for which the coder wishes to ensure
data propagation, must declare its field space name within the form
tag.
The name must be defined somewhere within the files which PSP is
compiling with a psp:fieldspace tag. The fieldspace must be defined in
a .fs file. For maintainability and style (though not mandatory), only
one fieldspace should be defined per file. This does not mean that one
cannot have non-PSP forms, however. It is possible to have such forms
and access their variables while within psp:script tags, as one would in
standard CGI scripting.\footnote{The special variable \$cgi is
available for this and other purposes.} See \ref{style: psp vs html
forms} for stylistic notes on when to employ each of the differing
forms.
The value of the errorpage attribute is the name of a
PSP-HTML page in the pile to go to if there is an error
encountered during the verification process. This will overide the
default value supplied in the fieldspace definition for this form
only.
Note that it is at the form tag (if a psp:fieldspace is specified) that
the fieldspace object will be instatiated. Refer to \ref{execution
flow} for how this will affect the execution of the page.
\subsection{psp:submit}
\subsubsection{Syntax}
\tag{psp:submit}{
name=\code{binds to an HTML control}\\
value=\code{unique among psp:submits of the same name, matches an HTML control}\\
goto=\code{absolute location to go to after successful verification}\\
{\rm [}unconditional=\code{"true"}{\rm ]}}
{ {\rm [$<$psp:vfield name=}psp:define'd field name within field space to verify {\rm $>$]}\\
{\rm [$<$psp:vpage name=}A page to be re-evaluated and verified {\rm $>$]}\\
{\rm [$<$psp:vverify name=}A psp:verify defined for this field space to be called {\rm $>$]}\\
{\rm [$<$vpresent$>$]}}
\subsubsection{Description}
This tag is used to declare how to handle submit buttons within a PSP
form. Each psp:submit must be associated with an HTML control of the
same name/value designation.
The name parameter should generally be common to all the related
submits (PSP and regular) buttons for the form which this tag appears
on (though not expressly non-unique for other forms, even those
sharing the same field name space). The recomended value for the name
attribute is [page name]_submit. That is, if the submit buttons are
to appear on a page called `result.html', the recommended name value
would be `result_submit.' This is mainly to keep things regular and
easy to follow, although just about any name will work. If one has
multiple forms on a page, then the recommended naming convention is
'result_submit1', etc. This is a style issue, though.
There are reasons to have psp:submits with differing names,
however. One is if one wants to implement variable goto's. Because of
the way PSP works, the goto parameter cannot be a variable. That is,
`goto=``\$foo''' is not valid code. One could have something of the form:
\begin{verbatim}
<psp:submit name=``test_submit'' value=``Submit''
goto=``analyze_test''>
</psp:submit>
<psp:submit name=``quiz_submit'' value=``Submit''
goto=``analyze_quiz''>
</psp:submit>
<input type=``Submit'' name=``$destination'' value=``Submit''>
\end{verbatim}
The name/value pairs are used to bind the psp:submit with the standard
HTML controls. Unlike psp:input and psp:display, a standard matching
HTML control tag must also be included and will not be generated for
you. The matching control will most often be a control button, but
does not necessarily have to be. It may also be an image-map
designation, or even some a hidden input or radio button. When the
form is submitted, the value will be resolved control will be passed
to the associated psp:submit.
Thus, when one {\it does} have different names for the psp:submits and
their associated controls, one must be careful that two can never be
defined at the same time. This is also a concern, actually, if they
all have the same name. Thus, while the page flow can be directed by a
hidden, a radio-button group, a button cluster, or an image map,
having both a button cluster and a radio-button group will have
unpredictable effects as PSP will not know which parameter to use.
The goto parameter defines the absolute URL within the system to go to
after a successful submit. Refer to psp:include for an example of
this. This page does not necessarily have to be in the same directory
and multiple submits can have pages in various directories (which is a
win over regular HTML submits and form control). Realize however that
each submit will share the target of the form tag, so to support
multiple targets, it is still necessary to break the control over
multiple forms.
If the attribute `unconditional' is included with the value of `true',
then the goto parameter will be invoked even in case of error. This
should be included only in the case where you want to go to the next
page even if there are errors {\bf produced by the verifications
associated with the psp:submit where the unconditional parameter
appears}. This may be the case with certain styles of error reporting.
Note that old errors (from previous pages in a series) will not cause
execution flow to redirect to the error page. Only errors produced by
the current page/submit.
The three optional included tags, psp:vpage, psp:vfield and psp:vverify define
pages (e.g., relative URLs), psp:define'd fields and psp:verify's,
respectively, that need to be checked to see if there was bad data
entered in the form. You may have as many or as few of these optional
tags as you wish. These tags, and the vpresent tag, are discussed in
section \ref{error handling tags}. Not that these tags only have
meaning in the context of a psp:submit and that no other tags or naked
text has any meaning when contained by a psp:submit.
Finally, the the no-reset-dynamic attribute should be included if one
wishes to start counting dynamic fields from the current dynamic
field. This should generally only be included if a page is
self-referencing, in which case psp:rollover and psp:rollback
should most likely be used.
An example of a psp:submit would be:
\begin{verbatim}
...
<psp:submit name="application_submit" value="Submit"
goto="application/process_application">
<psp:vfield name="applicant_name"/>
<psp:vfield name="applicant_ssn"/>
<psp:vverify name="enough_money"/>
</psp:submit>
<psp:input type="submit" name="application_submit" value="Submit">
<br>
<psp:submit name="application_submit" value="Cancel"
goto="home">
</psp:submit>
<input type="submit" name="application_submit" value="Cancel">
...
\end{verbatim}
\section{FieldSpace Tags}
\subsection{psp:fieldspace}
\label{tag psp:fieldspace}
\subsubsection{Syntax}
\tag{psp:fieldspace}{name=\code{field space name} inherit=\code{class name}
error_page=\code{an html page}}{
one or more psp:defines, zero or more psp:verifies and no more than one
non-nested psp:group}
\subsubsection{Description}
This tag and its included code defines a field space object. These
tags must appear in a .fs file and there should generally be one
psp:fieldspace tag per file with nothing but documentation and the tag
in a given file.
The code bounded by the psp:fieldspace form tags and external to all
other PSP tags (psp:define, psp:group, psp:verify) is treated as pure
Perl code (though it is still necesarry to HTML escape the code). For
this reason the logical PSP tags (psp:if, psp:else, etc.) cannot be used
here, and there Perl equivalents should be used (if, elsif, etc.). In
addition, snippet markups or meaningless. Display tags also have no
meaning and cannot be used. psp:inclued may be used, however. This is
because while a great portion of PSP code is meant to correspond
roughly to HTML output, the code within the psp:fieldspace is meant for
proper setup and instantiation of field spaces, so has an inately
different purpose, and therefore, form.
No psp:fieldspaces (or psp:defines) parameters should contain hyphens
('-').
\paragraph{name}
It was true with MIC 2.0 and earlier that the name of the
psp:fieldspace must be unique with regards to page names. That is, if
there was a page ``new_accounts.html'', then one could not have
name="new_accounts" in any fieldspace. Under MIC 1.0, there is
effective mangling of the fieldspace names and this is no longer a
problem.
Note from mkinman : I found that this is still a problem in 1.0.
Daniel should comment on this.
It is recommended that the name of the file containing the fieldspace
have the same name as the fieldspace plus `.fs.' I.e., it is recommended that the
line
\begin{verbatim}
<psp:fieldsapce name="new_accounts" ...
\end{verbatim}
\noindent appear within a file called new_accounts.fs.
Note that there are a few reserved words that are disallowed as field
space names. Specificially, `verify' and `inherit' are
forbidden. Other than these, a fieldspace may by any string of
alphabetic characters and the underscore. That is, it must match the
Perl regular expression /$\backslash$A[a-zA-Z_]+$\backslash$Z/.
\paragraph{inherit}
The inherit parameter specifies the class name from which the field
space object to be constructed will inherit from. This will define
certain behaviors, outside of the scope of this document, tied to the
implemntation of the PSP-compliant fieldspace. The type of bedaviors
this will control will be things like the life and scope of the data
maintained by the fieldspace (subject to certain restrictions and
minimums required by PSP), the mechanism of data propagation and
retrieval, etc. It may even be possible to inherit from other existing
fieldspaces, e.g., inherit="psp:FieldSpace::new_accounts", but this
is an untested feature which nevertheless should be supported in a
later release.
\paragraph{error_page}
The error page parameter defines the page to go to in case of an
error. Further details are given later in \ref{error handling}. Note
that this is a default value and can be overridden by the errorpage
attribute found in a form tag.
\subsection{psp:define}
\label{form tags: psp:define}
\subsubsection{Syntax}
\tag{psp:define}{name=\code{variable name} type=\code{IO class}
data=\code{data container class}}{
list to be passed to datatype constructor or list constructor[;;
Perl code to be executed in order to set up the field]
}
\subsubsection{Description}
psp:define is used to define field types---how they will be displayed
and the type of data they contain. Any piece of data which may be
queried from or displayed to an end user should be
psp:define'd. psp:define tags have an undefined meaning outside of a
psp:fieldspace tag.
Putting conditionals around a psp:define (or any other fieldspace tag)
has no effect. There is a fundamental difference between the setup
code or group setup code (the code external to the psp:define but
within a psp:fieldspace and possiblf psp:group) and they occupy
different lexical groups, even though bad style may make this
distinction unclear. For this reason and for simple style and purpose,
code within the code blocks following should be side effect-free with
regards to all data except for the field itself.
\paragraph{name}
The name parameter of psp:defines within the psp:fieldspace do not have
to be globally unique, but must be unique within the entire
psp:fieldspace. psp:groups within a psp:fieldspace do not constitute
seperate namespaces.
\paragraph{type}
The type parameter identifies the datatype to associate with this
field.\footnote{At this point, the term field might become a bit
confusing. Field does not necessarily refer to a blank field like a
text input device in HTML. A field may be associated with any input
device; e.g., a radiobutton, checkbox, select list, etc..} This must
be the name of a PSP-compliant datatype, discussed in
\ref{cross interface: datatypes}.
\paragraph{data}
The data parameter is the name of a data encapsulator class to be used
by the datatype specified in type. Depending on the implementation of
the PSP-compliant datatypes being used, the seperation of these two
parameters may seem uneccessary or even cumbersome and spurious, but
examples and justifications can be found in \ref{cross interface: datatypes}.
\paragraph{default code block, function or list}
Immediately after the $>$ follows the default specifier.
This is treated as the contents of a subroutine in the pile's
top package (i.e.~global pile variables are available); braces
are optional. Often this is a single constant value or a short
constant list, but more programmatic code can be included.
There are many cases where multiple values are expected;
for more on this, see \ref{forms etc.}.
As noted in \ref{execution flow}, this code block will not be executed
if PSP believes that there is data present which should override the
default data. It is a good idea to make your default data code side
effect free. Return the list of values, but don't go off and execute
arbitrary programs or mangle data, etc., etc.
\$obj and \$index (and all the obj's and indexes of parent groups)
will be available in this code block and the arbitrary code block, if
they themselves are available. Your code should never depend on any of
these, however, as described in \ref{forms etc.: objs}.
Note that \$fs and \$field are {\bf not} currently made available here.
\paragraph{arbitrary code block}
The arbitrary and optional code defined within the block following the
double semicolon (which is itself optional if no arbitrary code block
is defined) is executed as the last step of field initialization (see
\ref{execution flow}). Within this block PSP coders will have the
special variables \$fs and \$field made available to them; at runtime
these will be the fieldspace object and the field object respectively.
Specifics on the field object can be found in the documentation
accompanying the PSP-compliant field space implementation being used
in your PSP system. The PSP interface specification can be found in
\ref{cross interface: fieldspace}.
\paragraph{Dynamic psp:defines}
Dynamic psp:defines are any psp:defines within psp:group container
tags. Dynamic fields are discussed in more detail later. At this
point, it suffices to note that within the code block, the object
vaiarble and numvar variable will be made available through the action
of the psp:group tag.
\subsection{psp:verify}
\subsubsection{Syntax}
\tag{psp:verify}{name=\code{name for this verification} test=\code{test}}
{PSP-HTML code to be run... hopefully with a well defined purpose}
\subsubsection{Description}
psp:verify is used to provide special verification procedures which are
not handled by the datatype verification procedures. It provides for
arbitrary tests and reports.
psp:verify's are contained within a psp:fieldspace tag. The name parameter
assigns a name to this psp:verify. Later, in the psp:submit tag, one can
specify psp:verify names which must pass in order for the form to pass
the verification process.
The test parameter may be either a block of code or a function name to
call. A simple conditional statement is not sufficient because of the
accounting necessary for PSP's error tracking and reporting
functions. More about the necessary accounting in \ref{error handling:
user defined etc.}. For now, it will simlpy be noted that the code or
subroutine must return a boolean where a true value indicates that no
errors where found and a false indicates that an error was found, and
thus, the associated error text contained between the tags should be
processed and displayed when requested (with a psp:errorreport).
One may use a psp:verify for the purpose of conditional
verification. That is, there may be a situation where the user want to
verify fields A and B and run the verification X if parameter P is
set, and perform no verification otherwise. This may be accomplished
by using the \code{verify_fields()} and \code{verify_verifies()}
functions defined as necessary for a PSP compliant fieldspace
implementation. See \ref{error handling: conditional verification} and
\ref{suggested interface: fieldspace required}.
It is assumed (and highly recommended) that one will redisplay any
fields involved in a failed test. This will give the end user the
chance to change faulty data without having to return to an old
form. See \ref{error pages} for more about this.
Note that the PSP-HTML contained between the tags is deprecated
because it may not include certain PSP tags. Specifically, other
psp:verifies are excluded (as well as psp:fieldspace and psp:define,
obviously).
\subsection{psp:input}
\subsubsection{Syntax}
\stag{psp:input}{name$=$\code{psp:defined variable name} [no-format$=$``true'']
[edit_test$=$``test''][changflag$=$\code{variable}]}
\subsubsection{Description}
psp:input is analogous to the standard HTML {\tt <input ...>} tag. The
size of the input field created, its default value (if any) and other
attributes are defined earlier in psp:define.
psp:input is used to create input fields on forms for PSP defined
values. It must only be used within the {\tt <form...>} tags which
have the optional field space parameter. The name parameter takes a
psp:defined name which has (or will be) defined for the psp:fieldspace
of the current form.
Note that the psp:input does not overwrite the normal {\tt <input ...>}
tag, but is in addition to it. That is, one may freely mix psp:input
and input tags and make use of both. Realize, however, that there is
no psp:-supported checking and verification for non-PSP input, nor will
the data be saved to the database, etc.
Non-PSP fields should be controlled through standard HTML inputs and
PSP defined fields should be controlled through psp:inputs. A psp:input
with a non-psp:define'd field and a standard HTML input with a
psp:defined field are both undefined.\footnote{One of psp:'s security
features keeps the standard fields from being potent by registering
which fields have the possibility of change.}
psp:input's handle both statically and dynamically fieldspaces. If a
dynamic field is requested outside of a psp:dynamicdisplay, then the
results are undefined. Currently, it is also not permissible to have
non-dynamic field within a psp:dynamicdisplay since this is almost
always the wrong thing to do. This may be supported in future
releases, however.
Also, any psp:input will automatically attempt to format the value
before displaying it. This means that the data may change form, but
not meaning, from one viewing to the next. This may be overidden by
the tag {\tt no-format=true}, or there may be mechanisms within the
datatype object. The formatting is not only for viewing purposes; if
successful, it will store the canonical form in lieu of the
original. Of unsuccessful (i.e., unable to canonicalize), the original
form will be maintained. This functionality does not provied any error
handling on it's own. For that, you must specify the proper checks and
reporting mechanisms as specified in \ref{error handling tags}.
The optional changeflag attribute takes the name of a Perl variable
that will be set to true if the value of the named field ever changes
due to end-user action. This variable will be introduced my PSP and
will be scoped to the page.
The optional \emph{edit_test} attribute allows us to test on wether we want to
do a psp:input or a psp:display. If the \emph{edit_test} is true, then html
input is generated for the associated psp:define value. If the
\emph{edit_test} is fales, then the value of the psp:define is outputed to the
user.
\subsection{psp:display}
\subsubsection{Syntax}
\stag{psp:display}{name=\code{psp:defined variable name} [no-format="true" raw="true"]}
\subsubsection{Description}
psp:display is used to display psp:define'd variables. It will display
the current value of the field. A psp:display is compatible with a
psp:input and will cause no conflicts if both are used on the same page.
The {\tt raw} option, if set, will cause the value contained to be
displayed without HTML escaping. The intended purpose for this
functionality is to allow the presentation of the data as HTML within
the HTML. Note that raw displayed valuse are never formatted.
\subsection{psp:hidden}
\subsubsection{Syntax}
\stag{psp:hidden}{name=\code{psp:defined variable name} [no-format="true"]}
\subsubsection{Description}
psp:hidden will place the value of the proper field in a hidden HTML
tag. Use this tag with caution. Usually, if you want to use it, you
probably shouldn't. Remember, the field space will propagate all data
for you.
\subsection{psp:alias}
\subsubsection{Syntax}
\tagnop{psp:alias}{arbitrary markup language}
\subsubsection{Description}
blah blah.
blah blah.
blah blah.
\subsection{psp:field}
\subsubsection{Syntax}
\tagnop{psp:field}{arbitrary markup language}
\subsubsection{Description}
blah blah.
blah blah.
blah blah.
\subsection{psp:import}
\subsubsection{Syntax}
\tagnop{psp:import}{arbitrary markup language}
\subsubsection{Description}
blah blah.
blah blah.
blah blah.
\subsection{psp:use_fieldspace}
\subsubsection{Syntax}
\tagnop{psp:use_fieldspace}{arbitrary markup language}
\subsubsection{Description}
blah blah.
blah blah.
blah blah.
\subsection{psp:reinitializefs}
\subsubsection{Syntax}
\tag{psp:reinitializefs}{test=\code{perl code}}{PSP Code to be run when the test is true}
\subsubsection{Description}
When the test is true, this will cause the fieldspace associated with
the form to be reinitalized at the point that this tag is dropped. The
code contained by the tag may contain setup code of some sort, but may
also contain messages to print to the user, etc. It is regular psp:
code. This tag's purpose is to refresh the field space when actions on
the current page have changed the nature of the data. For instance, if
a user asks that certain items in a dynamic field be deleted, and the
page is refreshed, then we must first instantiate the regular
fieldspace, delete the fields. But, if we did not re-initialize, there
might be blank items on the screen. And, depending on how
initialization works, there is the possibility that a field will be
missed since the data may collapse on the next page, and the item
betwenn the final on the current and the first on the next will never
get shown.
\subsection{psp:group}
\subsubsection{Syntax}
\tag{psp:group}{name=\code{group name}
[obj=\code{name of special object variable}]
[numvar=\code{name of special indexing variable}]
[numdisplay=\code{default number to display per invocation of the psp:dynamicdisplay}]
[maxnum=\code{absolute maximum number to display}]
[dummyok="true"]
}
{
Group setup code and at least one psp:define
}
\subsubsection{Description}
All dynamic fields must belong to a psp:group. There can only be one
primary psp:group in a field space, although other psp:groups may be
nested inside.\footnote{Nested groups have been tested to some exent
at the time of writing, but it must be acknowledged that there are a
couple known minor bugs with nested groups. The behavior and code
appear, however, basically sound and the known bugs should be easy to
fix (they are already analyzed) when the need arises. That is not to
say that more extensive tests/usage will not turn up more fundamental
problems, though.} This tag and its contents define the behavior and
member fields for a dynmaic field which can then be later accessed
through a psp:dynamicdisplay tag.
\paragraph{group setup}
The group setup code is defined to be the Perl code within the
psp:group tags, but external to the psp:define or other psp:group
tags. The expected and recommended use of this code is to set up \$obj
(discussed below). \$obj can then be used as the information source
for the field initializations within the psp:group. It is common to
have \$obj be iterated (if indeed it is iterated) from some object or
variable set defined in the initialization code (within the field
space but external to the psp:group). If \$obj is static, then a
statement such as:
\begin{verbatim}
$obj = $query_object;
\end{verbatim}
\noindent is still required.
It is extremely important to realize the ramification for program
execution, however. Unfortuneately, the relationship of the \$obj to
the proper instantiation of fields is a bit involved.
The first thing to note is that the existence of \$obj controls the
halting of field instantiation in a non-dummy fieldspace and the point
of dummy production in a dummy fieldspace. That is, if you have a
fieldspace that is not a dummy fieldspace, and your code dictates the
creation of 5 \$obj's, then you will get a maximum of five field
groups total. If the fieldspace allowed dummies, the 6'th field group
and up will be dummies. Note that this means that in the initalization
code of the psp:define, one must not depend on \$obj for dummy
fieldspaces... it won't be their. See \ref{form tags: psp:define} for
more information on this.
\$obj should be independant of the order of indices defined by
\$index (discussed below). That is, it should either ignore \$index
or not depend on the order of \$index. So, if we have:
\begin{verbatim}
$obj = $batch_retriever->get_nth($index);
\end{verbatim}
If we get \$index as 2, 20, 1, 5, in that order, the code should
react reasonably. So, wanting to look back at the previous \$obj or
assuming that the previous \$index was one less that the current will
cause problems.
The fieldspace variable is made available as \$fs within the group
setup code.
\paragraph{dummyok}
A dummy field is a dynamic field for which there is no \$obj (they,
thus, must occur in groups since \$obj is defined for a group). As for
as ones psp:define code goes, these fields must be handled (by testing
on the existence of \$obj or by not requireing \$obj), but they act
the same. The purpose of the distinction is to support two common
functions of dynamic fields.
The first category is where a form is meant to support n user inputs
where n may be limited (by maxnum) or infinite. In this case, we would
want to support dummyok to be true since some or all of the fields
might have no dependency on prior data.
The second category, for which we would want to set dummyok to false,
or leave the parameter out, would be where we want to allow users to
edit existing data, but not add anything of their own. In the latter
case, it is obvious that once we run out of \$obj's (where each \$obj
is a package of existing data for a group of fields), we don't need to
create any more fields (or groups) and so stop.
This, in short, is the interaction of dummyok and the existence of
\$obj.
\paragraph{special variables}
Generally, the value of the obj attribute should be \$obj (which is
the default if the attribute is left out), because this is safe and
will be quickly understood by other PSP-coders by convention. Also,
other names may overrun special variables or global variables. Thus,
this convention also mandates that no global variable called \$obj is
created within a pile. (Note that \$obj is used in the text to refer
to that thing in code samples and in documentation.)
If there are nested groups, then a scheme such as \$obj1, \$obj2,
etc. is preferred. If, however, this is unclear (especially if
multiple objs are accessed in psp:defines which are members of nested
groups, one could more reasonably consider more descriptive
names. Nested names, however, must be unique within a field space. No
guarentee is made on what will happen if these names clash.
The value of numvar should generally be set to \$index for the same
reasons. \$index is the default that will be used if the attribute is
left out.
Within the psp:group (and nested psp:group's), all psp:define
initalization code will have \$obj and \$index made available to
it. While \$index is set by PSP code, \$obj must be set by the
PSP-coder in the group setup code.
\subsection{psp:do}
\subsubsection{Syntax}
\tag{psp:do}{name=\code{name of tied dynamic field}
numvar=\code{variable in which to place the current index}}
{code to be executed upon each instantiation}
\subsubsection{Description}
psp:do's are only valid within forms. Their purpose is to ``do''
something to each instantiation of the dynamic field specified in the
name attribute. Within the psp:do, \$field is made available to the
coder to modify and check. psp:do's are not necessarily expected to be
side effect-free with regards to other variables, but they should be
nice from a maintainability/debugging standpoint.
Also available within the code block is the variable specified by
numvar. Before we continue, let us look at an example:
\begin{verbatim}
<psp:do name="name" numvar="$index">
$val_hash{$index}->{name} = $field->value();
</psp:do>
\end{verbatim}
For every field present, the group iteration index of that field will
be used to key an anonymous hash. The string name will then key the
value of the field name corresponding to the group iteration.
So, what do we mean by group iteration? When dynamic fields are
created, the first one to be created is the first group iteration, the
second the second, etc., etc.
Of course, the astute reader is now wondering what fields are present.
Under MIC 2.1 and greater, the fields present are those which are
needed to be displayed, those which have changed from their initial
values (those fields which have had user input which is not exactly
equal to the original value), those that are in error, or those that
are members of a group where some field in that group meets the
previous criteria.
These facts are often exploited in the use of a psp:do. For an example,
see \ref{sample code-psp:do}.
\subsection{psp:dynamicdisplay}
\subsubsection{Syntax}
\tag{psp:dynamicdisplay}{name=\code{group name} [numvar=\code{index name}]
}
{deprecated psp code}
\subsubsection{Description}
psp:dynamicdisplay defines a set of psp-code to be repeated until a
valid stop condition is met. This may be either:
\begin{itemize}
\item The loop has iterated a number of time equal to the number
defined by the numdisplay attribute in the associated psp:group
tag\footnote{future versions of PSP will allow one to overide the
default specified in the psp:group with a value specified in the
psp:dynamicdisplay.}
\item There are no more valid pre-defined fields to be displayed and
no the group is not marked for dummyok
\item The total number of fields displayed for all calls to this page
is equal to the number defined by the maxnum attribute
\end{itemize}
The optional numvar parameter will allow one to specify the name of an
index variable for use within the psp:dynamicdisplay block. This
variable will hold the index of the current iteration. If not
specified, there is no default and the value will simply not
exist. The recommended name for this variable is ``\$index.''
\subsubsection{A Word about Using}
Note that when using a psp:dynamicdisplay with psp:rollover and
psp:rollback tags, the page must be able to be called again and again
in succession. Each time, any new datatypes created are added to the
fieldspace and remembered. Only the proper ones, however, are
displayed.
\subsection{psp:rollover, psp:rollback, and psp:refresh}
\subsubsection{Syntax}
\tag{psp:rollover}{name=\code{name to associate with submits}
assocdynamic=\code{group name which this button should control}
[text=\code{text to appear on button}]}{
[$<$psp:vfield ...$>$]
[$<$psp:vpage ...$>$]
[$<$psp:vverify ...$>$]}
[$<$vpresent$>$]
The syntax for psp:rollback and psp:refresh is the same.
\subsubsection{Description}
These three tags indicate that a button should be placed at the point
the tags are placed. These buttons will have the effect of going to
the next page of the dynamic form and re-evaluating the page on which
they display after starting psp:dynamicdisplay at a new index
point. The buttons are smart in that they know whether to display
themselves or not. That is, the rollback will not display on the first
page and the rollover will not display on the last. Neither will the
rollover display if there are no more valid items to be
considered. This will happen if any of the following conditions are
met:
\begin{itemize}
\item dummyok is false and the last obj evaluated or the first obj for
the next page is undefined
\item there are no evaluated psp:inputs in the psp:display (this means
that psp:if's are potent on this condition)
\item maxnum has been reached
\end{itemize}
The assocdynamic attribute is the name of the group which this button
should cause to roll back or forward. This must be specified due to
support of nested psp:dynamics.\footnote{At the time of this writing,
nesting is only a partially tested feature with some known bugs.}
Other than that, they act much like submit buttons, and, like submit
buttons, should have the same name within a form. One can place
verification tags between the containing tags to one's delight.
\subsection{psp:indexoverride}
\subsubsection{Syntax}
\stag{psp:indexoverride}{test=\code{perl code} group=\code{group to override}
[previous=``true''] [steps=\code{integer}]}
\subsubsection{Description}
When test is true, then the index will either be set back to the
previous iteration (which may or may not be back a step because of the
psp:refresh tag) or back/forward a number of steps equal to the value
given. Either may be set and previous will override if both are set.
\section{Error Handling and Verification}
\label{error handling tags}
PSP's robust and flexible error handling system is one of its
most useful features. This system allows one to verify data and then
track, report and possibly correct errors. Both verification and
reporting are rather flexible and powerful, while tracking is
automatic. While the tags are discussed here, to fully understand PSP
error handling one must read \ref{error handling}.
\subsection{psp:vfield}
\subsubsection{Syntax}
\stag{psp:vfield}{name=\code{field name} [ignore=``true'']}
\subsubsection{Description}
This has the effect of saying ``when the psp:submit I am associated
with (contained by) is hit, then check this field for errors with
respect to its data type.''\footnote{Datatype is a concept used by PSP
which may be supported to varying degrees with the data encapsulators
one is using in their PSP system. The idea is that user data is
expected to be of a type, which may be something like integer, credit
card number, or free form.}
The name parameter identifies a field name within the associated
fieldspace. Since names of all fields in a given fieldspace must be
unique, PSP will know whether the field is dynamic or not. If it is
dynamic, then all instantiations of that field present at the time of
verification will be checked.
The effect is to call verify() (discussed in the cross interface
section, \ref{cross interface: fieldspace}) on the field contained
within the fieldspace. The types of errors caught here are things like
`I am supposed to be an integer... am I?' as well as parameter
limitation checks, if supported.
The optional ignore parameter will tell PSP to {\bf ignore} any
errors generated directly by this field. Furthermore, it will take the
field out of error. This is to allow for the idea that certain submits
may change the nature of what we care about and data that was
previously in error is no longer in error. Note, however, that any
verification will override ignore directives, so combining a psp:vfield
tag with an ignore directive and a vinistantiated tag will have the
same effect as if the psp:vfield tag were not there at all.
When we say ``generated directly,'' we mean generated by a psp:vfield,
psp:vcurrent or psp:vinstantiated. If the field is in error through the agency
of an arbitrary verification (kicked off with psp:vverify), then it will
remain in error for that reason, even if the ignore directive is
called.
\subsection{psp:vpage}
\subsubsection{Syntax}
\stag{psp:vpage}{name=\code{page name}}
\subsubsection{Description}
This tag causes the named page to be reevaluated in the current
context (meaning, among other things, that any global variables will
have their current value). All fields which would be displayed (for
input or display only) will be verified.
Realize that any pages specified by a psp:vpage tag will essentially be
re-run. If this is a concern, specify fields individually or use
psp:vinstantiated. In fact, it has been found that it practice,
psp:vinstantiated works better and does whan is wanted; be cognizant of
the fact that the fields checked by each method are not the same.
As an example of the above, if on the first run through af a page, we
increment a global var, then it will be the new, incremented value
when the page is re-evaluated for psp:vpage. This will also have the
effect or incrementing the value again!
Note that there is no ignore attribute possible with psp:vpage. This is
because psp:vpage is being depricated.
\subsection{psp:vverify}
\subsubsection{Syntax}
\stag{psp:vverify}{name=\code{verify name} [ignore=``true'']}
\subsubsection{Description}
This causes the test specified by the named verify to be run, and if
it returns false, then the result of the PSP-HTML associated with the
verify will be associated with the error-reporting mechanisms.
The optional ignore tag will remove the verification from error and
all fields in error due to the verification. It will not remove direct
field errors, though.
\subsection{psp:vinstantiated}
\subsubsection{Syntax}
\stag{psp:vinstantiated}{[ignore=``true'']}
\subsubsection{Description}
This causes all the fields which are instantiated at the moment to be
verified.\footnote{That is all fields needed for the current page, all
fields in error, all fields which have changed, and all fialds being
carried along.} In general, this is usually the preferred alternative
to psp:vpage as it will generally have the desired affect without the side
effects of psp:vpage.
The ignore attribute has the effect of removing all field errors, but
not verification errors. To remove all errors, use psp:vignore.
\subsection{psp:vcurrent}
\subsubsection{Syntax}
\stag{psp:vcurrent}{[ignore=``true'']}
\subsubsection{Description}
This tag has the effect of requesting a verification of all fields
that have the potential of having been changed. It is, thus, different
from psp:vinstantiated in that past fields that may be hanging around due
to change or what not, will not be verified. This may be the more
efficient of the two to use, if it does what is needed.
The ignore directive will remove all fields from error that may have
changed in the current form. Note that it will not effect errors due
to verifications.
\subsection{psp:vignore}
\subsubsection{Syntax}
\stag{psp:vignore}{}
\subsubsection{Description}
This tag will obliterate all errors, both field and verification.
\chapter{Sample Code}
Note that portions of the code presented in this section are dependant
on interfaces which are outside the scope of this document (e.g., the
arbitrary code within a psp:define). Thus, the exact syntax of the code
that any given program may contain may differ. An effort has, however,
been made to make the examples clear as to their meaning.
\section{Embedded Logic}
\label{sample code-embedded logic}
\noindent Consider the following snippets:
\noindent{\it from login.html:}
\begin{verbatim}
...
Please enter your user name and password:
<form action="check_password.psp">
User Name:<input name="username" type="text"><br>
Password:<input name="password" type="password"><br>
<input name="login_submit" type="submit" value="Submit">
</form>
...
\end{verbatim}
\pagesep\\
\noindent{\it from check_password.psp:}
\begin{verbatim}
...
<psp:if test="check_login($cgi->param('username'),
$cgi->param('password'))">
return Pile::example::index($cgi);
</psp:if>
<psp:else>
return Pile::example::login($cgi);
</psp:else>
...
\end{verbatim}
\pagesep\\
The above example illustrates the use of simple embedded
logic, calling pages as functions, and the use of HTML forms within
PSP (which is trivial). In the above example, we are using a direct
CGI call to check the value of the fields, which is discouraged in
general, but may be appropriate in certain cases (see \ref{style: psp
vs cgi data}. The above, in particular, is a bad example in that
respect as far as the style guidlines are concerned.
On the basis of the result of the function check_login, we either
return the index page or return to the login page. Note that the
browser will believe that the page being displayed is called
`check_login.psp,' but since all three of the pages of concern are at
the same directory level, this is okay as far as functionality is
concerned.
\section{psp:do}
\label{sample code-psp:do}
\noindent Consider the following code snippets:
\noindent{\it from employee_entry.fs:}
\begin{verbatim}
...
<psp:group name="employees" obj="$obj"
numvar="$index" numdisplay="10" dummyok="true">
<psp:define name="eid" data="employee_id"
type="text">
get_employee_id($index);
</psp:define>
<psp:define name="name" data="text"
type="text">
get_employee_name($index);
</psp:define>
<psp:define name="ssn" data="ssn" type="text">
get_employee_ssn($index);
</psp:define>
<psp:define name="salary" data="uscurrency"
type="text">
get_employee_salary($index);
</psp:define>
</psp:group>
...
\end{verbatim}
\pagesep\\
\noindent{\it from enter.html:}
\begin{verbatim}
...
<form action="overridden"
psp:fieldspace="employee_entry">
<psp:dynamicdisplay>
<hr>
Name: <psp:display name="name">
SSN: <psp:display name="ssn"><br>
Salary: <psp:display name="salary><br>
</psp:dynamicdisplay>
<psp:rollback name="entry_submit"
assocdynamic="employees">
<vinstatiated>
</psp:rollback>
<psp:rollover name="entry_submit"
assocdynamic="employees">
<vinstantiated>
</psp:rollover>
<br>
<psp:submit name="entry_submit" value="Submit"
goto="process">
<vinstantiated>
</psp:submit>
<input type="submit" name="entry_submit"
value="Submit">
</form>
...
\end{verbatim}
\pagesep\\
\noindent{\it from process.html:}
\begin{verbatim}
...
<psp:Perl>
my %new_employees;
</psp:Perl>
<form action="none" psp:fieldspace="employee_entry">
<psp:do name="eid" numvar="$index">
$new_employees{$index}->{id}->{$field->value()};
</psp:do>
<psp:do name="name" numvar="$index">
$new_employees{$index}->{name}->{$field->value()};
</psp:do>
<psp:do name="ssn" numvar="$index">
$new_employees{$index}->{ssn}->{$field->value()};
</psp:do>
<psp:do name="salary" numvar="$index">
$new_employees{$index}->{salary}->{$field->value()};
</psp:do>
</form>
<psp:list iterator="$index" list="keys %new_employees">
<psp:Perl>
my $new_id;
if ($new_employees{$index}->{id}) {
$new_id = new_employee_id();
$new_employees{$index}->{id}->{$new_id};
add_employee($new_employees{$index});
}
else {
update_employee($new_employees{$index});
}
</psp:Perl>
</psp:list>
...
\end{verbatim}
\pagesep\\
The above code is meant to take new employee data and store it in a
database as well as display and update existing employee data. The
defualt code blocks will fill in the first n employees (where n is the
number of existing employees). Assume that the defualt code block
returns null when we go off the first n employees, leaving blank text
boxes.
Let us assume that we have strict error checking on all the data so
that we know when we get to the processing page, it is all good
data. That is, assume there is a lot of error checking and reporting
that is not shown. Part of this error checking is to ensure that if
one field is filled out, then the other two are.
Note that because of the instantiation rules of PSP, to change this
form from only adding new employees, to adding and updating means that
we only need to add 6 lines in the field space file and 6 in the
process.html (all of which are shown). When we get to the process
page, we blindly load up everything that is there, only noting the
state of the eid field at the very end. This is okay, since none of
the blank fields or unchanged fields for existing customers will be
instantiated, so all our data on the processing page are interesting.
So, we then psp:do over the fields, building up a hash, which is then
passed into the add_employee function, which takes the information
found in the hash reference and adds it to database or the
update_employee function.
\section{Multiple Values}
\label{sample code-multiple values}
\noindent Consider the following code snippets:
\noindent{\it from multiple.fs:}
\begin{verbatim}
...
<psp:define name="selector" data="text"
type="select_box">
daniel;;
{
$field->display({multiple => 3}};
$field->set_possible_hash({zane => Zane,
daniel => Daniel,
charles => Charles,
sam => Sam,
micheal => Michael});
}
</psp:define>
...
\end{verbatim}
The above creates a field that will display itself as a select box
with the multiple param set to three and the items as indicated in the
anonymous hash passed to set_possible. Daniel (value daniel) will be
highlighted/selected initially.\\
\pagesep\\
\noindent{\it from select.html:}
\begin{verbatim}
<html><body>
<form action="overridden" psp:fieldspace="multiple">
Please select everyone to invite to your party:<br>
<psp:input name="selector"><br>
<input type="submit" name="select_submit"
value="Submit">
<psp:submit name="select_submit" value="Submit"
goto="display">
</psp:submit>
</form>
</html></body>
\end{verbatim}
\pagesep\\
\noindent{\it from display.html:}
\begin{verbatim}
<html><body>
<form action="none" psp:fieldspace="multiple">
The revelers are:<br>
<psp:list iterator="$reveler"
list="$fs->get_field(`selector')->value()">
<b>$reveler</b><br>
</psp:list>
<input type="submit" name="multiple_submit"
value="Revise">
<psp:submit name="multiple_submit" value="Revise"
goto="select">
<input type="submit" name="multiple_submit"
value="Done">
<psp:submit name="multiple_submit" value="Done"
goto="done">
</form>
</body></html>
\end{verbatim}
\pagesep\\
If we point a user to the select page, they will get a 3-row select
box with the name `Daniel' highlighted. On this page, the field will
contain the single value, `daniel.' Suppose the user selects
`Charles,' `Sam,' and `Michael' (poor Zane) and hits submit. The will
then go the display page and be presented with the names `Daniel,'
`Charles,' `Sam,' and `Michael'\footnote{in no particular
order}. Remember that `Daniel' was never deselected. The fieldspace
now contains `daniel,' `michael,' `charles,' and `sam.' They then hit
the `Revise' button and are taken back the revise page. The fieldspace
contains all value but `zane' and the select box has all names
selected except `Zane.' The user then selects `Zane' and deselects
`Daniel' and resubmits. Now, we behave as before with `Zane' and
`zane' substituted for `Daniel' and `daniel.' Happy with the
arrangements, the user then hits `Done' and it does its trivial thing.
\section{Conditional Verifies}
\label{sample code-conditinal verifies}
\end{document}
|