DOMComment 和 DOMXPath的应用sample

symfony 1.0版本中的表单重填(当提交表单出现error的时候,要在表单中显示之前用户的输入)中的核心类:

/lib/symfony/util/sfFillInForm.class.php

 

  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, $formas $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', $elementas $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[$nameas $callable)
200       {
201         $value = call_user_func($callable, $value);
202       }
203     }
204 
205     return $value;
206   }
207 }
208 

 

 

posted @ 2010-08-02 15:03  rethink  阅读(380)  评论(0编辑  收藏  举报