1: <?php
2: /**
3: * Handles composite attributes.
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: * Handles composite attributes.
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_Composite
32: extends Horde_Kolab_Format_Xml_Type_Base
33: {
34: /**
35: * The elements of the composite attribute.
36: *
37: * @var array
38: */
39: protected $elements;
40:
41: /**
42: * Indicate which value type is expected.
43: *
44: * @var int
45: */
46: protected $value = Horde_Kolab_Format_Xml::VALUE_MAYBE_MISSING;
47:
48: /**
49: * A default value if required.
50: *
51: * @var string
52: */
53: protected $default;
54:
55: /**
56: * Should the velues be merged into the parent attributes?
57: *
58: * @var boolean
59: */
60: protected $merge = false;
61:
62: /**
63: * Load the node value from the Kolab object.
64: *
65: * @param string $name The name of the the
66: * attribute to be fetched.
67: * @param array &$attributes The data array that
68: * holds all attribute
69: * values.
70: * @param DOMNode $parent_node The parent node of the
71: * node to be loaded.
72: * @param Horde_Kolab_Format_Xml_Helper $helper A XML helper instance.
73: * @param array $params Additiona parameters for
74: * this parse operation.
75: *
76: * @return DOMNode|boolean The named DOMNode or false if no node value was
77: * found.
78: */
79: public function load(
80: $name,
81: &$attributes,
82: $parent_node,
83: Horde_Kolab_Format_Xml_Helper $helper,
84: $params = array()
85: )
86: {
87: if ($node = $helper->findNodeRelativeTo('./' . $name, $parent_node)) {
88: $result = $this->loadNodeValue($node, $helper, $params);
89: } else {
90: $result = $this->loadMissing($name, $params);
91: }
92: if (!$this->merge) {
93: $attributes[$name] = $result;
94: } else {
95: $attributes = array_merge($attributes, $result);
96: }
97: return false;
98: }
99:
100: /**
101: * Load the value of a node.
102: *
103: * @param DOMNode $node Retrieve value for this node.
104: * @param Horde_Kolab_Format_Xml_Helper $helper A XML helper instance.
105: * @param array $params Additiona parameters for
106: * this parse operation.
107: *
108: * @return mixed|null The value or null if no value was found.
109: */
110: public function loadNodeValue(
111: $node,
112: Horde_Kolab_Format_Xml_Helper $helper,
113: $params = array()
114: )
115: {
116: $result = array();
117: foreach ($this->elements as $sub_name => $sub_type) {
118: $this->createSubType($sub_type, $params)
119: ->load($sub_name, $result, $node, $helper, $params);
120: }
121: return $result;
122: }
123:
124: /**
125: * Update the specified attribute.
126: *
127: * @param string $name The name of the the
128: * attribute to be updated.
129: * @param array $attributes The data array that holds
130: * all attribute values.
131: * @param DOMNode $parent_node The parent node of the
132: * node that should be
133: * updated.
134: * @param Horde_Kolab_Format_Xml_Helper $helper A XML helper instance.
135: * @param array $params Additional parameters
136: * for this write operation.
137: *
138: * @return DOMNode|boolean The new/updated child node or false if this
139: * failed.
140: *
141: * @throws Horde_Kolab_Format_Exception If converting the data to XML failed.
142: */
143: public function save(
144: $name,
145: $attributes,
146: $parent_node,
147: Horde_Kolab_Format_Xml_Helper $helper,
148: $params = array()
149: )
150: {
151: $node = $helper->findNodeRelativeTo(
152: './' . $name, $parent_node
153: );
154:
155: if (!$this->merge && !isset($attributes[$name])) {
156: if ($node === false) {
157: if ($this->value == Horde_Kolab_Format_Xml::VALUE_MAYBE_MISSING ||
158: ($this->value == Horde_Kolab_Format_Xml::VALUE_NOT_EMPTY &&
159: $this->isRelaxed($params))) {
160: return false;
161: }
162: } else {
163: if ($this->value == Horde_Kolab_Format_Xml::VALUE_MAYBE_MISSING) {
164: /** Client indicates that the value should get removed */
165: $helper->removeNodes($parent_node, $name);
166: return false;
167: } else {
168: return $node;
169: }
170: }
171: }
172:
173: return $this->saveNodeValue(
174: $name,
175: $this->generateWriteValue($name, $attributes, $params),
176: $parent_node,
177: $helper,
178: $params,
179: $node
180: );
181: }
182:
183: /**
184: * Update the specified attribute.
185: *
186: * @param string $name The name of the attribute
187: * to be updated.
188: * @param mixed $value The value to store.
189: * @param DOMNode $parent_node The parent node of the
190: * node that should be
191: * updated.
192: * @param Horde_Kolab_Format_Xml_Helper $helper A XML helper instance.
193: * @param array $params The parameters for this
194: * write operation.
195: * @param DOMNode|NULL $old_node The previous value (or
196: * null if there is none).
197: *
198: * @return DOMNode|boolean The new/updated child node or false if this
199: * failed.
200: *
201: * @throws Horde_Kolab_Format_Exception If converting the data to XML failed.
202: */
203: public function saveNodeValue(
204: $name,
205: $value,
206: $parent_node,
207: Horde_Kolab_Format_Xml_Helper $helper,
208: $params = array(),
209: $old_node = false
210: )
211: {
212: if ($old_node === false) {
213: $node = $helper->createNewNode($parent_node, $name);
214: $this->_writeComposite($node, $name, $value, $helper, $params);
215: return $node;
216: } else {
217: $this->_writeComposite($old_node, $name, $value, $helper, $params);
218: return $old_node;
219: }
220: }
221:
222: /**
223: * Write a composite value to a parent node.
224: *
225: * @param DOMNode $parent_node The parent node of the
226: * node that should be
227: * updated.
228: * @param string $name The name of the the
229: * attribute to be updated.
230: * @param array $values The values to write.
231: * @param Horde_Kolab_Format_Xml_Helper $helper A XML helper instance.
232: * @param array $params The parameters for this
233: * write operation.
234: *
235: * @return array The list of new/updated child nodes.
236: *
237: * @throws Horde_Kolab_Format_Exception If converting the data to XML failed.
238: */
239: private function _writeComposite($parent_node, $name, $values,
240: Horde_Kolab_Format_Xml_Helper $helper,
241: $params)
242: {
243: foreach ($this->elements as $sub_name => $sub_type) {
244: $this->createSubType($sub_type, $params)
245: ->save($sub_name, $values, $parent_node, $helper, $params);
246: }
247: }
248:
249: /**
250: * Generate the value that should be written to the node. Override in the
251: * extending classes.
252: *
253: * @param string $name The name of the the attribute
254: * to be updated.
255: * @param array $attributes The data array that holds all
256: * attribute values.
257: * @param array $params The parameters for this write operation.
258: *
259: * @return mixed The value to be written.
260: */
261: protected function generateWriteValue($name, $attributes, $params)
262: {
263: if ($this->merge) {
264: return $attributes;
265: }
266: if (isset($attributes[$name])) {
267: return $attributes[$name];
268: } else {
269: return $this->loadMissing($name, $params);
270: }
271: }
272: }
273: