root/trunk/patForms/Parser/Html.php

Revision 299, 6.9 kB (checked in by schst, 3 years ago)

Allow several elements with the same name to be set in the form definitions (required by the parser, fixes bug #178),
Fixed bug in HTML attributes parser, fixed bug in HTML parser when using elements with the same name (as radio buttons)

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1 <?PHP
2 /**
3  * patForms parser that reads plain HTML files
4  * and creates a from from these
5  *
6  * $Id$
7  *
8  * @author        Stephan Schmidt <s.schmidt@metrix.de>
9  * @package        patForms
10  * @subpackage    Parser
11  * @license        LGPL
12  * @copyright    PHP Application Tools <http://www.php-tools.net>
13  */
14
15 define('PATFORMS_PARSER_HTML_ERROR_MULTIPLE_FORMS', 'patForms_Parser_HTML::0001');
16
17 /**
18  * patForms parser that reads plain HTML files
19  * and creates a from from these
20  *
21  * @author        Stephan Schmidt <s.schmidt@metrix.de>
22  * @package        patForms
23  * @subpackage    Parser
24  * @license        LGPL
25  * @copyright    PHP Application Tools <http://www.php-tools.net>
26  * @version        1.0
27  */
28 class patForms_Parser_Html extends patForms_Parser
29 {
30    /**
31     * extract all form elements from the HTML page
32     *
33     * @access    public
34     * @param    string        html content
35     * @return    boolean
36     */
37     function parseString($string)
38     {
39         // get the form information
40         $regexp = "/<form ([^>]+)\/?>/";
41         $matches = array();
42         if (preg_match_all($regexp, $string, $matches)) {
43             if (count($matches[0]) > 1) {
44                 return patErrorManager::raiseError(PATFORMS_PARSER_HTML_ERROR_MULTIPLE_FORMS, 'The HTML parser currently does not support more than one form per page.');
45             }
46             $attributes = $this->_parseAttributes($matches[1][0]);
47             if (isset($attributes['name'])) {
48                 $formName = $attributes['name'];
49             } else {
50                 $formName = '__default';
51             }
52             $this->_formAttributes = array(
53                                             $formName => $attributes
54                                         );
55         } else {
56             // set default attributes fo the form
57             $this->_formAttributes = array(
58                                             '__default' => array(
59                                                                 'name' => 'form'
60                                                             )
61                                         );
62         }
63
64         // transform simple input fields       
65         $regexp     = "/<input ([^>]+)\/?>/";
66         $matches = array();
67         if (preg_match_all( $regexp, $string, $matches)) {
68             for ($i = 0; $i < count( $matches[1] ); $i++) {
69                 $atts = trim($matches[1][$i]);
70                 if (substr( $atts, -1 ) == '/') {
71                     $atts    =    substr( $atts, 0, -1 );
72                 }
73
74                 $atts = $this->_parseAttributes($atts);
75                 array_change_key_case($atts, CASE_LOWER);
76                 if (!isset($atts['id'])) {
77                     $atts['id'] = 'pfph_' . $atts['name'];
78                 }
79                 
80                 switch (strtolower($atts['type'])) {
81
82                     case 'password':
83                         $atts['type'] = 'password';
84                         break;
85                     case 'radio':
86                         $atts['id'] = $atts['id'] . '_' . $atts['value'];
87                         unset($atts['type']);
88                         $elName = 'Radio';
89                         break;
90                     case 'checkbox':
91                         unset( $atts['type'] );
92                         $elName = 'Switch';
93                         break;
94                     case 'text':
95                         unset( $atts['type'] );
96                         $elName    = 'String';
97                         break;
98                     case 'hidden':
99                         unset( $atts['type'] );
100                         $elName = 'Hidden';
101                         break;
102                     case 'file':
103                         unset( $atts['type'] );
104                         $elName    = 'File';
105                         break;
106                     default:
107                         continue 2;
108                         break;
109                 }
110
111                 
112                 if (isset($atts['patforms:type'])) {
113                     $elName    = $atts['patforms:type'];
114                     unset($atts['patforms:type']);
115                 }
116
117                 $this->addElementDefinition($atts['name'], $elName, $atts);
118                 $pl = $this->_getPlaceholderForElement($atts['id']);
119                 $string = str_replace($matches[0][$i], $pl, $string);
120             }
121         }
122
123         // transform textarea fields
124         $regexp     = "/<textarea ([^>]+)\/?>([^<]*)<\/textarea>/sm";
125         $matches = array();
126         if (preg_match_all($regexp, $string, $matches)) {
127             for ($i = 0; $i < count( $matches[1] ); $i++) {
128                 $atts = trim( $matches[1][$i] );
129                 
130                 $atts = $this->_parseAttributes( $atts);
131                 array_change_key_case( $atts, CASE_LOWER );
132                 if (!isset($atts['id'])) {
133                     $atts['id'] = 'pfph_' . $atts['name'];
134                 }
135
136                 $elName    = 'Text';
137
138                 $atts['default'] = $matches[2][$i];
139
140                 $this->addElementDefinition($atts['name'], $elName, $atts);
141                 $pl = $this->_getPlaceholderForElement($atts['id']);
142                 $string = str_replace($matches[0][$i], $pl, $string);
143             }
144         }
145
146         // transform select fields
147         $regexp     = "/<select ([^>]+)\/?>(.*)<\/select>/smU";
148         $matches = array();
149         if (preg_match_all($regexp, $string, $matches)) {
150             for ($i = 0; $i < count( $matches[1] ); $i++) {
151                 $atts = trim( $matches[1][$i] );
152
153                 $atts    =    $this->_parseAttributes( $atts );
154                 array_change_key_case( $atts, CASE_LOWER );
155                 if (!isset($atts['id'])) {
156                     $atts['id'] = 'pfph_' . $atts['name'];
157                 }
158
159                 $elName    = 'Enum';
160                 if (isset($atts['multiple'])) {
161                     $elName = 'Set';
162                     unset( $atts['multiple'] );
163                 }
164
165                 $matches2 = array();
166                 $regexp     = "/<option ([^>]+)\/?>([^<]*)(<\/option>)?/sm";
167                 $options = array();
168                 if (preg_match_all($regexp, $matches[2][$i], $matches2)) {
169                     for ($j = 0; $j < count( $matches2[0] ); $j++) {
170                         $opt = $this->_parseAttributes( $matches2[1][$j] );
171                         $opt['label'] = trim( $matches2[2][$j] );
172                         array_push( $options, $opt );
173                     }
174                 }
175                 $atts['values'] = $options;
176                 $this->addElementDefinition($atts['name'], $elName, $atts);
177                 $pl = $this->_getPlaceholderForElement($atts['id']);
178                 $string = str_replace($matches[0][$i], $pl, $string);
179             }
180         }
181         $this->_html = $string;
182         return true;
183     }
184
185    /**
186     * write a patForms template after extracting the elements from the
187     * template.
188     *
189     * This allows you to later add additional information.
190     *
191     * @access    public
192     * @param    string        filename
193     * @param    string        namespace
194     * @return    boolean
195     */   
196     function writeFormTemplate( $file, $ns = 'patForms' )
197     {
198         $patForms = &$this->getForm();
199         $cnt    =    count( $patForms->elements );
200         for ($i=0; $i < $cnt; $i++) {
201             // first, serialize the element as this also initializes the attribute collection.
202             $serialized = trim($patForms->elements[$i]->toXML($ns));
203             
204             if ($serialized === false) {
205                 patErrorManager::raiseWarning(
206                     PATFORMS_PARSER_ERROR_ELEMENT_NOT_SERIALIZEABLE,
207                     "Element '".get_class( $patForms->elements[$i] )."' could not return serialized data."
208                 );
209                 continue;
210             }
211             $serializedElements[($patForms->elements[$i]->getId())] = $serialized;
212         }
213
214         $html = $this->getHTML();
215         foreach ($serializedElements as $id => $element) {
216             $varName = $this->_getPlaceholderForElement($id);
217             $html = str_replace($varName, $element, $html);
218         }
219
220         $this->_writeToFile($this->_adjustFilename($file), $html);
221         return true;
222     }
223
224    /**
225     * parse an attribute string and build an array
226     *
227     * @access    private
228     * @param    string    attribute string
229     * @param    array    attribute array
230     */
231     function _parseAttributes( $string )
232     {
233         $string = trim($string);
234
235         //    Check for trailing slash, if tag was an empty XML Tag
236         if (substr( $string, -1 ) == "/") {
237             $string    = trim( substr( $string, 0, strlen( $string )-1 ) );
238         }
239
240         $pairs = explode('" ', $string);
241         
242         for    ($i = 0; $i < count($pairs); $i++) {
243             $pair = explode('=', trim(str_replace('"', '', $pairs[$i])));
244
245             if (count($pair) == 1) {
246                  $pair[1] = 'yes';
247             }
248
249             if (strstr($pair[0], ' ')) {
250                 $tmp = explode(' ', $pair[0]);
251                 for ($j = 0; $j < (count($tmp)-1); $j++) {
252                     $attributes[strtolower($tmp[$j])] = 'yes';
253                 }
254                 $pair[0] = $tmp[$j];
255             }
256
257             $attributes[strtolower($pair[0])] = $pair[1];
258         }
259         return    $attributes;
260     }
261 }
262 ?>
Note: See TracBrowser for help on using the browser.