1: <?php
2: /**
3: * Utilities for the various XML handlers.
4: *
5: * PHP version 5
6: *
7: * @category Kolab
8: * @package Kolab_Format
9: * @author Gunnar Wrobel <wrobel@pardus.de>
10: * @license http://www.horde.org/licenses/lgpl21 LGPL
11: * @link http://www.horde.org/libraries/Horde_Kolab_Format
12: */
13:
14: /**
15: * Utilities for the various XML handlers.
16: *
17: * Copyright 2011-2012 Horde LLC (http://www.horde.org/)
18: *
19: * See the enclosed file COPYING for license information (LGPL). If you did not
20: * receive this file, see
21: * http://www.horde.org/licenses/lgpl21.
22: *
23: * @since Horde_Kolab_Format 1.1.0
24: *
25: * @category Kolab
26: * @package Kolab_Format
27: * @author Gunnar Wrobel <wrobel@pardus.de>
28: * @license http://www.horde.org/licenses/lgpl21 LGPL
29: * @link http://www.horde.org/libraries/Horde_Kolab_Format
30: */
31: class Horde_Kolab_Format_Xml_Type_Base
32: {
33: /**
34: * The factory for any additional objects required.
35: *
36: * @var Horde_Kolab_Format_Factory
37: */
38: private $_factory;
39:
40: /**
41: * Indicate which value type is expected.
42: *
43: * @var int
44: */
45: protected $value = Horde_Kolab_Format_Xml::VALUE_MAYBE_MISSING;
46:
47: /**
48: * A default value if required.
49: *
50: * @var string
51: */
52: protected $default;
53:
54: /**
55: * Collects xml types already created.
56: *
57: * @var array
58: */
59: static private $_xml_types;
60:
61: /**
62: * Constructor
63: *
64: * @param Horde_Kolab_Format_Factory $factory The factory for any additional
65: * objects required.
66: */
67: public function __construct($factory)
68: {
69: $this->_factory = $factory;
70: }
71:
72: /**
73: * Load the node value from the Kolab object.
74: *
75: * @param string $name The name of the the
76: * attribute to be fetched.
77: * @param array &$attributes The data array that
78: * holds all attribute
79: * values.
80: * @param DOMNode $parent_node The parent node of the
81: * node to be loaded.
82: * @param Horde_Kolab_Format_Xml_Helper $helper A XML helper instance.
83: * @param array $params Additiona parameters for
84: * this parse operation.
85: *
86: * @return DOMNode|boolean The named DOMNode or false if no node value was
87: * found.
88: */
89: public function load($name, &$attributes, $parent_node,
90: Horde_Kolab_Format_Xml_Helper $helper,
91: $params = array())
92: {
93: if ($node = $helper->findNodeRelativeTo('./' . $name, $parent_node)) {
94: if (($value = $this->loadNodeValue($node, $helper, $params)) !== null) {
95: $attributes[$name] = $value;
96: return $node;
97: }
98: }
99: return false;
100: }
101:
102: /**
103: * Load the value of a node.
104: *
105: * @param DOMNode $node Retrieve value for this node.
106: * @param Horde_Kolab_Format_Xml_Helper $helper A XML helper instance.
107: * @param array $params Additiona parameters for
108: * this parse operation.
109: *
110: * @return mixed|null The value or null if no value was found.
111: */
112: public function loadNodeValue($node, Horde_Kolab_Format_Xml_Helper $helper,
113: $params = array())
114: {
115: return $helper->fetchNodeValue($node);
116: }
117:
118: /**
119: * Load a default value for a node.
120: *
121: * @param string $name The attribute name.
122: * @param array $params The parameters for the current operation.
123: *
124: * @return mixed The default value.
125: *
126: * @throws Horde_Kolab_Format_Exception In case the attribute may not be
127: * missing or the default value was
128: * left undefined.
129: */
130: protected function loadMissing($name, $params)
131: {
132: if ($this->value == Horde_Kolab_Format_Xml::VALUE_NOT_EMPTY
133: && !$this->isRelaxed($params)) {
134: throw new Horde_Kolab_Format_Exception_MissingValue($name);
135: }
136: if ($this->value == Horde_Kolab_Format_Xml::VALUE_DEFAULT) {
137: return $this->default;
138: }
139: }
140:
141: /**
142: * Update the specified attribute.
143: *
144: * @param string $name The name of the the
145: * attribute to be updated.
146: * @param array $attributes The data array that holds
147: * all attribute values.
148: * @param DOMNode $parent_node The parent node of the
149: * node that should be
150: * updated.
151: * @param Horde_Kolab_Format_Xml_Helper $helper A XML helper instance.
152: * @param array $params Additional parameters
153: * for this write operation.
154: *
155: * @return DOMNode|boolean The new/updated child node or false if this
156: * failed.
157: *
158: * @throws Horde_Kolab_Format_Exception If converting the data to XML failed.
159: */
160: public function save($name, $attributes, $parent_node,
161: Horde_Kolab_Format_Xml_Helper $helper,
162: $params = array())
163: {
164: $node = $helper->findNodeRelativeTo(
165: './' . $name, $parent_node
166: );
167: $result = $this->saveNodeValue(
168: $name,
169: $this->generateWriteValue($name, $attributes, $params),
170: $parent_node,
171: $helper,
172: $params,
173: $node
174: );
175: return ($node !== false) ? $node : $result;
176: }
177:
178: /**
179: * Generate the value that should be written to the node. Override in the
180: * extending classes.
181: *
182: * @param string $name The name of the the attribute
183: * to be updated.
184: * @param array $attributes The data array that holds all
185: * attribute values.
186: * @param array $params The parameters for this write operation.
187: *
188: * @return mixed The value to be written.
189: */
190: protected function generateWriteValue($name, $attributes, $params)
191: {
192: if (isset($attributes[$name])) {
193: return $attributes[$name];
194: } else {
195: return '';
196: }
197: }
198:
199: /**
200: * Update the specified attribute.
201: *
202: * @param string $name The name of the attribute
203: * to be updated.
204: * @param mixed $value The value to store.
205: * @param DOMNode $parent_node The parent node of the
206: * node that should be
207: * updated.
208: * @param Horde_Kolab_Format_Xml_Helper $helper A XML helper instance.
209: * @param array $params The parameters for this
210: * write operation.
211: * @param DOMNode|NULL $old_node The previous value (or
212: * null if there is none).
213: *
214: * @return DOMNode|boolean The new/updated child node or false if this
215: * failed.
216: *
217: * @throws Horde_Kolab_Format_Exception If converting the data to XML failed.
218: */
219: public function saveNodeValue(
220: $name,
221: $value,
222: $parent_node,
223: Horde_Kolab_Format_Xml_Helper $helper,
224: $params = array(),
225: $old_node = false
226: )
227: {
228: if ($old_node === false) {
229: return $helper->storeNewNodeValue(
230: $parent_node, $name, $value
231: );
232: } else {
233: $helper->replaceFirstNodeTextValue($old_node, $value);
234: return $old_node;
235: }
236: }
237:
238: /**
239: * Validate that the parameter array contains all required parameters.
240: *
241: * @param string $key The parameter name.
242: * @param array $params The parameters.
243: * @param string $attribute The attribute name.
244: *
245: * @throws Horde_Kolab_Format_Exception In case required parameters are
246: * missing.
247: */
248: protected function checkMissing($key, $params, $attribute)
249: {
250: if (!isset($params[$key])) {
251: throw new Horde_Kolab_Format_Exception(
252: sprintf(
253: 'Required parameter "%s" missing (attribute: %s)!',
254: $key,
255: $attribute
256: )
257: );
258: }
259: }
260:
261: /**
262: * Return a parameter value.
263: *
264: * @param string $name The parameter name.
265: *
266: * @return mixed The parameter value.
267: */
268: public function getParam($name)
269: {
270: return isset($this->_params[$name]) ? $this->_params[$name] : null;
271: }
272:
273: /**
274: * Returns if the XML handling should be relaxed.
275: *
276: * @param array $params The parameters.
277: *
278: * @return boolean True if the XML should not be strict.
279: */
280: protected function isRelaxed($params)
281: {
282: return !empty($params['relaxed']);
283: }
284:
285: /**
286: * Create a handler for the sub type of this attribute.
287: *
288: * @param string $type The sub type.
289: * @param array $params Additional parameters.
290: *
291: * @return Horde_Kolab_Format_Xml_Type The sub type handler.
292: */
293: protected function createSubType($type, $params)
294: {
295: if (isset($params['api-version'])) {
296: $class = $type . '_V' . $params['api-version'];
297: } else {
298: $class = $type;
299: }
300: if (!isset(self::$_xml_types[$class])) {
301: self::$_xml_types[$class] = $this->_factory->createXmlType($type, $params);
302: }
303: return self::$_xml_types[$class];
304: }
305: }