1<?php
2
3namespace Sabre\DAV\Xml\Property;
4
5use Sabre\DAV\Browser\HtmlOutput;
6use Sabre\DAV\Browser\HtmlOutputHelper;
7use Sabre\Xml\Element;
8use Sabre\Xml\Reader;
9use Sabre\Xml\Writer;
10
11/**
12 * Href property
13 *
14 * This class represents any WebDAV property that contains a {DAV:}href
15 * element, and there are many.
16 *
17 * It can support either 1 or more hrefs. If while unserializing no valid
18 * {DAV:}href elements were found, this property will unserialize itself as
19 * null.
20 *
21 * @copyright Copyright (C) 2007-2015 fruux GmbH (https://fruux.com/).
22 * @author Evert Pot (http://www.rooftopsolutions.nl/)
23 * @license http://sabre.io/license/ Modified BSD License
24 */
25class Href implements Element, HtmlOutput {
26
27    /**
28     * List of uris
29     *
30     * @var array
31     */
32    protected $hrefs;
33
34    /**
35     * Automatically prefix the url with the server base directory
36     *
37     * @var bool
38     */
39    protected $autoPrefix = true;
40
41    /**
42     * Constructor
43     *
44     * You must either pass a string for a single href, or an array of hrefs.
45     *
46     * If auto-prefix is set to false, the hrefs will be treated as absolute
47     * and not relative to the servers base uri.
48     *
49     * @param string|string[] $href
50     * @param bool $autoPrefix
51     */
52    function __construct($hrefs, $autoPrefix = true) {
53
54        if (is_string($hrefs)) {
55            $hrefs = [$hrefs];
56        }
57        $this->hrefs = $hrefs;
58        $this->autoPrefix = $autoPrefix;
59
60
61    }
62
63    /**
64     * Returns the first Href.
65     *
66     * @return string
67     */
68    function getHref() {
69
70        return $this->hrefs[0];
71
72    }
73
74    /**
75     * Returns the hrefs as an array
76     *
77     * @return array
78     */
79    function getHrefs() {
80
81        return $this->hrefs;
82
83    }
84
85    /**
86     * The xmlSerialize metod is called during xml writing.
87     *
88     * Use the $writer argument to write its own xml serialization.
89     *
90     * An important note: do _not_ create a parent element. Any element
91     * implementing XmlSerializble should only ever write what's considered
92     * its 'inner xml'.
93     *
94     * The parent of the current element is responsible for writing a
95     * containing element.
96     *
97     * This allows serializers to be re-used for different element names.
98     *
99     * If you are opening new elements, you must also close them again.
100     *
101     * @param Writer $writer
102     * @return void
103     */
104    function xmlSerialize(Writer $writer) {
105
106        foreach ($this->getHrefs() as $href) {
107            if ($this->autoPrefix) {
108                $href = $writer->contextUri . $href;
109            }
110            $writer->writeElement('{DAV:}href', $href);
111        }
112
113    }
114
115    /**
116     * Generate html representation for this value.
117     *
118     * The html output is 100% trusted, and no effort is being made to sanitize
119     * it. It's up to the implementor to sanitize user provided values.
120     *
121     * The output must be in UTF-8.
122     *
123     * The baseUri parameter is a url to the root of the application, and can
124     * be used to construct local links.
125     *
126     * @param HtmlOutputHelper $html
127     * @return string
128     */
129    function toHtml(HtmlOutputHelper $html) {
130
131        $links = [];
132        foreach ($this->getHrefs() as $href) {
133            $links[] = $html->link($href);
134        }
135        return implode('<br />', $links);
136
137    }
138
139    /**
140     * The deserialize method is called during xml parsing.
141     *
142     * This method is called statictly, this is because in theory this method
143     * may be used as a type of constructor, or factory method.
144     *
145     * Often you want to return an instance of the current class, but you are
146     * free to return other data as well.
147     *
148     * You are responsible for advancing the reader to the next element. Not
149     * doing anything will result in a never-ending loop.
150     *
151     * If you just want to skip parsing for this element altogether, you can
152     * just call $reader->next();
153     *
154     * $reader->parseInnerTree() will parse the entire sub-tree, and advance to
155     * the next element.
156     *
157     * @param Reader $reader
158     * @return mixed
159     */
160    static function xmlDeserialize(Reader $reader) {
161
162        $hrefs = [];
163        foreach ((array)$reader->parseInnerTree() as $elem) {
164            if ($elem['name'] !== '{DAV:}href')
165                continue;
166
167            $hrefs[] = $elem['value'];
168
169        }
170        if ($hrefs) {
171            return new self($hrefs, false);
172        }
173
174    }
175
176}
177