symfony 1.0版本中的表单重填(当提交表单出现error的时候,要在表单中显示之前用户的输入)中的核心类:
/lib/symfony/util/sfFillInForm.class.php
<!--<br/ /><br/ />Code highlighting produced by Actipro CodeHighlighter (freeware)<br/ />http://www.CodeHighlighter.com/<br/ /><br/ />-->
1
<?
php
2
3 /*
4 * This file is part of the symfony package.
5 * (c) 2004-2006 Fabien Potencier <fabien.potencier@symfony-project.com>
6 *
7 * For the full copyright and license information, please view the LICENSE
8 * file that was distributed with this source code.
9 */
10
11 /* *
12 *
13 * @package symfony
14 * @subpackage util
15 * @author Fabien Potencier <fabien.potencier@symfony-project.com>
16 * @version SVN: $Id: sfFillInForm.class.php 2976 2006-12-08 19:11:36Z fabien $
17 */
18 class sfFillInForm
19 {
20 protected
21 $converters = array () ,
22 $skipFields = array () ,
23 $types = array ( ' text ' , ' checkbox ' , ' radio ' , ' hidden ' , ' password ' );
24
25 public function addConverter( $callable , $fields )
26 {
27 foreach (( array ) $fields as $field )
28 {
29 $this -> converters[ $field ][] = $callable ;
30 }
31 }
32
33 public function setSkipFields( $fields )
34 {
35 $this -> skipFields = $fields ;
36 }
37
38 public function setTypes( $types )
39 {
40 $this -> types = $types ;
41 }
42
43 public function fillInHtml( $html , $formName , $formId , $values )
44 {
45 $dom = new DomDocument( ' 1.0 ' , sfConfig :: get( ' sf_charset ' , ' UTF-8 ' ));
46 @ $dom -> loadHTML( $html );
47
48 $dom = $this -> fillInDom( $dom , $formName , $formId , $values );
49
50 return $dom -> saveHTML();
51 }
52
53 public function fillInXml( $xml , $formName , $formId , $values )
54 {
55 $dom = new DomDocument( ' 1.0 ' , sfConfig :: get( ' sf_charset ' , ' UTF-8 ' ));
56 @ $dom -> loadXML( $xml );
57
58 $dom = $this -> fillInDom( $dom , $formName , $formId , $values );
59
60 return $dom -> saveXML();
61 }
62
63 public function fillInDom( $dom , $formName , $formId , $values )
64 {
65 $xpath = new DomXPath( $dom );
66
67 $query = ' descendant::input[@name and (not(@type) ' ;
68 foreach ( $this -> types as $type )
69 {
70 $query .= ' or @type=" ' . $type . ' " ' ;
71 }
72 $query .= ' )] | descendant::textarea[@name] | descendant::select[@name] ' ;
73
74 // find our form
75 if ( $formName )
76 {
77 $xpath_query = ' //form[@name=" ' . $formName . ' "] ' ;
78 }
79 elseif ( $formId )
80 {
81 $xpath_query = ' //form[@id=" ' . $formId . ' "] ' ;
82 }
83 else
84 {
85 $xpath_query = ' //form ' ;
86 }
87
88 $form = $xpath -> query( $xpath_query ) -> item( 0 );
89 if ( ! $form )
90 {
91 if ( ! $formName && ! $formId )
92 {
93 throw new sfException( ' No form found in this page ' );
94 }
95 else
96 {
97 throw new sfException( sprintf ( ' The form "%s" cannot be found ' , $formName ? $formName : $formId ));
98 }
99 }
100
101 foreach ( $xpath -> query( $query , $form ) as $element )
102 {
103 $name = ( string ) $element -> getAttribute( ' name ' );
104 $value = ( string ) $element -> getAttribute( ' value ' );
105 $type = ( string ) $element -> getAttribute( ' type ' );
106
107 // skip fields
108 if ( ! $this -> hasValue( $values , $name ) || in_array ( $name , $this -> skipFields))
109 {
110 continue ;
111 }
112
113 if ( $element -> nodeName == ' input ' )
114 {
115 if ( $type == ' checkbox ' || $type == ' radio ' )
116 {
117 // checkbox and radio
118 $element -> removeAttribute( ' checked ' );
119 if ( $this -> hasValue( $values , $name ) && ( $this -> getValue( $values , $name ) == $value || ! $element -> hasAttribute( ' value ' )))
120 {
121 $element -> setAttribute( ' checked ' , ' checked ' );
122 }
123 }
124 else
125 {
126 // text input
127 $element -> removeAttribute( ' value ' );
128 if ( $this -> hasValue( $values , $name ))
129 {
130 $element -> setAttribute( ' value ' , $this -> escapeValue( $this -> getValue( $values , $name ) , $name ));
131 }
132 }
133 }
134 else if ( $element -> nodeName == ' textarea ' )
135 {
136 $el = $element -> cloneNode( false );
137 $el -> appendChild( $dom -> createTextNode( $this -> escapeValue( $this -> getValue( $values , $name ) , $name )));
138 $element -> parentNode -> replaceChild( $el , $element );
139 }
140 else if ( $element -> nodeName == ' select ' )
141 {
142 // select
143 $value = $this -> getValue( $values , $name );
144 $multiple = $element -> hasAttribute( ' multiple ' );
145 foreach ( $xpath -> query( ' descendant::option ' , $element ) as $option )
146 {
147 $option -> removeAttribute( ' selected ' );
148 if ( $multiple && is_array ( $value ))
149 {
150 if ( in_array ( $option -> getAttribute( ' value ' ) , $value ))
151 {
152 $option -> setAttribute( ' selected ' , ' selected ' );
153 }
154 }
155 else if ( $value == $option -> getAttribute( ' value ' ))
156 {
157 $option -> setAttribute( ' selected ' , ' selected ' );
158 }
159 }
160 }
161 }
162
163 return $dom ;
164 }
165
166 protected function hasValue( $values , $name )
167 {
168 if ( array_key_exists ( $name , $values ))
169 {
170 return true ;
171 }
172
173 return null !== sfToolkit :: getArrayValueForPath( $values , $name );
174 }
175
176 protected function getValue( $values , $name )
177 {
178 if ( array_key_exists ( $name , $values ))
179 {
180 return $values [ $name ];
181 }
182
183 return sfToolkit :: getArrayValueForPath( $values , $name );
184 }
185
186 protected function escapeValue( $value , $name )
187 {
188 if ( function_exists ( ' iconv ' ) && strtolower (sfConfig :: get( ' sf_charset ' )) != ' utf-8 ' )
189 {
190 $new_value = iconv (sfConfig :: get( ' sf_charset ' ) , ' UTF-8 ' , $value );
191 if ( false !== $new_value )
192 {
193 $value = $new_value ;
194 }
195 }
196
197 if ( isset ( $this -> converters[ $name ]))
198 {
199 foreach ( $this -> converters[ $name ] as $callable )
200 {
201 $value = call_user_func ( $callable , $value );
202 }
203 }
204
205 return $value ;
206 }
207 }
208
2
3 /*
4 * This file is part of the symfony package.
5 * (c) 2004-2006 Fabien Potencier <fabien.potencier@symfony-project.com>
6 *
7 * For the full copyright and license information, please view the LICENSE
8 * file that was distributed with this source code.
9 */
10
11 /* *
12 *
13 * @package symfony
14 * @subpackage util
15 * @author Fabien Potencier <fabien.potencier@symfony-project.com>
16 * @version SVN: $Id: sfFillInForm.class.php 2976 2006-12-08 19:11:36Z fabien $
17 */
18 class sfFillInForm
19 {
20 protected
21 $converters = array () ,
22 $skipFields = array () ,
23 $types = array ( ' text ' , ' checkbox ' , ' radio ' , ' hidden ' , ' password ' );
24
25 public function addConverter( $callable , $fields )
26 {
27 foreach (( array ) $fields as $field )
28 {
29 $this -> converters[ $field ][] = $callable ;
30 }
31 }
32
33 public function setSkipFields( $fields )
34 {
35 $this -> skipFields = $fields ;
36 }
37
38 public function setTypes( $types )
39 {
40 $this -> types = $types ;
41 }
42
43 public function fillInHtml( $html , $formName , $formId , $values )
44 {
45 $dom = new DomDocument( ' 1.0 ' , sfConfig :: get( ' sf_charset ' , ' UTF-8 ' ));
46 @ $dom -> loadHTML( $html );
47
48 $dom = $this -> fillInDom( $dom , $formName , $formId , $values );
49
50 return $dom -> saveHTML();
51 }
52
53 public function fillInXml( $xml , $formName , $formId , $values )
54 {
55 $dom = new DomDocument( ' 1.0 ' , sfConfig :: get( ' sf_charset ' , ' UTF-8 ' ));
56 @ $dom -> loadXML( $xml );
57
58 $dom = $this -> fillInDom( $dom , $formName , $formId , $values );
59
60 return $dom -> saveXML();
61 }
62
63 public function fillInDom( $dom , $formName , $formId , $values )
64 {
65 $xpath = new DomXPath( $dom );
66
67 $query = ' descendant::input[@name and (not(@type) ' ;
68 foreach ( $this -> types as $type )
69 {
70 $query .= ' or @type=" ' . $type . ' " ' ;
71 }
72 $query .= ' )] | descendant::textarea[@name] | descendant::select[@name] ' ;
73
74 // find our form
75 if ( $formName )
76 {
77 $xpath_query = ' //form[@name=" ' . $formName . ' "] ' ;
78 }
79 elseif ( $formId )
80 {
81 $xpath_query = ' //form[@id=" ' . $formId . ' "] ' ;
82 }
83 else
84 {
85 $xpath_query = ' //form ' ;
86 }
87
88 $form = $xpath -> query( $xpath_query ) -> item( 0 );
89 if ( ! $form )
90 {
91 if ( ! $formName && ! $formId )
92 {
93 throw new sfException( ' No form found in this page ' );
94 }
95 else
96 {
97 throw new sfException( sprintf ( ' The form "%s" cannot be found ' , $formName ? $formName : $formId ));
98 }
99 }
100
101 foreach ( $xpath -> query( $query , $form ) as $element )
102 {
103 $name = ( string ) $element -> getAttribute( ' name ' );
104 $value = ( string ) $element -> getAttribute( ' value ' );
105 $type = ( string ) $element -> getAttribute( ' type ' );
106
107 // skip fields
108 if ( ! $this -> hasValue( $values , $name ) || in_array ( $name , $this -> skipFields))
109 {
110 continue ;
111 }
112
113 if ( $element -> nodeName == ' input ' )
114 {
115 if ( $type == ' checkbox ' || $type == ' radio ' )
116 {
117 // checkbox and radio
118 $element -> removeAttribute( ' checked ' );
119 if ( $this -> hasValue( $values , $name ) && ( $this -> getValue( $values , $name ) == $value || ! $element -> hasAttribute( ' value ' )))
120 {
121 $element -> setAttribute( ' checked ' , ' checked ' );
122 }
123 }
124 else
125 {
126 // text input
127 $element -> removeAttribute( ' value ' );
128 if ( $this -> hasValue( $values , $name ))
129 {
130 $element -> setAttribute( ' value ' , $this -> escapeValue( $this -> getValue( $values , $name ) , $name ));
131 }
132 }
133 }
134 else if ( $element -> nodeName == ' textarea ' )
135 {
136 $el = $element -> cloneNode( false );
137 $el -> appendChild( $dom -> createTextNode( $this -> escapeValue( $this -> getValue( $values , $name ) , $name )));
138 $element -> parentNode -> replaceChild( $el , $element );
139 }
140 else if ( $element -> nodeName == ' select ' )
141 {
142 // select
143 $value = $this -> getValue( $values , $name );
144 $multiple = $element -> hasAttribute( ' multiple ' );
145 foreach ( $xpath -> query( ' descendant::option ' , $element ) as $option )
146 {
147 $option -> removeAttribute( ' selected ' );
148 if ( $multiple && is_array ( $value ))
149 {
150 if ( in_array ( $option -> getAttribute( ' value ' ) , $value ))
151 {
152 $option -> setAttribute( ' selected ' , ' selected ' );
153 }
154 }
155 else if ( $value == $option -> getAttribute( ' value ' ))
156 {
157 $option -> setAttribute( ' selected ' , ' selected ' );
158 }
159 }
160 }
161 }
162
163 return $dom ;
164 }
165
166 protected function hasValue( $values , $name )
167 {
168 if ( array_key_exists ( $name , $values ))
169 {
170 return true ;
171 }
172
173 return null !== sfToolkit :: getArrayValueForPath( $values , $name );
174 }
175
176 protected function getValue( $values , $name )
177 {
178 if ( array_key_exists ( $name , $values ))
179 {
180 return $values [ $name ];
181 }
182
183 return sfToolkit :: getArrayValueForPath( $values , $name );
184 }
185
186 protected function escapeValue( $value , $name )
187 {
188 if ( function_exists ( ' iconv ' ) && strtolower (sfConfig :: get( ' sf_charset ' )) != ' utf-8 ' )
189 {
190 $new_value = iconv (sfConfig :: get( ' sf_charset ' ) , ' UTF-8 ' , $value );
191 if ( false !== $new_value )
192 {
193 $value = $new_value ;
194 }
195 }
196
197 if ( isset ( $this -> converters[ $name ]))
198 {
199 foreach ( $this -> converters[ $name ] as $callable )
200 {
201 $value = call_user_func ( $callable , $value );
202 }
203 }
204
205 return $value ;
206 }
207 }
208