[Easymod-cvs] easymod2/dev functions_xml.php,NONE,1.1 mod_template.xml,NONE,1.1
Status: Beta
Brought to you by:
wgeric
From: Eric F. <wg...@us...> - 2005-05-15 01:34:13
|
Update of /cvsroot/easymod/easymod2/dev In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv25967/dev Added Files: functions_xml.php mod_template.xml Log Message: XML MOD Template Parser. Needs some minor work but the bulk of it is there. --- NEW FILE: mod_template.xml --- <?xml version="1.0" encoding="utf-8" standalone="yes"?> <!--?xml-stylesheet type="text/xsl" href="english.subsilver.xsl"?--> <mod xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <header> <title lang="en">Country Flags</title> <description lang="en">This mod allows your registered board members to select the flag of their country. Their flag will then display thoughout the phpBB system.</description> <author-notes lang="en">This MOD is not to be listed, downloaded or posted at -any- site except Official phpBB Web Sites. Thank You. JbA</author-notes> <!-- multiple authors are easy --> <author realname="nuttzy" email="pkt...@bl..." username="Nuttzy99" homepage="http://www.blizzhackers.com" /> <author realname="John B. Abela" email="ab...@4c..." username="abelajohnb" homepage="N/A" /> <!-- breaking the MOD version up into it's components allows for flexibility, while still enforcing an absolute standard --> <mod-version> <major>2</major> <minor>2</minor> <revision>2</revision> <release>a</release> </mod-version> <installation> <level>Easy</level> <time>2820</time> <target-version> <!-- Even though we have the components, they can be split up, also, as we plan to support Beta 1, a text field thats for show purposes only seems necessary, as it may not always be possible to grab a single designed for version --> <target-primary>3.0.0 Beta 1</target-primary> <target-major allow="exact">3</target-major> <target-minor allow="exact">0</target-minor> <target-revision allow="after">0</target-revision> <!-- this is just so the xsd creates this field, this just effectively locks out all letter releases, not something we really want in practice, but the field may be useful, and thus future-proofing the template --> <target-release allow="exact"></target-release> </target-version> <easymod-compliant>false</easymod-compliant> <mod-config>config.modcfg</mod-config> </installation> <history> <revision> <date>2004-07-26T00:00:00.0000000+10:00</date> <version>2.2.2</version> <change>eliminated flags.sql file</change> </revision> <revision> <date>2003-02-20T00:00:00.0000000+10:00</date> <version>2.2.0</version> <change>updated for phpBB 2.0.4</change> <change>added admin tools to edit/add/remove flags</change> </revision> </history> <!-- why have meta, why not? it just allows for organised information to be stored that an author or application could put in to indicate various aspects of the MOD --> <meta name="generator" content="MOD Studio sharp 4, beta 1 with mod functions sharp 2" /> </header> <action-group> <sql> ALTER TABLE phpbb_users ADD user_from_flag varchar(25) NULL AFTER user_from; CREATE TABLE phpbb_flags ( flag_id int(10) NOT NULL auto_increment, flag_name varchar(25), flag_image varchar(25), PRIMARY KEY (flag_id) ); INSERT INTO phpbb_flags (flag_id, flag_name, flag_image) VALUES ('','usa','usa.gif'); INSERT INTO phpbb_flags (flag_id, flag_name, flag_image) VALUES ('','afghanistan','afghanistan.gif'); INSERT INTO phpbb_flags (flag_id, flag_name, flag_image) VALUES ('','albania','albania.gif'); INSERT INTO phpbb_flags (flag_id, flag_name, flag_image) VALUES ('','algeria','algeria.gif'); INSERT INTO phpbb_flags (flag_id, flag_name, flag_image) VALUES ('','andorra','andorra.gif'); INSERT INTO phpbb_flags (flag_id, flag_name, flag_image) VALUES ('','angola','angola.gif'); INSERT INTO phpbb_flags (flag_id, flag_name, flag_image) VALUES ('','antigua and barbuda','antiguabarbuda.gif'); INSERT INTO phpbb_flags (flag_id, flag_name, flag_image) VALUES ('','argentina','argentina.gif'); INSERT INTO phpbb_flags (flag_id, flag_name, flag_image) VALUES ('','armenia','armenia.gif'); INSERT INTO phpbb_flags (flag_id, flag_name, flag_image) VALUES ('','australia','australia.gif'); </sql> <copy from="flags/*.*" to = "images/flag/*.*" /> <copy from="admin_flags.php.txt" to="admin/admin_flags.php" /> <copy from="flages_list_body.tpl.txt" to="templates/subSilver/admin/flags_list_body.tpl" /> <copy from="flags_edit_body.tpl.txt" to="templates/subSilver/admin/flags_edit_body.tpl" /> <open file="includes/constants.php"> <edit> <find> define('VOTE_USERS_TABLE', $table_prefix.'vote_voters'); </find> <action type="before-add"> // before </action> <action type="after-add"> // FLAGHACK-start define('FLAG_TABLE', $table_prefix.'flags'); // FLAGHACK-end </action> </edit> </open> <open file="includes/usercp_viewprofile.php"> <edit> <find> $pm_img = '<a href=" </find> <action type="after-add"> // FLAGHACK-start $location = ( $profiledata['user_from'] ) ? $profiledata['user_from'] : '&nbsp;' ; $flag = ( !empty($profiledata['user_from_flag']) ) ? "&nbsp;<img src=\"images/flags/" . $profiledata['user_from_flag'] . "\" alt=\"" . $profiledata['user_from_flag'] . "\">" : ""; $location .= $flag ; // FLAGHACK-end </action> </edit> <edit> <find> 'LOCATION' => </find> <action type="replace-with"> // FLAGHACK-start 'LOCATION' => $location, // FLAGHACK-endd </action> </edit> <edit> <find> $user_timezone = ( </find> <action type="after-add"> // FLAGHACK-start $user_flag = ( !empty($HTTP_POST_VARS['user_flag']) ) ? $HTTP_POST_VARS['user_flag'] : '' ; // FLAGHACK-end </action> </edit> <edit> <find> $sql = "UPDATE " . USERS_TABLE . " user_from = '" . str_replace("\'", "''", $location) . "', </find> <inline-edit> <inline-find> user_from = '" . str_replace("\'", "''", $location) . "', </inline-find> <inline-action type="after-add"> user_from_flag = '$user_flag', </inline-action> </inline-edit> </edit> <edit> <find> $sql = "INSERT INTO " . USERS_TABLE VALUES ( </find> <inline-edit> <inline-find> user_from, </inline-find> <inline-action type="after-add"> user_from_flag, </inline-action> </inline-edit> </edit> <edit> <find> $sql = "INSERT INTO " . USERS_TABLE VALUES ( </find> <inline-edit> <inline-find> '" . str_replace("\'", "''", $location) . "', </inline-find> <inline-action type="after-add"> '$user_flag', </inline-action> </inline-edit> </edit> <edit> <find> $location = $userdata['user_from']; </find> <action type="after-add"> // FLAGHACK-start $user_flag = $userdata['user_from_flag']; // FLAGHACK-end </action> </edit> <edit> <find type="regex"> display_avatar_gallery( </find> <inline-edit> <inline-find> $location, </inline-find> <inline-action type="after-add"> $user_flag, </inline-action> </inline-edit> <inline-edit> <inline-find type="regex"> [a-z]{9} </inline-find> <inline-action type="operation">{0}++</inline-action> </inline-edit> <inline-edit> <inline-find type="regex"> [0-9] </inline-find> <inline-action type="operation">{0}--</inline-action> </inline-edit> </edit> <edit> <find> if ( $mode == 'editprofile' ) { $template->assign_block_vars('switch_edit_profile', array()); } </find> <action type="after-add"> // FLAGHACK-start // query to get the list of flags $sql = "SELECT * FROM " . FLAG_TABLE . " ORDER BY flag_id"; if(!$flags_result = $db->sql_query($sql)) { message_die(GENERAL_ERROR, "Couldn't obtain flags information.", "", __LINE__, __FILE__, $sql); } $flag_row = $db->sql_fetchrowset($ranksresult); $num_flags = $db->sql_numrows($ranksresult) ; // build the html select statement $flag_start_image = 'blank.gif' ; $selected = ( isset($user_flag) ) ? '' : ' selected="selected"' ; $flag_select = "<select name=\"user_flag\" onChange=\"document.images['user_flag'].src = 'images/flags/' + this.value;\" >"; $flag_select .= "<option value=\"blank.gif\"$selected>" . $lang['Select_Country'] . "</option>"; for ($i = 0; $i < $num_flags; $i++) { $flag_name = $flag_row[$i]['flag_name']; $flag_image = $flag_row[$i]['flag_image']; $selected = ( isset( $user_flag) ) ? (($user_flag == $flag_image) ? 'selected="selected"' : '' ) : '' ; $flag_select .= "\t<option value=\"$flag_image\"$selected>$flag_name</option>"; if ( isset( $user_flag) && ($user_flag == $flag_image)) { $flag_start_image = $flag_image ; } } $flag_select .= '</select>'; // FLAGHACK-end </action> </edit> <edit> <find> 'LOCATION' => $location, </find> <comment lang="en">This comment comes after the find.</comment> <action type="after-add"> // FLAGHACK-start 'L_FLAG' => $lang['Country_Flag'], 'FLAG_SELECT' => $flag_select, 'FLAG_START' => $flag_start_image, // FLAGHACK-end </action> <comment lang="en">This comment comes after the edit action.</comment> </edit> </open> <diy-instructions lang="en">Hop on one leg and do a rain dance. If you do it right the MOD may work for you. However on tuesdays you must bow down to the sungod and give him special berries, from the tallest berry tree on the planet pluto, 9th from the Hyrogen sun.</diy-instructions> </action-group> </mod> --- NEW FILE: functions_xml.php --- <?php $mod_parser = new xml_mod_parser; $results = $mod_parser->parse_file('mod_template.xml'); echo '<pre>'; var_dump($results); echo '</pre>'; // getting even lower level data lookup. soon we'll be parsing xml. wait... wait? we are! class xml_mod_parser { var $data; var $handlers = array(); function parse_file($filename,$options = false) { $data = implode('', file($filename)); $data = str_replace('&', '{AMPERSTAND}', $data); if (preg_match('#[\s]*<\?xml[^>]+encoding="([a-zA-Z0-9_\- ]+)"#si', $data, $matches)) { $encoding = $matches[1]; $xml_parser = xml_parser_create(strtoupper($encoding)); xml_parser_set_option($xml_parser, XML_OPTION_TARGET_ENCODING, 'ISO-8859-1'); } else { $xml_parser = xml_parser_create(); } xml_parser_set_option($xml_parser, XML_OPTION_CASE_FOLDING, 0); xml_parser_set_option($xml_parser, XML_OPTION_SKIP_WHITE, 1); xml_parse_into_struct($xml_parser, $data, $values, $tags); xml_parser_free($xml_parser); $this->parse($values,$options,$filename); return $this->export(); } function parse($values,$options = false,$filename = '') { $this->clear_data(); if ( !empty($options) && !is_array($options) ) { $options = array($options); } $mod = array_shift($values); if ( handler::typecheck($mod,'mod','open') ) { while ( $set = array_shift($values) ) { $tag = str_replace('-', '_', $set['tag']); $handler = $tag . '_handler'; if ( (!$options || in_array($tag,$options) ) && class_exists($handler) ) { if ( !isset($this->handlers[$handler]) ) { $this->handlers[$handler] = new $handler; } $this->data[$tag] = call_user_func_array(array(&$this->handlers[$handler],'parse'),array(&$values,$set,$filename)); } else if ( handler::typecheck($set,'mod','close') ) { break; } else { if ( !isset($this->handlers['default']) ) { $this->handlers['default'] = new handler; } // if we're just skipping parsing this one, we can pass it to an empty handler if ( true || class_exists($handler) ) { $this->data[$tag][] = call_user_func_array(array(&$this->handlers['default'],'parse'),array(&$values,$set,$filename)); } // handler::parse_error('mod',$set,__LINE__,"No handler defined for this tag",$filename); } } } // foreach passes by value, less efficient @reset($this->data); while ( list($tag,) = each($this->data) ) { $handler = $tag . '_handler'; $handler = isset($this->handlers[$handler]) ? $handler : 'default'; $this->data[$tag] = call_user_func_array(array(&$this->handlers[$handler],'process'),array($this->data[$tag])); } } function export() { return $this->data; } function clear_data() { $this->data = array(); } } class handler { function parse(&$values,$tag,$filename) { $tagname = $tag['tag']; if ( $tag['type'] == 'complete' ) { return array($tagname , $tag['type'], 'unparsed'); } while ( $tag = array_shift($values) ) { switch( true ) { case $this->typecheck($tag,$tagname,'close'): return array($tagname , $tag['type'], 'unparsed'); break; default: break; } } } function process($data) { return count($data); } function parse_error($area,$bad_data,$line = 0,$message='',$filename='') { printf('Error parsing XML Document in %s%s<br />',$area,$line?sprintf(' on line %d%s',$line,!empty($filename)?sprintf(' for file %s',$filename):''):''); print('<pre>'); if (!empty($message) ) print $message . "\n"; var_dump($bad_data); print "\n\n\n\n"; global $mod_parser; var_dump($mod_parser); print('</pre>'); die(); } function typecheck($tag,$names,$types) { if ( !is_array($names) ) { $names = array($names); } if ( !is_array($types) ) { $types = array($types); } // printf('Typecheck: %s vs %s, %s vs %s<br />',$tag['tag'],$name,$tag['type'],$type); return ( in_array($tag['tag'],$names) && in_array($tag['type'],$types) ); } function parse_bool($value,$attr_name = '',$line = 0,$filename = '') { switch($value) { case "1": case "true": return true; break; case "0": case "false": return false; break; default: $message = sprintf('Invalid boolean value "%s"',$value); if ( !empty($attr_name) ) { $message .= sprintf(' for attribute "%s"',$attr_name); } if ( $line ) { $message .= sprintf(' on line %d',$line); } $this->parse_error(__CLASS__,$attributes['dynamic'],$line,$message,$filename); break; } } } // handles the header xml tags class header_handler extends handler { function parse(&$values, $tag, $filename = '') { $result = array(); $valid_keys = array('title', 'description', 'mod_version', 'author-notes'); $valid_loops = array('meta', 'author'); $valid_open = array('mod-version', 'installation', 'history'); while ( $tag = array_shift($values) ) { $tagname = $tag['tag']; switch ( true ) { case $this->typecheck($tag, 'header', 'close'): { return $result; } break; case $this->typecheck($tag, $valid_keys, 'complete'): { $result[$tagname] = $tag['value']; } break; case $this->typecheck($tag, $valid_loops, 'complete'): { $result[$tagname][] = $tag['attributes']; } break; case $this->typecheck($tag, $valid_open, 'open'); { $handler = str_replace('-', '_', $tagname) . '_handler'; if ( class_exists($handler) ) { if ( !isset($this->handlers[$handler]) ) { $this->handlers[$handler] = new $handler; } $result[$tagname] = call_user_func_array(array(&$this->handlers[$handler],'parse'),array(&$values,$tag,$filename)); } else { if ( !isset($this->handlers['default']) ) { $this->handlers['default'] = new handler; } // if we're just skipping parsing this one, we can pass it to an empty handler if ( true || class_exists($handler) ) { $result[$tagname][] = call_user_func_array(array(&$this->handlers['default'],'parse'),array(&$values,$tag,$filename)); } } } break; default: { $this->parse_error(__CLASS__,$tag,__LINE__,"Invalid tag",$filename); } break; } } } function process($data) { return $data; } } // handles xml tags in the header and mod-version class mod_version_handler extends handler { function parse(&$values,$tag,$filename = '') { $result = array(); $valid_keys = array('major', 'minor', 'revision', 'release'); while ( $tag = array_shift($values) ) { $tagname = $tag['tag']; switch ( true ) { case $this->typecheck($tag,'mod-version','close'): { return $result; } break; case $this->typecheck($tag, $valid_keys, 'complete'): { $result[$tagname] = $tag['value']; } break; default: { $result[$tagname] = $tag['value']; } break; } } } function process($data) { return $data; } } // handles tags in the header and installation class installation_handler extends handler { function parse(&$values,$tag,$filename = '') { $result = array(); $valid_keys = array('level', 'time', 'target-primary', 'target-major', 'target-minor', 'target-revision', 'target-release', 'easymod-compliant', 'mod-config'); $valid_open = array('target-version'); while ( $tag = array_shift($values) ) { $tagname = $tag['tag']; switch ( true ) { case $this->typecheck($tag,'installation','close'): { return $result; } break; case $this->typecheck($tag, $valid_keys, 'complete'): { if ( empty($current_tag) ) { $result[$tagname] = $tag['value']; } else { $result[$current_tag][$tagname] = $tag['value']; } } break; case $this->typecheck($tag, $valid_open, 'open'): { $current_tag = $tagname; } break; case $this->typecheck($tag, $valid_open, 'close'): { $current_tag = ''; } break; default: { $result[$tagname] = $tag['value']; } break; } } } function process($data) { return $data; } } // handles tags in the header and history class history_handler extends handler { function parse(&$values,$tag,$filename = '') { $result = array(); $valid_keys = array('date', 'version'); $valid_loops = array('change'); $valid_open = array('revision'); $i = 0; while ( $tag = array_shift($values) ) { $tagname = $tag['tag']; switch ( true ) { case $this->typecheck($tag,'history','close'): { return $result; } break; case $this->typecheck($tag, $valid_keys, 'complete'): { if ( empty($current_tag) ) { $result[$tagname] = $tag['value']; } else { $result[$current_tag][$i][$tagname] = $tag['value']; } } break; case $this->typecheck($tag, $valid_loops, 'complete'): { if ( empty($current_tag) ) { $result[$tagname][] = $tag['value']; } else { $result[$current_tag][$i][$tagname][] = $tag['value']; } } break; case $this->typecheck($tag, $valid_open, 'open'): { $current_tag = $tagname; } break; case $this->typecheck($tag, $valid_open, 'close'): { $current_tag = ''; $i++; } break; default: { $result[$tagname] = $tag['value']; } break; } } } function process($data) { return $data; } } // handles the actions in action-group class action_group_handler extends handler { function parse(&$values,$tag,$filename = '') { $result = array(); $valid_keys = array('sql', 'diy-instructions'); $valid_loops = array('copy'); $valid_open = array('open'); while ( $tag = array_shift($values) ) { $tagname = $tag['tag']; switch ( true ) { case $this->typecheck($tag, 'action-group', 'close'): { return $result; } break; case $this->typecheck($tag, $valid_keys, 'complete'): { $result[$tagname] = $tag['value']; } break; case $this->typecheck($tag, $valid_loops, 'complete'): { $result[$tagname][] = $tag['attributes']; } break; case $this->typecheck($tag, $valid_open, 'open'); { $handler = str_replace('-', '_', $tagname) . '_handler'; if ( class_exists($handler) ) { if ( !isset($this->handlers[$handler]) ) { $this->handlers[$handler] = new $handler; } $result[$tagname][$tag['attributes']['file']] = call_user_func_array(array(&$this->handlers[$handler],'parse'),array(&$values,$tag,$filename)); } else { if ( !isset($this->handlers['default']) ) { $this->handlers['default'] = new handler; } // if we're just skipping parsing this one, we can pass it to an empty handler if ( true || class_exists($handler) ) { $result[$tagname][$tag['attributes']['file']][] = call_user_func_array(array(&$this->handlers['default'],'parse'),array(&$values,$tag,$filename)); } } } break; default: { $this->parse_error(__CLASS__,$tag,__LINE__,"Invalid tag",$filename); } break; } } } function process($data) { return $data; } } // handles tags in the open and action group class open_handler extends handler { function parse(&$values,$tag,$filename = '') { $result = array(); $valid_keys = array('find'); $valid_loops = array('change', 'comment', 'action'); $valid_open = array('edit'); $valid_new = array('inline-edit'); $i = 0; while ( $tag = array_shift($values) ) { $tagname = $tag['tag']; switch ( true ) { case $this->typecheck($tag,'open','close'): { return $result; } break; case $this->typecheck($tag, $valid_keys, 'complete'): { if ( empty($current_tag) ) { $result[$tagname] = $tag['value']; } else { $result[$current_tag][$i][$tagname] = $tag['value']; } } break; case $this->typecheck($tag, $valid_loops, 'complete'): { if ( empty($current_tag) ) { if ( $tagname == 'action' ) { $result[$tagname][] = array( 'type' => $tag['attributes']['type'], 'code' => $tag['value']); } else { $result[$tagname][] = $tag['value']; } } else { if ( $tagname == 'action' ) { $result[$current_tag][$i][$tagname][] = array( 'type' => $tag['attributes']['type'], 'code' => $tag['value']); } else { $result[$current_tag][$i][$tagname][] = $tag['value']; } } } break; case $this->typecheck($tag, $valid_open, 'open'): { $current_tag = $tagname; } break; case $this->typecheck($tag, $valid_open, 'close'): { $current_tag = ''; $i++; } break; case $this->typecheck($tag, $valid_new, 'open'); { $handler = str_replace('-', '_', $tagname) . '_handler'; if ( class_exists($handler) ) { if ( !isset($this->handlers[$handler]) ) { $this->handlers[$handler] = new $handler; } if ( empty($current_tag) ) { $result[$tagname][] = call_user_func_array(array(&$this->handlers[$handler],'parse'),array(&$values,$tag,$filename)); } else { $result[$current_tag][$i][$tagname][] = call_user_func_array(array(&$this->handlers[$handler],'parse'),array(&$values,$tag,$filename)); } } else { if ( !isset($this->handlers['default']) ) { $this->handlers['default'] = new handler; } // if we're just skipping parsing this one, we can pass it to an empty handler if ( true || class_exists($handler) ) { if ( empty($current_tag) ) { $result[$tagname][] = call_user_func_array(array(&$this->handlers['default'],'parse'),array(&$values,$tag,$filename)); } else { $result[$current_tag][$i][$tagname][] = call_user_func_array(array(&$this->handlers['default'],'parse'),array(&$values,$tag,$filename)); } } } } break; default: { $result[$tagname] = $tag['value']; } break; } } } function process($data) { return $data; } } // handles tags in the inline, open, and action group class inline_edit_handler extends handler { function parse(&$values,$tag,$filename = '') { $result = array(); $valid_keys = array('inline-find'); $valid_loops = array('inline-action'); $i = 0; while ( $tag = array_shift($values) ) { $tagname = $tag['tag']; switch ( true ) { case $this->typecheck($tag,'inline-edit','close'): { return $result; } break; case $this->typecheck($tag, $valid_keys, 'complete'): { $result[$tagname] = $tag['value']; } break; case $this->typecheck($tag, $valid_loops, 'complete'): { $result[$tagname][] = array( 'type' => $tag['attributes']['type'], 'code' => $tag['value']); } break; default: { $result[$tagname] = $tag['value']; } break; } } } function process($data) { return $data; } } ?> |