cvs: pearweb /include html_form.php pear-prepend.php /public_html add-author.php add-package.php authors.php index.php list-authors.php
/public_html/doc pear.html pear.xml

From: Date: Mon, 17 Jul 2000 22:54:39 +0000
Subject: cvs: pearweb /include html_form.php pear-prepend.php /public_html add-author.php add-package.php authors.php index.php list-authors.php
/public_html/doc pear.html pear.xml
Groups: php.pear 
Request: Send a blank email to php-pear+get-143@lists.php.net to get a copy of this message
ssb Mon Jul 17 15:54:39 2000 EDT Added files: /pearweb/include html_form.php /pearweb/public_html authors.php Modified files: /pearweb/include pear-prepend.php /pearweb/public_html add-author.php add-package.php index.php list-authors.php /pearweb/public_html/doc pear.html pear.xml Log: * new class: Author (subclasses DB_storage) * new class: HTML_Form (should go into its own package when it's one) Index: pearweb/include/pear-prepend.php diff -u pearweb/include/pear-prepend.php:1.2 pearweb/include/pear-prepend.php:1.3 --- pearweb/include/pear-prepend.php:1.2 Sun Feb 27 20:15:09 2000 +++ pearweb/include/pear-prepend.php Mon Jul 17 15:54:38 2000 @@ -1,23 +1,9 @@ <?php -define('PEAR_CRED_DOWNLOAD', 0); -define('PEAR_CRED_UPLOAD', 1); -define('PEAR_CRED_ADMIN', 2); +require_once "DB.php"; +require_once "DB/storage.php"; -/* -function use($package) -{ - global $USED_PACKAGES; - if ($USED_PACKAGES[$package]) { - return; - } - if (@include($package . '.php')) { - $USED_PACKAGES[$package] = true; - } else { - die("Unable to load package \"$package\"!"); - } -} -*/ +$DSN = "mysql://pear@localhost/pear"; function pageHeader($title = "PEAR: PHP Extension and Add-on Repository", $style = false) @@ -43,60 +29,28 @@ } print "</BODY></HTML>\n"; } - -function formMultipleInputRow($data) { - reset($data); - while (list($var, $title) = each($data)) { - global $$var; - formInputRow($title, $var, $$var); - } -} - -function formInputCell($name, $default = '', $size = 20) { - print " <TD><INPUT NAME=\"$name\" VALUE=\"$default\" SIZE=\"$size\"></TD>\n"; -} - -function formInputRow($title, $name, $default = '', $size = 20) { - print " <TR>\n"; - print " <TH ALIGN=\"right\">$title</TH>"; - formInputCell($name, $default, $size); - print " </TR>\n"; -} -function formCheckbox($name, $default = false) { - print "<INPUT TYPE=\"checkbox\" NAME=\"$name\""; - if ($default && $default != 'off') { - print " CHECKED"; +function validate($entity, $field, $value) { + switch ("$entity/$field") { + case "authors/handle": + if (!preg_match('/^[a-z][a-z0-9]+$/i', $value)) { + return false; + } + break; + case "authors/name": + if (!$value) { + return false; + } + break; + case "authors/email": + if (!preg_match('/[a-z0-9_\.\+%]@[a-z0-9\.]+\.[a-z]+$', $email)) { + return false; + } + break; } - print ">"; -} - -function formCheckboxCell($name, $default = false) { - print " <TD>"; - formCheckbox($name, $default); - print "</TD>\n"; + return true; } -function formCheckboxRow($title, $name, $default = false) { - print " <TR>\n"; - print " <TH ALIGN=\"right\">$title</TH>"; - formCheckboxCell($name, $default); - print " </TR>\n"; -} - -function formSubmit($title = 'Submit Changes') { - print "<INPUT TYPE=\"submit\" VALUE=\"$title\">"; -} - -function formSubmitRow($title = 'Submit Changes') { - print " <TR>\n"; - print " <TD>&nbsp</TD>\n"; - print " <TD>"; - formSubmit($title); - print "</TD>\n"; - print " </TR>\n"; -} - function invalidHandle($handle) { if (preg_match('/^[a-z]+-?[a-z]+$/i', $handle)) { return false; @@ -125,27 +79,52 @@ return 'invalid URL'; } -class Author { - var $handle, $password, $name, $email, $homepage, $created, - $homepage, $modified, $createdby, $showemail, $registered, - $credentials, $authorinfo; - function Author() { - +class Author extends DB_storage +{ + function Author(&$dbh, $handle = false) { + $this->DB_storage("authors", "handle", &$dbh); + if ($handle) { + $this->setup($handle); + } } } -function add_author(&$dbh, $handle, $name, $email, $homepage, $createdby, - $showemail, $credentials, $authorinfo) +function authReject($realm, $login_file = false) { - $query = 'INSERT INTO authors (handle,password,name,email,homepage,'. - 'created,modified,createdby,showemail,registered,credentials,'. - 'authorinfo) VALUES(?,?,?,?,?,?,?,?,?,?,?,?)'; - $stmt = $dbh->prepare($query); - // XXX not finished - return $dbh->execute($stmt, array($handle, $passwd, $name, $email, - $homepage, $created, $modified, - $modifiedy, $showemail, $registered, - $credentials, $authorinfo)); + Header("HTTP/1.0 401 Unauthorized"); + Header("WWW-authenticate: basic realm=\"$realm\""); + if ($login_file) { + include($login_file); + } else { + print "access denied"; + } + exit; +} + +function authRequire($level = 0) +{ + global $PHP_AUTH_USER, $PHP_AUTH_PW, $DSN, $dbh, $authorObject; + + $authorObject = new Author(&$dbh, strtoupper($PHP_AUTH_USER)); + if (DB::isError($authorObject) || md5($PHP_AUTH_PW) != $authorObject->password) { + if ($level > 0) { + authReject("PEAR administrator"); + } else { + authReject("PEAR maintainer"); + } + } +} + +if (!is_object($dbh)) { + $dbh = DB::connect($DSN); +} +if (DB::isError($dbh)) { + pageHeader("Database Error"); + print "DB::connect error: "; + print DB::errorMessage($dbh); + print "<BR>\n"; + pageFooter(); + exit; } ?> Index: pearweb/public_html/add-author.php diff -u pearweb/public_html/add-author.php:1.2 pearweb/public_html/add-author.php:1.3 --- pearweb/public_html/add-author.php:1.2 Sun Feb 27 20:15:09 2000 +++ pearweb/public_html/add-author.php Mon Jul 17 15:54:38 2000 @@ -1,36 +1,106 @@ <?php -pageHeader("PEAR: Add an author"); +require_once "html_form.php"; +authRequire(); + +$display_form = true; + +function displayError($msg) +{ + global $errorMsg; + $errorMsg .= "<FONT COLOR=\"#CC0000\">$msg</FONT><BR>\n"; +} + +$jumpto = "handle"; + +do { + if ($submit) { + $required = array("handle", "name", "email"); + while (list($i, $field) = each($required)) { + if (!$$field) { + displayError("Please enter $field"); + $jumpto = $field; + break 2; + } + } + + if (!preg_match("/^[a-z][a-z0-9]+$/i", $handle)) { + displayError("Handle must start with a letter and contain ". + "only letters and digits."); + break; + } + + if ($password != $password2) { + displayError("Passwords did not match"); + $password = $password2 = ""; + break; + } + + if (!$password) { + displayError("Empty passwords not allowed"); + break; + } + + $handle = strtoupper($handle); + $obj = new Author(&$dbh); + $err = $obj->insert($handle); + if (DB::isError($err)) { + displayError("$handle: " . DB::errorMessage($err)); + $jumpto = "handle"; + break; + } + + $display_form = false; + $obj->name = $name; + $obj->email = $email; + $obj->homepage = $homepage; + $obj->showemail = (bool)$showemail; + $obj->admin = (bool)$admin; + $obj->password = md5($password); + } +} while (0); + +if ($display_form) { + + pageHeader("PEAR: Add an author"); + ?> <H1>Add an author</H1> <FORM ACTION="<?php echo $PHP_SELF; ?>" METHOD="POST"> <TABLE> <?php - -formInputRow("Handle", "handle", '', 10); -formInputRow("Name", "name", '', 40); -formInputRow("Email", "email", '', 40); -formInputRow("Homepage", "homepage", '', 40); - -formCheckboxRow("Show email?", "showemail", '', 40); - -print " <TR>\n"; -print " <TH ALIGN=\"right\">Credentials</TH>\n"; -print " <TD>\n "; -formCheckbox('cred_upload', true); -print " contributor<BR>\n "; -formCheckbox('cred_admin'); -print " administrator<BR>\n"; -print " </TD>\n"; -print " </TR>\n"; -formSubmitRow(); + if ($errorMsg) { + print " <TR>\n"; + print " <TD>&nbsp;</TD>\n"; + print " <TD><B>$errorMsg</B></TD>\n"; + print " </TR>\n"; + } + + $width = 60; + + formInputRow("Handle", "handle", $handle, 12); + formInputRow("Name", "name", $name, $width); + formInputRow("Email", "email", $email, $width); + formInputRow("Homepage", "homepage", $homepage, $width); + formCheckboxRow("Show Email Address?", "showemail", (bool)$showemail); + formCheckboxRow("Administrator?", "admin", (bool)$admin); + formPasswordRow("Password", "password", $password); + formTextareaRow("More info", "info", '', $width, 5); + formSubmitRow("Add Author"); ?></TABLE> </FORM> <?php + + if ($jumpto) { + print "<SCRIPT LANGUAGE=\"JavaScript\">\n<!--\n"; + print "document.forms[0].$jumpto.focus();\n"; + print "\n// -->\n</SCRIPT>\n"; + } + pageFooter(); -pageFooter(); +} ?> Index: pearweb/public_html/add-package.php diff -u pearweb/public_html/add-package.php:1.1 pearweb/public_html/add-package.php:1.2 --- pearweb/public_html/add-package.php:1.1 Sun Dec 12 04:44:31 1999 +++ pearweb/public_html/add-package.php Mon Jul 17 15:54:38 2000 @@ -1,13 +1,30 @@ <?php +$t1 = microtime(); + +include_once "html_form.php"; + +$t2 = microtime(); + pageHeader("PEAR: Add a package"); -?> -<FORM ACTION="<?php echo $PHP_SELF; ?>" METHOD="POST"> +$domains = $dbh->getAssoc("SELECT domain,domain FROM domains"); +$domains[""] = "[root]"; -</FORM> -<?php +$form = new HTML_Form($PHP_SELF, "POST"); +$form->addText("name", "Name", ""); +$form->addHidden("hidden1", "foo"); +$form->addHidden("hidden2", "bar"); +$form->addSelect("domain", "Domain", &$domains, '', 1, 'Select Domain'); +$form->addSubmit(); +$form->display(); pageFooter(); + +$t3 = microtime(); + +print "t1=$t1<br>\n"; +print "t2=$t2 (".((double)$t2-(double)$t1).")<br>\n"; +print "t3=$t3 (".((double)$t3-(double)$t2).")<br>\n"; ?> Index: pearweb/public_html/index.php diff -u pearweb/public_html/index.php:1.3 pearweb/public_html/index.php:1.4 --- pearweb/public_html/index.php:1.3 Sun Feb 27 20:17:53 2000 +++ pearweb/public_html/index.php Mon Jul 17 15:54:38 2000 @@ -5,13 +5,15 @@ print "<H1>PEAR: PHP Extension and Add-on Repository</H1>\n"; if ($SERVER_NAME != "pear.php.net") { - print "<A HREF=\"add-package.php\">ADD NEW PACKAGE</A><BR>\n"; - print "<A HREF=\"add-author.php\">ADD NEW AUTHOR</A><BR>\n"; - print "<A HREF=\"list-packages.php\">LIST PACKAGES</A><BR>\n"; - print "<A HREF=\"list-authors.php\">LIST AUTHORS</A><BR>\n"; - print "<A HREF=\"domains.php\">DOMAIN ADMINISTRATION</A><BR>\n"; + print "<A HREF=\"authors.php\">AUTHORS</A><BR>\n"; + print "<A HREF=\"packages.php\">PACKAGES</A><BR>\n"; + print "<A HREF=\"domains.php\">DOMAINS</A><BR>\n"; } print "<H2><A HREF=\"doc/\">Documentation</A></H2>\n"; + +$dbh = DB::connect("mysql://pear@localhost/pear"); +$ssb = new Author(&$dbh, "SSB"); +print $ssb->toString(); pageFooter(); Index: pearweb/public_html/list-authors.php diff -u pearweb/public_html/list-authors.php:1.2 pearweb/public_html/list-authors.php:1.3 --- pearweb/public_html/list-authors.php:1.2 Sun Feb 27 20:15:09 2000 +++ pearweb/public_html/list-authors.php Mon Jul 17 15:54:38 2000 @@ -1,7 +1,5 @@ <?php -use("DB"); - pageHeader("PEAR: List packages"); $dbh = DB::Connect("mysql://pear@localhost/pear"); Index: pearweb/public_html/doc/pear.html diff -u pearweb/public_html/doc/pear.html:1.3 pearweb/public_html/doc/pear.html:1.4 --- pearweb/public_html/doc/pear.html:1.3 Mon Feb 28 08:19:05 2000 +++ pearweb/public_html/doc/pear.html Mon Jul 17 15:54:39 2000 @@ -24,6 +24,10 @@ ><H3 CLASS="author" >Stig Bakken</H3 +><SPAN +CLASS="releaseinfo" +>&#13; + <BR></SPAN ><DIV CLASS="revhistory" ><TABLE @@ -41,10 +45,10 @@ ><TR ><TD ALIGN="LEFT" ->Revision $Revision: 1.3 $</TD +>Revision $Revision: 1.4 $</TD ><TD ALIGN="LEFT" ->$Date: 2000/02/28 16:19:05 $</TD +>$Date: 2000/07/17 22:54:39 $</TD ><TD ALIGN="LEFT" >Revised by: $Author: ssb $</TD @@ -60,11 +64,6 @@ ><HR></DIV ><P >PEAR is dedicated to Malin Bakken, born 1999-11-21.</P -><P ->&#13; This document is incomplete. For now it only contains a brief - description of PEAR and "Coding Rules and Guidelines". The rules - and guidelines are initial suggestions, and are open for discussion. - </P ><DIV CLASS="section" ><HR><H1 @@ -96,7 +95,7 @@ ></H1 ><P >&#13; This section describes some rules that are meant to make PEAR code - available to as many users as possible. If you plan to contribute + available to as many users as possible. If you want to contribute to PEAR, please read this section carefully and follow these rules, or someone will yell at you. :-) </P @@ -113,9 +112,22 @@ CLASS="filename" >.php</TT > for - all files with PHP code (files that when included don't output - anything, but only define variables, constants, functions or - classes). + all files with PHP code. + <DIV +CLASS="note" +><BLOCKQUOTE +CLASS="note" +><P +><B +>Note: </B +> + It is important that your files do not output anything, so watch + those extra linefeeds at the end of the files (no more than + one!) + </P +></BLOCKQUOTE +></DIV +> </P ><P >&#13; A related set of one or more classes and functions in PEAR are @@ -128,8 +140,10 @@ this structure maps 1:1 down to the file system, it is conceptually not a filesystem structure. The structure is based on the developer's view when writing code, which is the parameters - to "use" or "import" (PEAR is currently using "include" though). - An example: + to <B +CLASS="function" +>use</B +>. An example: <DIV CLASS="informalexample" ><P @@ -162,20 +176,41 @@ ><HR><H3 CLASS="section" ><A -NAME="pear-funcnames" ->Function and Method Names</A +NAME="pear-pkgnames" +>Package Names</A ></H3 ><P ->&#13; Functions (not methods), should be named with underscores, like - this: <TT -CLASS="function" ->my_function</TT ->. Methods should be named - with initial lower-case studlycaps like this: +>&#13; The definition of a package in PEAR is file defining one "public" + class and possible several "private" ones. Although PHP doesn't + have the notion of public classes, PEAR uses this concept. A + public class is a class that is available to other packages or + the user, a private class is a class that is internal to that + package, and that the PHP programmer will normally not deal with + directly. + </P +><P +>&#13; All PEAR package files should use the suffix <TT +CLASS="filename" +>.php</TT +>. The class name is the file name + without the <TT +CLASS="filename" +>.php</TT +> suffix. + </P +><P +>&#13; For example, the package <SPAN +CLASS="systemitem" +>DB/mysql</SPAN +> would have its code in a + file called <TT +CLASS="filename" +>mysql.php</TT +> in a directory called <TT -CLASS="function" ->myFunction</TT ->. +CLASS="filename" +>DB</TT +> in a directory in PHP's include path. </P ></DIV ><DIV @@ -187,21 +222,138 @@ >Class Names</A ></H3 ><P ->&#13; Class names are not as straightforward. PEAR should never have - name conflicts among its classes (and preferably ditto for - functions, but that can be solved using static methods in - classes). Since PHP doesn't have packages or name spaces yet, we - need to "brute force" it. The solution is currently not too - pretty, maybe it serves as inspiration for the Zend authors to - implement name spaces :-). +>&#13; PEAR classes should never have name conflicts. Since PHP doesn't + have packages or name spaces yet, it is necessary to enforce a + class naming convention that provides a "poor man's name spaces". + Hopefully this will serve as an inspiration for the Zend authors + to implement name spaces :-). </P ><P >&#13; The basic class name rule is to use the package name and - substitute slashes with underscores. The package "DB/mysql" has - its code in the file "DB/mysql.php" and defines a class called - "DB_mysql". + substitute slashes with underscores. The package <SPAN +CLASS="systemitem" +>DB/mysql</SPAN +> has its code in the file + <TT +CLASS="filename" +>DB/mysql.php</TT +> and defines a class called + <TT +CLASS="classname" +>DB_mysql</TT +>. + </P +></DIV +><DIV +CLASS="section" +><HR><H3 +CLASS="section" +><A +NAME="pear-functions" +>Functions</A +></H3 +><P +>&#13; At this time, PEAR does not support plain functions. The reason + for this is that we want to avoid name space problems where + different packages define functions with the same name. One + solution could be prefixing each function's name with its package + name, but then encapsulating the functions in classes is better. </P +><P +>&#13; When PHP gets support for namespaces (some time _after_ the 4.0 + release), PEAR will support plain functions. + </P +><P +>&#13; If you have a function you want to make available in a PEAR + package, make a class based on the package name (Foo/Bar -&#62; + Foo_Bar), and add the function as a method there. Example: + <DIV +CLASS="informalexample" +><P +></P +><TABLE +BORDER="0" +BGCOLOR="#E0E0E0" +WIDTH="100%" +><TR +><TD +><PRE +CLASS="programlisting" +> 1&nbsp; + 2&nbsp;Header("Last-Modified: " . HTTP::Date(getlastmod())); + 3&nbsp;</PRE +></TD +></TR +></TABLE +><P +></P +></DIV +> + </P +></DIV +><DIV +CLASS="section" +><HR><H3 +CLASS="section" +><A +NAME="pear-funcnames" +>Method Names</A +></H3 +><P +>&#13; Methods should be named with initial lower-case studlycaps like + this: <B +CLASS="function" +>myFunction()</B +>. + </P +></DIV +></DIV +><DIV +CLASS="section" +><HR><H2 +CLASS="section" +><A +NAME="AEN63" +>Variable Names</A +></H2 +><P +>&#13; Global variables visible to the user should be prefixed with the + package name with "/" substituted with "_" (like for class names) + and an underscore. If you need global variables that are not to + be "visible" to the user, prefix the whole thing with an + underscore. + </P +><P +>&#13; Example (let's say this package is Gah/Zonk): + <DIV +CLASS="informalexample" +><P +></P +><TABLE +BORDER="0" +BGCOLOR="#E0E0E0" +WIDTH="100%" +><TR +><TD +><PRE +CLASS="programlisting" +> 1&nbsp; + 2&nbsp;&#60;?php + 3&nbsp; + 4&nbsp;$Gah_Zonk_errorcodes = array( -1 =&#62; "This error", + 5&nbsp; -2 =&#62; "That error" ); + 6&nbsp;$_Gah_Zonk_cache = array(); + 7&nbsp; + 8&nbsp;?&#62; + 9&nbsp;</PRE +></TD +></TR +></TABLE +><P +></P ></DIV +> + </P ></DIV ><DIV CLASS="section" @@ -209,25 +361,21 @@ CLASS="section" ><A NAME="pear-errors" ->Returning Errors</A +>Errors</A ></H2 ><P ->&#13; Your code should <I -CLASS="emphasis" ->never</I -> use - <TT +>&#13; Never use <B CLASS="function" ->exit</TT -> or <TT +>exit()</B +> or <B CLASS="function" ->die</TT -> if it - encounters an error. This would make developers using your code - unable to catch these errors, handle them or even display their - own error message. As far as possible, use some way of giving - errors back to the caller, even if it is just a boolean return - value. +>die()</B +> if + your PEAR package encounters an error. Doing this generally makes + peoples lives miserable when they try handling errors nicely. Try + to always provide a way of telling whether something went wrong + and what, be it as simple as returning an error code, or something + more fancy. </P ></DIV ><DIV @@ -236,13 +384,13 @@ CLASS="section" ><A NAME="pear-options" ->Depending on Optional Features</A +>Optional PHP Features</A ></H2 ><P ->&#13; PEAR code is meant to be useable with all (reasonable) - configurations of PHP. Since PHP is very configurable and many of - its features are optional, this requires extra attention from you - as a PEAR author to make sure that your code works with different +>&#13; PEAR code should be useable with all (reasonable) configurations + of PHP. Since PHP is very configurable and many of its features + are optional, this requires extra attention from you as a PEAR + author to make sure that your code works with different configurations. </P ><P @@ -258,13 +406,23 @@ CLASS="informalexample" ><P ></P +><TABLE +BORDER="0" +BGCOLOR="#E0E0E0" +WIDTH="100%" +><TR +><TD ><PRE CLASS="programlisting" ->&#13;// If magic_quotes_gpc is enabled, remove those slashes. -if (ini_get("magic_quotes_gpc")) { - $arg = stripslashes($arg); -} -</PRE +> 1&nbsp; + 2&nbsp;// If magic_quotes_gpc is enabled, remove those slashes. + 3&nbsp;if (ini_get("magic_quotes_gpc")) { + 4&nbsp; $arg = stripslashes($arg); + 5&nbsp;} + 6&nbsp;</PRE +></TD +></TR +></TABLE ><P ></P ></DIV @@ -354,40 +512,82 @@ within a function. The included file will inherit the calling code's scope: - <DIV + <TABLE +WIDTH="100%" +BORDER="0" +CELLPADDING="0" +CELLSPACING="0" +CLASS="EXAMPLE" +><TR +><TD +><DIV CLASS="example" ><P ><B >Example 1. file1.php</B ></P +><TABLE +BORDER="0" +BGCOLOR="#E0E0E0" +WIDTH="100%" +><TR +><TD ><PRE CLASS="programlisting" ->&#13;&#60;?php $myglobal = 42; ?&#62; -</PRE +> 1&nbsp; + 2&nbsp;&#60;?php $myglobal = 42; ?&#62; + 3&nbsp;</PRE +></TD +></TR +></TABLE ></DIV +></TD +></TR +></TABLE > - <DIV + <TABLE +WIDTH="100%" +BORDER="0" +CELLPADDING="0" +CELLSPACING="0" +CLASS="EXAMPLE" +><TR +><TD +><DIV CLASS="example" ><P ><B >Example 2. file2.php</B ></P +><TABLE +BORDER="0" +BGCOLOR="#E0E0E0" +WIDTH="100%" +><TR +><TD ><PRE CLASS="programlisting" ->&#13;&#60;?php - -class Foo { - function Foo($arg) { - if ($arg == 42) { - include("file1.php"); - } - } -} - -?&#62; -</PRE +> 1&nbsp; + 2&nbsp;&#60;?php + 3&nbsp; + 4&nbsp;class Foo { + 5&nbsp; function Foo($arg) { + 6&nbsp; if ($arg == 42) { + 7&nbsp; include("file1.php"); + 8&nbsp; } + 9&nbsp; } + 10&nbsp;} + 11&nbsp; + 12&nbsp;?&#62; + 13&nbsp;</PRE +></TD +></TR +></TABLE ></DIV +></TD +></TR +></TABLE > </P ><P Index: pearweb/public_html/doc/pear.xml diff -u pearweb/public_html/doc/pear.xml:1.4 pearweb/public_html/doc/pear.xml:1.5 --- pearweb/public_html/doc/pear.xml:1.4 Mon Feb 28 08:18:47 2000 +++ pearweb/public_html/doc/pear.xml Mon Jul 17 15:54:39 2000 @@ -10,10 +10,18 @@ <surname>Bakken</surname> </author> </authorgroup> + <releaseinfo> + <comment> + This document is incomplete. For now it only contains a brief + description of PEAR and "Coding Rules and Guidelines". The rules + and guidelines are initial suggestions, and are open for + discussion. + </comment> + </releaseinfo> <revhistory> <revision> - <revnumber>$Revision: 1.4 $</revnumber> - <date>$Date: 2000/02/28 16:18:47 $</date> + <revnumber>$Revision: 1.5 $</revnumber> + <date>$Date: 2000/07/17 22:54:39 $</date> <authorinitials>$Author: ssb $</authorinitials> </revision> </revhistory> @@ -21,12 +29,6 @@ <simpara>PEAR is dedicated to Malin Bakken, born 1999-11-21.</simpara> - <simpara> - This document is incomplete. For now it only contains a brief - description of PEAR and "Coding Rules and Guidelines". The rules - and guidelines are initial suggestions, and are open for discussion. - </simpara> - <section id="pear-whatis"> <title>What is PEAR?</title> <simpara> @@ -48,7 +50,7 @@ <title>Coding Rules and Guidelines</title> <simpara> This section describes some rules that are meant to make PEAR code - available to as many users as possible. If you plan to contribute + available to as many users as possible. If you want to contribute to PEAR, please read this section carefully and follow these rules, or someone will yell at you. :-) </simpara> @@ -56,12 +58,16 @@ <section id="pear-names"> <title>Naming Conventions</title> - <simpara> + <para> Use the extension <filename role="extension">.php</filename> for - all files with PHP code (files that when included don't output - anything, but only define variables, constants, functions or - classes). - </simpara> + all files with PHP code. + <note> + <simpara> + It is important that your files do not output anything, so watch + those linefeeds at the end of files (no more than one!) + </simpara> + </note> + </para> <para> A related set of one or more classes and functions in PEAR are @@ -75,8 +81,7 @@ this structure maps 1:1 down to the file system, it is conceptually not a filesystem structure. The structure is based on the developer's view when writing code, which is the parameters - to "use" or "import" (PEAR is currently using "include" though). - An example: + to <function role="statement">use</function>. An example: <informalexample> <literallayout>DB DB/common @@ -94,56 +99,126 @@ filesystem structure, as explained above. So there. </para> - <section id="pear-funcnames"> - <title>Function and Method Names</title> + <section id="pear-pkgnames"> + <title>Package Names</title> + <simpara> + The definition of a package in PEAR is file defining one "public" + class and possible several "private" ones. Although PHP doesn't + have the notion of public classes, PEAR uses this concept. A + public class is a class that is available to other packages or + the user, a private class is a class that is internal to that + package, and that the PHP programmer will normally not deal with + directly. + </simpara> <simpara> - Functions (not methods), should be named with underscores, like - this: <function>my_function</function>. Methods should be named - with initial lower-case studlycaps like this: - <function>myFunction</function>. + All PEAR package files should use the suffix <filename + role="suffix">.php</filename>. The class name is the file name + without the <filename role="suffix">.php</filename> suffix. </simpara> + <para> + For example, the package <systemitem + role="package">DB/mysql</systemitem> would have its code in a + file called <filename>mysql.php</filename> in a directory called + <filename>DB</filename> in a directory in PHP's include path. + </para> </section> <section id="pear-classnames"> <title>Class Names</title> <para> - Class names are not as straightforward. PEAR should never have - name conflicts among its classes (and preferably ditto for - functions, but that can be solved using static methods in - classes). Since PHP doesn't have packages or name spaces yet, we - need to "brute force" it. The solution is currently not too - pretty, maybe it serves as inspiration for the Zend authors to - implement name spaces :-). + PEAR classes should never have name conflicts. Since PHP doesn't + have packages or name spaces yet, it is necessary to enforce a + class naming convention that provides a "poor man's name spaces". + Hopefully this will serve as an inspiration for the Zend authors + to implement name spaces :-). </para> <para> The basic class name rule is to use the package name and - substitute slashes with underscores. The package "DB/mysql" has - its code in the file "DB/mysql.php" and defines a class called - "DB_mysql". + substitute slashes with underscores. The package <systemitem + role="package">DB/mysql</systemitem> has its code in the file + <filename>DB/mysql.php</filename> and defines a class called + <classname>DB_mysql</classname>. </para> </section> + + <section id="pear-functions"> + <title>Functions</title> + <simpara> + At this time, PEAR does not support plain functions. The reason + for this is that we want to avoid name space problems where + different packages define functions with the same name. One + solution could be prefixing each function's name with its package + name, but then encapsulating the functions in classes is better. + </simpara> + <simpara> + When PHP gets support for namespaces (some time _after_ the 4.0 + release), PEAR will support plain functions. + </simpara> + <para> + If you have a function you want to make available in a PEAR + package, make a class based on the package name (Foo/Bar -&gt; + Foo_Bar), and add the function as a method there. Example: + <informalexample> + <programlisting> +Header("Last-Modified: " . HTTP::Date(getlastmod())); +</programlisting> + </informalexample> + </para> + </section> + + <section id="pear-funcnames"> + <title>Method Names</title> + <simpara> + Methods should be named with initial lower-case studlycaps like + this: <function>myFunction</function>. + </simpara> + </section> + </section> + + <section> + <title>Variable Names</title> + <simpara> + Global variables visible to the user should be prefixed with the + package name with "/" substituted with "_" (like for class names) + and an underscore. If you need global variables that are not to + be "visible" to the user, prefix the whole thing with an + underscore. + </simpara> + <para> + Example (let's say this package is Gah/Zonk): + <informalexample> + <programlisting> +&lt?php + +$Gah_Zonk_errorcodes = array( -1 => "This error", + -2 => "That error" ); +$_Gah_Zonk_cache = array(); + +?> +</programlisting> + </informalexample> + </para> </section> <section id="pear-errors"> - <title>Returning Errors</title> + <title>Errors</title> <simpara> - Your code should <emphasis>never</emphasis> use - <function>exit</function> or <function>die</function> if it - encounters an error. This would make developers using your code - unable to catch these errors, handle them or even display their - own error message. As far as possible, use some way of giving - errors back to the caller, even if it is just a boolean return - value. + Never use <function>exit</function> or <function>die</function> if + your PEAR package encounters an error. Doing this generally makes + peoples lives miserable when they try handling errors nicely. Try + to always provide a way of telling whether something went wrong + and what, be it as simple as returning an error code, or something + more fancy. </simpara> </section> <section id="pear-options"> - <title>Depending on Optional Features</title> + <title>Optional PHP Features</title> <simpara> - PEAR code is meant to be useable with all (reasonable) - configurations of PHP. Since PHP is very configurable and many of - its features are optional, this requires extra attention from you - as a PEAR author to make sure that your code works with different + PEAR code should be useable with all (reasonable) configurations + of PHP. Since PHP is very configurable and many of its features + are optional, this requires extra attention from you as a PEAR + author to make sure that your code works with different configurations. </simpara> <para> Index: pearweb/include/html_form.php +++ pearweb/include/html_form.php <?php // {{{ constants if (!defined("HTML_FORM_TEXT_SIZE")) { define("HTML_FORM_TEXT_SIZE", 20); } if (!defined("HTML_FORM_PASSWD_SIZE")) { define("HTML_FORM_PASSWD_SIZE", 10); } if (!defined("HTML_FORM_TEXTAREA_HT")) { define("HTML_FORM_TEXTAREA_HT", 5); } if (!defined("HTML_FORM_TEXTAREA_WT")) { define("HTML_FORM_TEXTAREA_WT", HTML_FORM_TEXT_SIZE); } // }}} class HTML_Form { // {{{ properties /** ACTION attribute of <FORM> tag */ var $action; /** METHOD attribute of <FORM> tag */ var $method; /** NAME attribute of <FORM> tag */ var $name; /** an array of entries for this form */ var $fields; /** DB_storage object, if tied to one */ var $storageObject; // }}} // {{{ constructor function HTML_Form($action, $method = 'GET', $name = '') { $this->action = $action; $this->method = $method; $this->name = $name; $this->fields = array(); } // }}} // {{{ addText() function addText($name, $title, $default, $size = HTML_FORM_TEXT_SIZE) { $this->fields[] = array("text", $name, $title, $default, $size); } // }}} // {{{ addPassword() function addPassword($name, $title, $default, $size = HTML_FORM_PASSWD_SIZE) { $this->fields[] = array("password", $name, $title, $default, $size); } // }}} // {{{ addCheckbox() function addCheckbox($name, $title, $default) { $this->fields[] = array("checkbox", $name, $title, $default); } // }}} // {{{ addTextarea() function addTextarea($name, $title, &$default, $width = HTML_FORM_TEXTAREA_WT, $height = HTML_FORM_TEXTAREA_HT) { $this->fields[] = array("textarea", $name, $title, &$default, $width, $height); } // }}} // {{{ addSubmit function addSubmit($name = "submit", $title = "Submit Changes") { $this->fields[] = array("submit", $name, $title); } // }}} // {{{ addReset() function addReset($title = "Discard Changes") { $this->fields[] = array("reset", $title); } // }}} // {{{ addSelect() function addSelect($name, $title, $entries, $default = '', $size = 1, $blank = '', $multiple = false) { $this->fields[] = array("select", $name, $title, &$entries, $default, $size, $blank, $multiple); } // }}} // {{{ addRadio() function addRadio($name, $title, $value, $default) { $this->fields[] = array("radio", $name, $title, $value, $default); } // }}} // {{{ addImage() function addImage($name, $src) { $this->fields[] = array("image", $name, $src); } // }}} // {{{ addHidden() function addHidden($name, $value) { $this->fields[] = array("hidden", $name, $value); } // }}} // {{{ start() function start($action, $method = 'GET', $name = '') { print "<FORM ACTION=\"$action\" METHOD=\"$method\""; if ($name) { print " NAME=\"$name\""; } print ">"; } // }}} // {{{ end() function end() { $fields = array(); reset($this->fields); while (list($i, $data) = each($this->fields)) { if ($data[0] == 'reset') { continue; } $name = $data[1]; } $this->displayHidden("_fields", implode(":", $fields)); print "</FORM>"; } // }}} // {{{ displayText() function displayText($name, $default = '', $size = HTML_FORM_TEXT_SIZE) { print "<INPUT NAME=\"$name\" VALUE=\"$default\" SIZE=\"$size\">"; } // }}} // {{{ displayTextRow() function displayTextRow($name, $title, $default = '', $size = HTML_FORM_TEXT_SIZE) { print " <TR>\n"; print " <TH ALIGN=\"right\">$title</TH>"; print " <TD>"; $this->displayText($name, $default, $size); print "</TD>\n"; print " </TR>\n"; } // }}} // {{{ displayPassword() function displayPassword($name, $default = '', $size = HTML_FORM_PASSWD_SIZE) { print "<INPUT NAME=\"$name\" TYPE=\"password\" VALUE=\"$default\" SIZE=\"$size\">"; } // }}} // {{{ displayPasswordRow() function displayPasswordRow($name, $title, $default = '', $size = HTML_FORM_PASSWD_SIZE) { print "<TR>\n"; print " <TH ALIGN=\"right\">$title</TH>\n"; print " <TD>"; $this->displayPassword($name, $default, $size); print " repeat: "; $this->displayPassword($name."2", $default, $size); print "</TD>\n"; print "</TR>\n"; } // }}} // {{{ displayCheckbox() function displayCheckbox($name, $default = false) { print "<INPUT TYPE=\"checkbox\" NAME=\"$name\""; if ($default && $default != 'off') { print " CHECKED"; } print ">"; } // }}} // {{{ displayCheckboxRow() function displayCheckboxRow($name, $title, $default = false) { print " <TR>\n"; print " <TH ALIGN=\"right\">$title</TH>"; print " <TD>"; $this->displayCheckbox($name, $default); print "</TD>\n"; print " </TR>\n"; } // }}} // {{{ displayTextarea() function displayTextarea($name, $default = '', $width = 40, $height = 5) { print "<TEXTAREA NAME=\"$name\" COLS=\"$width\" ROWS=\"$height\">"; print $default; print "</TEXTAREA>"; } // }}} // {{{ displayTextareaRow() function displayTextareaRow($name, $title, $default = '', $width = 40, $height = 5) { print " <TR>\n"; print " <TH ALIGN=\"right\">$title</TH>\n"; print " <TD>"; $this->displayTextarea($name, &$default, $width, $height); print "</TD>\n"; print " </TR>\n"; } // }}} // {{{ displaySubmit() function displaySubmit($title = 'Submit Changes', $name = "submit") { print "<INPUT NAME=\"$name\" TYPE=\"submit\" VALUE=\"$title\">"; } // }}} // {{{ displaySubmitRow() function displaySubmitRow($name = "submit", $title = 'Submit Changes') { print " <TR>\n"; print " <TD>&nbsp</TD>\n"; print " <TD>"; $this->displaySubmit($title, $name); print "</TD>\n"; print " </TR>\n"; } // }}} // {{{ displayHidden() function displayHidden($name, $value) { print "<INPUT TYPE=\"hidden\" NAME=\"$name\" VALUE=\"$value\">"; } // }}} // {{{ displaySelect() function displaySelect($name, $entries, $default = '', $size = 1, $blank = '', $multiple = false) { print " <SELECT NAME=\"$name\""; if ($size) { print " SIZE=\"$size\""; } if ($multiple) { print " MULTIPLE"; } print ">\n"; if ($blank) { print " <OPTION VALUE=\"\">$blank\n"; } while (list($val, $text) = each($entries)) { print ' <OPTION '; if ($default && $default == $val) { print 'SELECTED '; } print "VALUE=\"$val\">$text\n"; } print " </SELECT>\n"; } // }}} // {{{ displaySelectRow() function displaySelectRow($name, $title, &$entries, $default = '', $size = 1, $blank = '', $multiple = false) { print " <TR>\n"; print " <TH ALIGN=\"right\">$title:</TH>\n"; print " <TD>\n"; $this->displaySelect($name, &$entries, $default, $size, $blank, $multiple); print " </TD>\n"; print " </TR>\n"; } // }}} // XXX missing: displayRadio displayRadioRow displayReset // {{{ display() function display() { $this->start(); print "<TABLE>\n"; reset($this->fields); $hidden = array(); $call_cache = array(); while (list($i, $data) = each($this->fields)) { switch ($data[0]) { case "hidden": $hidden[] = $i; continue 2; case "reset": $params = 1; break; case "submit": case "image": $params = 2; break; case "checkbox": $params = 3; break; case "text": case "password": case "radio": $params = 4; break; case "textarea": $params = 5; break; case "select": $params = 7; break; default: // unknown field type continue 2; } $str = $call_cache[$params]; if (!$str) { $str = '$this->display'.ucfirst($data[0])."Row("; for ($i = 1; $i <= $params; $i++) { $str .= '$data['.$i.']'; if ($i < $params) $str .= ', '; } $str .= ');'; $call_cache[$params] = $str; } eval($str); } print "</TABLE>\n"; for ($i = 0; $i < sizeof($hidden); $i++) { $this->displayHidden($this->fields[$hidden[$i]][1], $this->fields[$hidden[$i]][2]); } $this->end(); } // }}} } ?> Index: pearweb/public_html/authors.php +++ pearweb/public_html/authors.php <?php pageHeader("PEAR: Authors"); print "<H1>Authors</H1>\n"; $sth = $dbh->query('SELECT handle,name,email,homepage,showemail '. 'FROM authors WHERE registered = 1'); if (DB::isError($sth)) { die("query failed: ".DB::errorMessage($dbh)."<BR>\n"); } print "<TABLE BORDER=1>\n"; print " <TR>\n"; print " <TH>Handle</TH>\n"; print " <TH>Name</TH>\n"; print " <TH>Email</TH>\n"; print " <TH>Homepage</TH>\n"; print " </TR>\n"; while (is_array($row = $sth->fetchRow(DB_GETMODE_ASSOC))) { extract($row); print " <TR>\n"; print " <TD>$handle</TD>\n"; print " <TD>$name</TD>\n"; if ($showemail) { print " <TD><A HREF=\"mailto:$email\">$email</A></TD>\n"; } else { print " <TD>(not shown)</TD>\n"; } print " <TD><A HREF=\"$homepage\">$homepage</A></TD>\n"; print " </TR>\n"; } print "</TABLE>\n"; pageFooter(); ?>

« previous php.pear (#143) next »