PHP Programming Guide - jcobban/Genealogy GitHub Wiki

Up: Home

Table of Contents:

Overview of Programming

This section of the documentation describes how to write a PHP script to display an application specific page.

The classes that implement the behavior of the Genealogy application are in namespace Genealogy. So each script in the application identifies that it is in the Genealogy application by specifying namespace Genealogy;. While PHP handles references to functions that are globally defined, in particular the built-in functions of PHP, references to classes defined in any other namespace must be qualified. For example if the script uses or handles Exceptions then there must be a use \Exception; statement at the beginning of the script. The classes that are not specific to the Genealogy application are in other namespaces. In particular the Template engine is in namespace Templating. Most scripts only access the Template engine through the application specific class \Genealogy\FtTemplate but those scripts that access class \Templating\Template directly must add use \Templating\Template;.

In order that all of the pages on the Genealogy site have a similar appearance the logical structure of the common header portion is implemented by a common template. One of the objectives of using a template is to support communicating with users in their language of choice. The preferred language of communication is identified to the application by the parameter lang, whether passed in the URL for requests which do not alter the state of the database, or as the value of a field passed by method=POST for requests which do alter the database. The value of this attribute is a IETF BCP 47 identifier string which contains an ISO 639-1 2-character language code optionally separated from an ISO 3166-1 2-character country identifier by a hyphen. For example “lang=en” or “lang=en-US” or “lang=fr” or “lang=es-MX” or "lang=de-AT". Therefore the script must have obtained the value of this parameter before invoking the template engine. Since most scripts have other parameters all of the parameter values are typically collected by code which looks like:

    $lang                       = 'en';     // default non-country-specific English

// if invoked by method=get process the parameters
if (isset($_GET) && count($_GET) > 0)
{                       // invoked by URL
    $parmsText              = "<p class='label'>\$_GET</p>\n" .
                               "<table class='summary'>\n" .
                                  "<tr><th class='colhead'>key</th>" .
                                    "<th class='colhead'>value</th></tr>\n";
    foreach($_GET as $key => $value)
    {			    // loop through all parameters
        $safevalue          = htmlspecialchars($value);
        $parmsText          .= "<tr><th class='detlabel'>$key</th>" .
                                "<td class='white left'>" .
                                "$safevalue</td></tr>\n"; 

        switch(strtolower($key))
        {		// act on specific parameters
            case 'lang':
    	    {
    		$lang	= FtTemplate::validateLang($value);
    	        break;
    	    }           // language
            // check other parameters ... 
        }		// act on specific parameters
    }			// loop through all parameters
    if ($debug)
        $warn               .= $parmsText . "</table>\n";
}                       // invoked by URL

Collecting the parameters in this way provides a number of advantages over referencing the elements of $_GET or $_POST directly. For example this method ignores the case of the attribute identifier.

Note that it is not desirable to issue error messages in this loop because the language of communication has not yet been identified and the language-specific text of any such messages should be defined in the language specific template for the application. Instead if the value of the parameter is validated in this loop it should only set an indicator which will cause a message to be displayed in the requested language once the template has been loaded. For example:

    $byeartext                  = null;

    foreach($_GET as $key => $value)
    {			// loop through all parameters
        $safevalue          = htmlspecialchars($value);
        switch(strtolower($key))
        {		// act on specific parameters
            case 'byear':
            {               // Birth Year
                if (ctype_digit($value) &&
                    $value >= 1750 && $value < 2100)
                    $byear              = $value;
                else
                    $byeartext          = $safevalue;
                break;
            }               // Birth Year
        }		// act on specific parameters
    }			// loop through all parameters

...
$template   = new FtTemplate($file);
...
if (is_string($byeartext))
    $msg       .= $template['byearInvalid']->replace('$value', $byeartext);

If the language code is not supported by a matching template then a language specific message to that effect is presented when the page is displayed by the template engine. Furthermore it is common for the valid values for one parameter to depend upon the values of other parameters. So, for example, the ISO language code is merely collected here and not validated by FtTemplate::validateLang except to ignore values that are less than 2 characters long, make the language code portion of the value lower case, and make the country code portion upper case.

All scripts invoke this common template by creating an instance of class \Genealogy\FtTemplate:

 $template	        = new FtTemplate("PageName$lang.html");

or

 $template	        = new FtTemplate("PageName$option$lang.html");

Where "PageName" is the name of the application specific template. A common reason for inserting a $option into the requested file name is to choose a different layout for users who are authorized to update the information on the page as opposed to casual visitors. So a template file "PageNameDisplayen.html" is used to present the information in such a way that the user cannot change anything, for example including readonly="readonly" in input fields and omitting buttons to request updates and possibly using different CSS classes, while "PageNameUpdateen.html" presents the information as a form with active input fields, checkboxes, selection lists, buttons, and so on. The class \Genealogy\FtTemplate is an extension of class \Templating\Template to implement specific functionality related to the Family Tree application and support that application's implementation of localization. The client's requested language is passed in the template file name. The language specific template does not need to already exist. If it has not been created then the English version of the template is used. On November 29, 2018 there were base templates, defining the appearance of the common page header, for English, French, German, and Spanish.

The language code is used by class FtTemplate to load a template Trantab$lang.html containing a number of localization translations. In particular this localization template contains a table 'tranTab' which contains translations of common phrases used by the Genealogy application into the target language.

 $template	        = new FtTemplate("PageName$lang.html");
 $translate             = $template->getTranslate();
 $t                     = $translate['tranTab']
 ...
 $after                 = $t['after'];            // the word 'after' in the requested language

If the script displays numbers in the template then it should use the locale specific instance of class NumberFormatter which is obtained from $formatter = $template->getFormatter();.

The header section of each page displayed for the site can be customized in the base template "page$lang.html". The distributed version for the header layout has multiple columns:

  1. The left column displays a main menu button, commonly called a "hamburger" button, which looks like a stack of three thick lines.
  2. The next column is reserved for advertising.
  3. If there is sufficient room then social media links are displayed.
  4. The right hand column displays the logo of the site.

Common Page Header Appearance

The main section of each page is displayed using style div.body. The page script fills this with page-specific content by identifying the application layout for the requested language through the filename passed to new FtTemplate.

class \Genealogy\FtTemplate attempts to locate the language specific version of the application layout template. If there is no language specific version this code selects the English language version and apologizes for the lack of specific support using a message from the Language record for the requested language. On November 22, 2018 there were 12 languages with language specific apology text. The code works even if the requested language code is not defined by the ISO standard. The content of the Languages table is managed by page LanguagesEdit.php where the text of the language specific apology can be altered by authorized subscribers.

Apology for not supporting Polish

If the page requires specific CSS additions then the page PHP script should include:

$template->updateTag('otherStylesheets',
                     array('filename'   => 'PageName'));

which causes the standard page template to expand the following element inside the <head> tag:

<link rel='stylesheet' type='text/css' href='$filename.css'
            id="otherStylesheets">

Note that the value of $filename does not include the filetype extension .css. Also if $filename is an array of strings then multiple style sheet links are generated. If the application specific script does not define an action to take for element "otherStylesheets" then the element is removed from the generated document.

Next: Javascript Programming Guide

⚠️ **GitHub.com Fallback** ⚠️