1<?php
2/**
3 * Handles the document root.
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 the document root.
16 *
17 * Copyright 2011-2016 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 * @category Kolab
24 * @package  Kolab_Format
25 * @author   Gunnar Wrobel <wrobel@pardus.de>
26 * @license  http://www.horde.org/licenses/lgpl21 LGPL
27 * @link     http://www.horde.org/libraries/Horde_Kolab_Format
28 */
29class Horde_Kolab_Format_Xml_Type_Root
30extends Horde_Kolab_Format_Xml_Type_Composite
31{
32    /**
33     * Indicate which value type is expected.
34     *
35     * @var int
36     */
37    protected $value = Horde_Kolab_Format_Xml::VALUE_NOT_EMPTY;
38
39    /**
40     * Should the velues be merged into the parent attributes?
41     *
42     * @var boolean
43     */
44    protected $merge = true;
45
46    /**
47     * Basic attributes in any Kolab object
48     *
49     * @var array
50     */
51    private $_attributes_basic = array(
52        'uid'                    => 'Horde_Kolab_Format_Xml_Type_Uid',
53        'body'                   => 'Horde_Kolab_Format_Xml_Type_String_Empty',
54        'categories'             => 'Horde_Kolab_Format_Xml_Type_String_Empty_List',
55        'creation-date'          => 'Horde_Kolab_Format_Xml_Type_CreationDate',
56        'last-modification-date' => 'Horde_Kolab_Format_Xml_Type_ModificationDate',
57        'sensitivity'            => 'Horde_Kolab_Format_Xml_Type_Sensitivity',
58        'inline-attachment'      => 'Horde_Kolab_Format_Xml_Type_Multiple_String',
59        'link-attachment'        => 'Horde_Kolab_Format_Xml_Type_Multiple_String',
60        'product-id'             => 'Horde_Kolab_Format_Xml_Type_ProductId',
61    );
62
63    /**
64     * Load the node value from the Kolab object.
65     *
66     * @param string                        $name        The name of the the
67     *                                                   attribute to be fetched.
68     * @param array                         &$attributes The data array that
69     *                                                   holds all attribute
70     *                                                   values.
71     * @param DOMNode                       $parent_node The parent node of the
72     *                                                   node to be loaded.
73     * @param Horde_Kolab_Format_Xml_Helper $helper      A XML helper instance.
74     * @param array                         $params      Additiona parameters for
75     *                                                   this parse operation.
76     *
77     * @return DOMNode|boolean The named DOMNode or false if no node value was
78     *                         found.
79     */
80    public function load(
81        $name,
82        &$attributes,
83        $parent_node,
84        Horde_Kolab_Format_Xml_Helper $helper,
85        $params = array()
86    )
87    {
88        if (!($root = $helper->findNode('/' . $name))) {
89            throw new Horde_Kolab_Format_Exception_InvalidRoot(
90                sprintf('Missing root node "%s"!', $name)
91            );
92        }
93        $attributes['_format-version'] = $root->getAttribute('version');
94        $attributes['_api-version'] = $params['api-version'];
95        if (!$this->isRelaxed($params)) {
96            if (version_compare($params['expected-version'], $attributes['_format-version']) < 0) {
97                throw new Horde_Kolab_Format_Exception_InvalidRoot(
98                    sprintf(
99                        'Not attempting to read higher root version of %s with our version %s!',
100                        $attributes['_format-version'],
101                        $params['expected-version']
102                    )
103                );
104            }
105        }
106        $this->_prepareCompositeParameters(
107            $params, $attributes['_format-version']
108        );
109        parent::load($name, $attributes, $parent_node, $helper, $params);
110        return $root;
111    }
112
113    /**
114     * Update the specified attribute.
115     *
116     * @param string                        $name        The name of the the
117     *                                                   attribute to be updated.
118     * @param array                         $attributes  The data array that holds
119     *                                                   all attribute values.
120     * @param DOMNode                       $parent_node The parent node of the
121     *                                                   node that should be
122     *                                                   updated.
123     * @param Horde_Kolab_Format_Xml_Helper $helper      A XML helper instance.
124     * @param array                         $params      Additional parameters
125     *                                                   for this write operation.
126     *
127     * @return DOMNode|boolean The new/updated child node or false if this
128     *                         failed.
129     *
130     * @throws Horde_Kolab_Format_Exception If converting the data to XML failed.
131     */
132    public function save(
133        $name,
134        $attributes,
135        $parent_node,
136        Horde_Kolab_Format_Xml_Helper $helper,
137        $params = array()
138    )
139    {
140        if (!($root = $helper->findNode('/' . $name, $parent_node))) {
141            $root = $helper->createNewNode($parent_node, $name);
142            $root->setAttribute('version', $params['expected-version']);
143        } else {
144            if (!$this->isRelaxed($params)) {
145                if (version_compare($params['expected-version'], $root->getAttribute('version')) < 0) {
146                    throw new Horde_Kolab_Format_Exception_InvalidRoot(
147                        sprintf(
148                            'Not attempting to overwrite higher root version of %s with our version %s!',
149                            $root->getAttribute('version'),
150                            $params['expected-version']
151                        )
152                    );
153                }
154            }
155            if ($params['expected-version'] != $root->getAttribute('version')) {
156                $root->setAttribute('version', $params['expected-version']);
157            }
158        }
159        $this->_prepareCompositeParameters(
160            $params, $params['expected-version']
161        );
162        parent::save($name, $attributes, $parent_node, $helper, $params);
163        return $root;
164    }
165
166    /**
167     * Prepare the parameters for the parent composite handler.
168     *
169     * @param array  &$params The parameters for this operation.
170     * @param string $version The format version of the document.
171     *
172     * @return NULL
173     */
174    private function _prepareCompositeParameters(&$params, $version)
175    {
176        $params['format-version'] = $version;
177
178        $this->elements = $this->_attributes_basic;
179        if (isset($params['attributes-specific'])) {
180            $this->elements = array_merge(
181                $this->elements, $params['attributes-specific']
182            );
183        }
184        if (isset($params['attributes-application'])) {
185            $this->elements = array_merge(
186                $this->elements, $params['attributes-application']
187            );
188        }
189    }
190}
191