Location: PHPKode > scripts > phpPhrasebook > phpphrasebook/Phrasebook.php
<?php

/**

 * phpPhrasebook: PHP Implementation of the Phrasebook pattern

 *

 * This class implements the phrasebook pattern, as documented by Yonat Sharon

 * and Rani Pinchuk in their paper, The Phrasebook Pattern available at

 * {@link http://jerry.cs.uiuc.edu/~plop/plop2k/proceedings/Pinchuk/Pinchuk.pdf}.

 *

 * @package phpPhrasebook

 * @author Andrew Barilla <hide@address.com>

 * @version 0.1

 * @link http://phpphrasebook.sourceforge.net

 * @copyright GNU-GPL

 *

 */



/**

 * Implements the Phrasebook pattern

 *

 * This class implements the phrasebook pattern, as documented by Yonat Sharon

 * and Rani Pinchuk in their paper, The Phrasebook Pattern available at

 * http://jerry.cs.uiuc.edu/~plop/plop2k/proceedings/Pinchuk/Pinchuk.pdf.  It

 * uses similar calls and XML document format to Rani Pinchuk's 

 * Class::Phrasebook module for Perl.  The following documentation detailing 

 * the XML format is from the Class::Phrasebook module.  (No reason to

 * rewrite it)

 *

 * <snip>

 *

 * This class implements the Phrasebook pattern.  It lets us create 

 * dictionaries of phrases. Each phrase can be accessed by a unique key. Each

 * phrase may have placeholders. Group of phrases are kept in a dictionary. 

 * ... The phrases are kept in an XML document.

 * 

 * The XML document type definition is as followed:

 * <pre>

 *  &lt;?xml version="1.0"?&gt;

 *  &lt;!DOCTYPE phrasebook [

 * 	       &lt;!ELEMENT phrasebook (dictionary)*&gt;              

 * 	       &lt;!ELEMENT dictionary (phrase)*&gt;

 *                &lt;!ATTLIST dictionary name CDATA #REQUIRED&gt;

 *                &lt;!ELEMENT phrase (#PCDATA)&gt;

 *                &lt;!ATTLIST phrase name CDATA #REQUIRED&gt;

 *  ]&gt;

 * </pre>

 * Example for XML file:

 * <pre>

 *  &lt;?xml version="1.0"?&gt;

 *  &lt;!DOCTYPE phrasebook [

 * 	       &lt;!ELEMENT phrasebook (dictionary)*&gt;              

 * 	       &lt;!ELEMENT dictionary (phrase)*&gt;

 *                &lt;!ATTLIST dictionary name CDATA #REQUIRED&gt;

 *                &lt;!ELEMENT phrase (#PCDATA)&gt;

 *                &lt;!ATTLIST phrase name CDATA #REQUIRED&gt;

 *  ]&gt;

 *  &lt;phrasebook&gt;

 *  &lt;dictionary name="EN"&gt;

 * 

 *  &lt;phrase name="HELLO_WORLD"&gt;

 *             Hello World!!!

 *  &lt;/phrase&gt;

 * 

 *  &lt;phrase name="THE_HOUR"&gt;

 *             The time now is $hour. 

 *  &lt;/phrase&gt;

 * 

 *  &lt;phrase name="ADDITION"&gt;

 *             add $a and $b and you get $c

 *  &lt;/phrase&gt;

 * 

 * 

 *  &lt;!-- my name is the same in English Dutch and French. --&gt;

 *  &lt;phrase name="THE_AUTHOR"&gt;

 *             Rani Pinchuk

 *  &lt;/phrase&gt;

 *  &lt;/dictionary&gt;

 * 

 *  &lt;dictionary name="FR"&gt;

 *  &lt;phrase name="HELLO_WORLD"&gt;

 *             Bonjour le Monde!!!

 *  &lt;/phrase&gt;

 * 

 *  &lt;phrase name="THE_HOUR"&gt;

 *             Il est maintenant $hour. 

 *  &lt;/phrase&gt;

 * 

 *  &lt;phrase name="ADDITION"&gt;

 *             $a + $b = $c

 *  &lt;/phrase&gt;

 * 

 *  &lt;/dictionary&gt;

 * 

 *  &lt;dictionary name="NL"&gt;

 *  &lt;phrase name="HELLO_WORLD"&gt;

 *             Hallo Werld!!!

 *  &lt;/phrase&gt;

 * 

 *  &lt;phrase name="THE_HOUR"&gt;

 *             Het is nu $hour. 

 *  &lt;/phrase&gt;

 * 

 *  &lt;phrase name="ADDITION"&gt;

 *             $a + $b = $c

 *  &lt;/phrase&gt;

 * 

 *  &lt;/dictionary&gt;

 * 

 *  &lt;/phrasebook&gt;

 * </pre>

 * 

 * Each phrase should have a unique name. Within the phrase text we can 

 * place placeholders. When get method is called, those placeholders will be 

 * replaced by their value.

 * 

 * </snip>

 *

 * <b>Example:</b>

 *

 * <pre>

 * 

 * require ("Phrasebook.php");

 *

 * $hPhrase = new Phrasebook("mydict.xml");

 * $hPhrase->load("EN");

 * print $hPhrase->getPhrase("ADDITION", array("a"=>"1",

 *                                             "b"=>"2",

 *                                             "c"=>"3"));

 * 

 * </pre>

 * 

 * @package phpPhrasebook

 * @author Andrew Barilla <hide@address.com>

 * 

 */

class Phrasebook {



    /**#@+

     * @access private

     */



    var $stFileName;

    var $stDictionary;

    var $astPhrases;



    var $stCurrentTag;

    var $stPhraseName;

    var $stPhraseValue;

    var $boReadOn;

    var $boRemoveNewLines;

    /**#@-*/



    /**

     * Constructor for Phrasebook class.

     * 

     * @param string    a_stFileName

     *        The filename of the xml phrasebook document to read.

     * @see setFileName

     */    

    function Phrasebook ($a_stFileName) {



        $this->setFileName($a_stFileName);

        $this->stPhrases = array();

        $this->boRemoveNewLines = false;



    }



    /**

     * Registers the name of the XML phrasebook file to use next time the

     * load function is called.  Currently, this looks in the working directory

     * for the XML file.

     * 

     * @param string   a_stFileName       

     *        The filename of the xml phrasebook document to read.

     */

    function setFileName ($a_stFileName) {



        $this->stFileName = $a_stFileName;



    }



    /**

     * Loads the dictionary from the xml file into memory.  Calling this 

     * more than once will not reset the previous dictionary but will instead

     * override and add to it.

     * 

     * @param string   a_stDictionary

     *        The filename of the dictionary to read from the phrasebook

     */

    function load ($a_stDictionary = "") {



        if ($a_stDictionary != "") 

            $this->setDictionaryName ($a_stDictionary);



        $l_hXmlParser = xml_parser_create();



        xml_set_element_handler($l_hXmlParser, 

                                array(&$this, "_startElement"), 

                                array(&$this, "_endElement"));

        xml_set_character_data_handler($l_hXmlParser, 

                                       array(&$this, "_characterData"));



        if (!($l_hFile = fopen($this->stFileName, "r"))) {

            die("Cannot locate XML data file: ".$this->stFileName);

        }



        $this->boReadOn = false;

        $this->stPhraseName = "";

        $this->stPhraseValue = "";



        // read and parse data

        while ($l_stData = fread($l_hFile, 4096)) {

            if (!xml_parse($l_hXmlParser, $l_stData, feof($l_hFile))) {

                $stError = xml_error_string(xml_get_error_code($l_hXmlParser));

                die(sprintf("XML error: %s at line %d",

                            $stError,

                            xml_get_current_line_number($l_hXmlParser)));

            }

        }



        xml_parser_free($l_hXmlParser);



    }



    /**

     * Returns the phrase from the dictionary and will substitute 

     * variables when appropriate.

     * 

     * @param     string      a_stName

     *            The key of the phrase to return

     * @param     array       a_astValues

     *            Array of strings to replace variables in the phrase with

     * @return    string

     *            The phrase with variables replaced if appropriate

     *            

     */

    function getPhrase ($a_stName, $a_astValues = array()) {



        if (!array_key_exists($a_stName, $this->astPhrases)) 

            return "";



        $stPhrase = $this->astPhrases[$a_stName];



        $stPhrase = preg_replace('/(\$)([a-zA-Z0-9_]+)/ie', 

                                 "\$a_astValues['$2']",

                                 $stPhrase);



        $stPhrase = preg_replace('/(\$\()([a-zA-Z0-9_]+)\)/ie', 

                                 "\$a_astValues['$2']",

                                 $stPhrase);



        if ($this->boRemoveNewLines) 

            $stPhrase = str_replace('\n', '', $stPhrase);



        return $stPhrase;



    }



    /**

     * Returns the name of the dictionary currently in use

     *

     * @return    string

     *            The name of the current dictionary

     *            

     */

    function getDictionaryName () {



        return $this->stDictionary;



    }



    /**

     * Registers the name of the dictionary to use next time 

     * the load function is called. 

     *

     * @param     string       a_stDictionary

     *            The name of the dictionary to use

     *            

     */

    function setDictionaryName ($a_stDictionary) {



        $this->stDictionary = $a_stDictionary;



    }



    /**

     * Returns the value of the RemoveNewLines setting

     *

     * @return    boolean

     *            The current value of the RemoveNewLines setting

     *            

     */

    function getRemoveNewLines () {



        return $this->boRemoveNewLines;



    }



    /**

     * Sets the value of the RemoveNewLines setting.  When true,

     * new lines will be stripped when calling the getPhrase method.

     * When false, will leave phrases intact. 

     *

     * @param     boolean      a_boRemoveNewLines

     *            The value of the RemoveNewLines setting

     *            

     */

    function setRemoveNewLines ($a_boRemoveNewLines) {



        $this->boRemoveNewLines = $a_boRemoveNewLines;



    }



    /**#@+

     * @access private

     */

    function _startElement ($a_hParser, $a_stName, $a_astAttrs) {

            

        $this->stCurrentTag = $a_stName;

        $this->stPhraseValue = "";

        

        switch ($a_stName) {

        case "DICTIONARY":



            if (is_array($a_astAttrs)) {

            

                $stDictionary = $a_astAttrs["NAME"] or 

                    die("The dictionary element must " .

                        "have the name attribute.");



                if ($stDictionary == $this->stDictionary) {

                    $this->boReadOn = true;

                }

                else {

                    $this->boReadOn = false;

                }



            }

            else {

                die("The dictionary element must have the name attribute.");

            }



            break;



        case "PHRASE":



            if ($this->boReadOn) {



                if (is_array($a_astAttrs)) {



                    $stPhraseName = $a_astAttrs["NAME"] or 

                        die("The phrase element must " . 

                            "have the name attribute.");



                    $this->stPhraseName = $stPhraseName;

                    $this->stPhraseValue = "";



                }



            }



            break;



        }





    }



    function _endElement ($a_hParser, $a_stName) {

  

        if ($this->boReadOn && strlen($a_stName)) {



            $this->astPhrases[$this->stPhraseName] = $this->stPhraseValue;



        }

        



            

            

        $this->stCurrentTag = "";



    }

    

    function _characterData ($a_hParser, $a_stData) {

        

        $this->stPhraseValue .= $a_stData;

                

    }

    /**#@-*/



}



?>
Return current item: phpPhrasebook