1<?php
2
3namespace Sabre\DAVACL\Xml\Property;
4
5use Sabre\DAV;
6use Sabre\DAV\Browser\HtmlOutputHelper;
7use Sabre\DAV\Exception\BadRequest;
8use Sabre\Xml\Reader;
9use Sabre\Xml\Writer;
10
11/**
12 * Principal property
13 *
14 * The principal property represents a principal from RFC3744 (ACL).
15 * The property can be used to specify a principal or pseudo principals.
16 *
17 * @copyright Copyright (C) fruux GmbH (https://fruux.com/)
18 * @author Evert Pot (http://evertpot.com/)
19 * @license http://sabre.io/license/ Modified BSD License
20 */
21class Principal extends DAV\Xml\Property\Href {
22
23    /**
24     * To specify a not-logged-in user, use the UNAUTHENTICATED principal
25     */
26    const UNAUTHENTICATED = 1;
27
28    /**
29     * To specify any principal that is logged in, use AUTHENTICATED
30     */
31    const AUTHENTICATED = 2;
32
33    /**
34     * Specific principals can be specified with the HREF
35     */
36    const HREF = 3;
37
38    /**
39     * Everybody, basically
40     */
41    const ALL = 4;
42
43    /**
44     * Principal-type
45     *
46     * Must be one of the UNAUTHENTICATED, AUTHENTICATED or HREF constants.
47     *
48     * @var int
49     */
50    protected $type;
51
52    /**
53     * Creates the property.
54     *
55     * The 'type' argument must be one of the type constants defined in this class.
56     *
57     * 'href' is only required for the HREF type.
58     *
59     * @param int $type
60     * @param string|null $href
61     */
62    function __construct($type, $href = null) {
63
64        $this->type = $type;
65        if ($type === self::HREF && is_null($href)) {
66            throw new DAV\Exception('The href argument must be specified for the HREF principal type.');
67        }
68        if ($href) {
69            $href = rtrim($href, '/') . '/';
70            parent::__construct($href);
71        }
72
73    }
74
75    /**
76     * Returns the principal type
77     *
78     * @return int
79     */
80    function getType() {
81
82        return $this->type;
83
84    }
85
86
87    /**
88     * The xmlSerialize method is called during xml writing.
89     *
90     * Use the $writer argument to write its own xml serialization.
91     *
92     * An important note: do _not_ create a parent element. Any element
93     * implementing XmlSerializable should only ever write what's considered
94     * its 'inner xml'.
95     *
96     * The parent of the current element is responsible for writing a
97     * containing element.
98     *
99     * This allows serializers to be re-used for different element names.
100     *
101     * If you are opening new elements, you must also close them again.
102     *
103     * @param Writer $writer
104     * @return void
105     */
106    function xmlSerialize(Writer $writer) {
107
108        switch ($this->type) {
109
110            case self::UNAUTHENTICATED :
111                $writer->writeElement('{DAV:}unauthenticated');
112                break;
113            case self::AUTHENTICATED :
114                $writer->writeElement('{DAV:}authenticated');
115                break;
116            case self::HREF :
117                parent::xmlSerialize($writer);
118                break;
119            case self::ALL :
120                $writer->writeElement('{DAV:}all');
121                break;
122        }
123
124    }
125
126    /**
127     * Generate html representation for this value.
128     *
129     * The html output is 100% trusted, and no effort is being made to sanitize
130     * it. It's up to the implementor to sanitize user provided values.
131     *
132     * The output must be in UTF-8.
133     *
134     * The baseUri parameter is a url to the root of the application, and can
135     * be used to construct local links.
136     *
137     * @param HtmlOutputHelper $html
138     * @return string
139     */
140    function toHtml(HtmlOutputHelper $html) {
141
142        switch ($this->type) {
143
144            case self::UNAUTHENTICATED :
145                return '<em>unauthenticated</em>';
146            case self::AUTHENTICATED :
147                return '<em>authenticated</em>';
148            case self::HREF :
149                return parent::toHtml($html);
150            case self::ALL :
151                return '<em>all</em>';
152        }
153
154    }
155
156    /**
157     * The deserialize method is called during xml parsing.
158     *
159     * This method is called staticly, this is because in theory this method
160     * may be used as a type of constructor, or factory method.
161     *
162     * Often you want to return an instance of the current class, but you are
163     * free to return other data as well.
164     *
165     * Important note 2: You are responsible for advancing the reader to the
166     * next element. Not doing anything will result in a never-ending loop.
167     *
168     * If you just want to skip parsing for this element altogether, you can
169     * just call $reader->next();
170     *
171     * $reader->parseInnerTree() will parse the entire sub-tree, and advance to
172     * the next element.
173     *
174     * @param Reader $reader
175     * @return mixed
176     */
177    static function xmlDeserialize(Reader $reader) {
178
179        $tree = $reader->parseInnerTree()[0];
180
181        switch ($tree['name']) {
182            case '{DAV:}unauthenticated' :
183                return new self(self::UNAUTHENTICATED);
184            case '{DAV:}authenticated' :
185                return new self(self::AUTHENTICATED);
186            case '{DAV:}href':
187                return new self(self::HREF, $tree['value']);
188            case '{DAV:}all':
189                return new self(self::ALL);
190            default :
191                throw new BadRequest('Unknown or unsupported principal type: ' . $tree['name']);
192        }
193
194    }
195
196}
197