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