@@ -23,108 +23,108 @@ |
||
23 | 23 | */ |
24 | 24 | abstract class AbstractBearer implements BackendInterface |
25 | 25 | { |
26 | - /** |
|
27 | - * Authentication Realm. |
|
28 | - * |
|
29 | - * The realm is often displayed by browser clients when showing the |
|
30 | - * authentication dialog. |
|
31 | - * |
|
32 | - * @var string |
|
33 | - */ |
|
34 | - protected $realm = 'sabre/dav'; |
|
26 | + /** |
|
27 | + * Authentication Realm. |
|
28 | + * |
|
29 | + * The realm is often displayed by browser clients when showing the |
|
30 | + * authentication dialog. |
|
31 | + * |
|
32 | + * @var string |
|
33 | + */ |
|
34 | + protected $realm = 'sabre/dav'; |
|
35 | 35 | |
36 | - /** |
|
37 | - * Validates a Bearer token. |
|
38 | - * |
|
39 | - * This method should return the full principal url, or false if the |
|
40 | - * token was incorrect. |
|
41 | - * |
|
42 | - * @param string $bearerToken |
|
43 | - * |
|
44 | - * @return string|false |
|
45 | - */ |
|
46 | - abstract protected function validateBearerToken($bearerToken); |
|
36 | + /** |
|
37 | + * Validates a Bearer token. |
|
38 | + * |
|
39 | + * This method should return the full principal url, or false if the |
|
40 | + * token was incorrect. |
|
41 | + * |
|
42 | + * @param string $bearerToken |
|
43 | + * |
|
44 | + * @return string|false |
|
45 | + */ |
|
46 | + abstract protected function validateBearerToken($bearerToken); |
|
47 | 47 | |
48 | - /** |
|
49 | - * Sets the authentication realm for this backend. |
|
50 | - * |
|
51 | - * @param string $realm |
|
52 | - */ |
|
53 | - public function setRealm($realm) |
|
54 | - { |
|
55 | - $this->realm = $realm; |
|
56 | - } |
|
48 | + /** |
|
49 | + * Sets the authentication realm for this backend. |
|
50 | + * |
|
51 | + * @param string $realm |
|
52 | + */ |
|
53 | + public function setRealm($realm) |
|
54 | + { |
|
55 | + $this->realm = $realm; |
|
56 | + } |
|
57 | 57 | |
58 | - /** |
|
59 | - * When this method is called, the backend must check if authentication was |
|
60 | - * successful. |
|
61 | - * |
|
62 | - * The returned value must be one of the following |
|
63 | - * |
|
64 | - * [true, "principals/username"] |
|
65 | - * [false, "reason for failure"] |
|
66 | - * |
|
67 | - * If authentication was successful, it's expected that the authentication |
|
68 | - * backend returns a so-called principal url. |
|
69 | - * |
|
70 | - * Examples of a principal url: |
|
71 | - * |
|
72 | - * principals/admin |
|
73 | - * principals/user1 |
|
74 | - * principals/users/joe |
|
75 | - * principals/uid/123457 |
|
76 | - * |
|
77 | - * If you don't use WebDAV ACL (RFC3744) we recommend that you simply |
|
78 | - * return a string such as: |
|
79 | - * |
|
80 | - * principals/users/[username] |
|
81 | - * |
|
82 | - * @return array |
|
83 | - */ |
|
84 | - public function check(RequestInterface $request, ResponseInterface $response) |
|
85 | - { |
|
86 | - $auth = new HTTP\Auth\Bearer( |
|
87 | - $this->realm, |
|
88 | - $request, |
|
89 | - $response |
|
90 | - ); |
|
58 | + /** |
|
59 | + * When this method is called, the backend must check if authentication was |
|
60 | + * successful. |
|
61 | + * |
|
62 | + * The returned value must be one of the following |
|
63 | + * |
|
64 | + * [true, "principals/username"] |
|
65 | + * [false, "reason for failure"] |
|
66 | + * |
|
67 | + * If authentication was successful, it's expected that the authentication |
|
68 | + * backend returns a so-called principal url. |
|
69 | + * |
|
70 | + * Examples of a principal url: |
|
71 | + * |
|
72 | + * principals/admin |
|
73 | + * principals/user1 |
|
74 | + * principals/users/joe |
|
75 | + * principals/uid/123457 |
|
76 | + * |
|
77 | + * If you don't use WebDAV ACL (RFC3744) we recommend that you simply |
|
78 | + * return a string such as: |
|
79 | + * |
|
80 | + * principals/users/[username] |
|
81 | + * |
|
82 | + * @return array |
|
83 | + */ |
|
84 | + public function check(RequestInterface $request, ResponseInterface $response) |
|
85 | + { |
|
86 | + $auth = new HTTP\Auth\Bearer( |
|
87 | + $this->realm, |
|
88 | + $request, |
|
89 | + $response |
|
90 | + ); |
|
91 | 91 | |
92 | - $bearerToken = $auth->getToken($request); |
|
93 | - if (!$bearerToken) { |
|
94 | - return [false, "No 'Authorization: Bearer' header found. Either the client didn't send one, or the server is mis-configured"]; |
|
95 | - } |
|
96 | - $principalUrl = $this->validateBearerToken($bearerToken); |
|
97 | - if (!$principalUrl) { |
|
98 | - return [false, 'Bearer token was incorrect']; |
|
99 | - } |
|
92 | + $bearerToken = $auth->getToken($request); |
|
93 | + if (!$bearerToken) { |
|
94 | + return [false, "No 'Authorization: Bearer' header found. Either the client didn't send one, or the server is mis-configured"]; |
|
95 | + } |
|
96 | + $principalUrl = $this->validateBearerToken($bearerToken); |
|
97 | + if (!$principalUrl) { |
|
98 | + return [false, 'Bearer token was incorrect']; |
|
99 | + } |
|
100 | 100 | |
101 | - return [true, $principalUrl]; |
|
102 | - } |
|
101 | + return [true, $principalUrl]; |
|
102 | + } |
|
103 | 103 | |
104 | - /** |
|
105 | - * This method is called when a user could not be authenticated, and |
|
106 | - * authentication was required for the current request. |
|
107 | - * |
|
108 | - * This gives you the opportunity to set authentication headers. The 401 |
|
109 | - * status code will already be set. |
|
110 | - * |
|
111 | - * In this case of Bearer Auth, this would for example mean that the |
|
112 | - * following header needs to be set: |
|
113 | - * |
|
114 | - * $response->addHeader('WWW-Authenticate', 'Bearer realm=SabreDAV'); |
|
115 | - * |
|
116 | - * Keep in mind that in the case of multiple authentication backends, other |
|
117 | - * WWW-Authenticate headers may already have been set, and you'll want to |
|
118 | - * append your own WWW-Authenticate header instead of overwriting the |
|
119 | - * existing one. |
|
120 | - */ |
|
121 | - public function challenge(RequestInterface $request, ResponseInterface $response) |
|
122 | - { |
|
123 | - $auth = new HTTP\Auth\Bearer( |
|
124 | - $this->realm, |
|
125 | - $request, |
|
126 | - $response |
|
127 | - ); |
|
128 | - $auth->requireLogin(); |
|
129 | - } |
|
104 | + /** |
|
105 | + * This method is called when a user could not be authenticated, and |
|
106 | + * authentication was required for the current request. |
|
107 | + * |
|
108 | + * This gives you the opportunity to set authentication headers. The 401 |
|
109 | + * status code will already be set. |
|
110 | + * |
|
111 | + * In this case of Bearer Auth, this would for example mean that the |
|
112 | + * following header needs to be set: |
|
113 | + * |
|
114 | + * $response->addHeader('WWW-Authenticate', 'Bearer realm=SabreDAV'); |
|
115 | + * |
|
116 | + * Keep in mind that in the case of multiple authentication backends, other |
|
117 | + * WWW-Authenticate headers may already have been set, and you'll want to |
|
118 | + * append your own WWW-Authenticate header instead of overwriting the |
|
119 | + * existing one. |
|
120 | + */ |
|
121 | + public function challenge(RequestInterface $request, ResponseInterface $response) |
|
122 | + { |
|
123 | + $auth = new HTTP\Auth\Bearer( |
|
124 | + $this->realm, |
|
125 | + $request, |
|
126 | + $response |
|
127 | + ); |
|
128 | + $auth->requireLogin(); |
|
129 | + } |
|
130 | 130 | } |
@@ -10,105 +10,105 @@ |
||
10 | 10 | */ |
11 | 11 | class PDOBasicAuth extends AbstractBasic |
12 | 12 | { |
13 | - /** |
|
14 | - * Reference to PDO connection. |
|
15 | - * |
|
16 | - * @var PDO |
|
17 | - */ |
|
18 | - protected $pdo; |
|
13 | + /** |
|
14 | + * Reference to PDO connection. |
|
15 | + * |
|
16 | + * @var PDO |
|
17 | + */ |
|
18 | + protected $pdo; |
|
19 | 19 | |
20 | - /** |
|
21 | - * PDO table name we'll be using. |
|
22 | - * |
|
23 | - * @var string |
|
24 | - */ |
|
25 | - protected $tableName; |
|
20 | + /** |
|
21 | + * PDO table name we'll be using. |
|
22 | + * |
|
23 | + * @var string |
|
24 | + */ |
|
25 | + protected $tableName; |
|
26 | 26 | |
27 | - /** |
|
28 | - * PDO digest column name we'll be using |
|
29 | - * (i.e. digest, password, password_hash). |
|
30 | - * |
|
31 | - * @var string |
|
32 | - */ |
|
33 | - protected $digestColumn; |
|
27 | + /** |
|
28 | + * PDO digest column name we'll be using |
|
29 | + * (i.e. digest, password, password_hash). |
|
30 | + * |
|
31 | + * @var string |
|
32 | + */ |
|
33 | + protected $digestColumn; |
|
34 | 34 | |
35 | - /** |
|
36 | - * PDO uuid(unique user identifier) column name we'll be using |
|
37 | - * (i.e. username, email). |
|
38 | - * |
|
39 | - * @var string |
|
40 | - */ |
|
41 | - protected $uuidColumn; |
|
35 | + /** |
|
36 | + * PDO uuid(unique user identifier) column name we'll be using |
|
37 | + * (i.e. username, email). |
|
38 | + * |
|
39 | + * @var string |
|
40 | + */ |
|
41 | + protected $uuidColumn; |
|
42 | 42 | |
43 | - /** |
|
44 | - * Digest prefix: |
|
45 | - * if the backend you are using for is prefixing |
|
46 | - * your password hashes set this option to your prefix to |
|
47 | - * cut it off before verfiying. |
|
48 | - * |
|
49 | - * @var string |
|
50 | - */ |
|
51 | - protected $digestPrefix; |
|
43 | + /** |
|
44 | + * Digest prefix: |
|
45 | + * if the backend you are using for is prefixing |
|
46 | + * your password hashes set this option to your prefix to |
|
47 | + * cut it off before verfiying. |
|
48 | + * |
|
49 | + * @var string |
|
50 | + */ |
|
51 | + protected $digestPrefix; |
|
52 | 52 | |
53 | - /** |
|
54 | - * Creates the backend object. |
|
55 | - * |
|
56 | - * If the filename argument is passed in, it will parse out the specified file fist. |
|
57 | - */ |
|
58 | - public function __construct(\PDO $pdo, array $options = []) |
|
59 | - { |
|
60 | - $this->pdo = $pdo; |
|
61 | - if (isset($options['tableName'])) { |
|
62 | - $this->tableName = $options['tableName']; |
|
63 | - } else { |
|
64 | - $this->tableName = 'users'; |
|
65 | - } |
|
66 | - if (isset($options['digestColumn'])) { |
|
67 | - $this->digestColumn = $options['digestColumn']; |
|
68 | - } else { |
|
69 | - $this->digestColumn = 'digest'; |
|
70 | - } |
|
71 | - if (isset($options['uuidColumn'])) { |
|
72 | - $this->uuidColumn = $options['uuidColumn']; |
|
73 | - } else { |
|
74 | - $this->uuidColumn = 'username'; |
|
75 | - } |
|
76 | - if (isset($options['digestPrefix'])) { |
|
77 | - $this->digestPrefix = $options['digestPrefix']; |
|
78 | - } |
|
79 | - } |
|
53 | + /** |
|
54 | + * Creates the backend object. |
|
55 | + * |
|
56 | + * If the filename argument is passed in, it will parse out the specified file fist. |
|
57 | + */ |
|
58 | + public function __construct(\PDO $pdo, array $options = []) |
|
59 | + { |
|
60 | + $this->pdo = $pdo; |
|
61 | + if (isset($options['tableName'])) { |
|
62 | + $this->tableName = $options['tableName']; |
|
63 | + } else { |
|
64 | + $this->tableName = 'users'; |
|
65 | + } |
|
66 | + if (isset($options['digestColumn'])) { |
|
67 | + $this->digestColumn = $options['digestColumn']; |
|
68 | + } else { |
|
69 | + $this->digestColumn = 'digest'; |
|
70 | + } |
|
71 | + if (isset($options['uuidColumn'])) { |
|
72 | + $this->uuidColumn = $options['uuidColumn']; |
|
73 | + } else { |
|
74 | + $this->uuidColumn = 'username'; |
|
75 | + } |
|
76 | + if (isset($options['digestPrefix'])) { |
|
77 | + $this->digestPrefix = $options['digestPrefix']; |
|
78 | + } |
|
79 | + } |
|
80 | 80 | |
81 | - /** |
|
82 | - * Validates a username and password. |
|
83 | - * |
|
84 | - * This method should return true or false depending on if login |
|
85 | - * succeeded. |
|
86 | - * |
|
87 | - * @param string $username |
|
88 | - * @param string $password |
|
89 | - * |
|
90 | - * @return bool |
|
91 | - */ |
|
92 | - public function validateUserPass($username, $password) |
|
93 | - { |
|
94 | - $stmt = $this->pdo->prepare('SELECT '.$this->digestColumn.' FROM '.$this->tableName.' WHERE '.$this->uuidColumn.' = ?'); |
|
95 | - $stmt->execute([$username]); |
|
96 | - $result = $stmt->fetchAll(); |
|
81 | + /** |
|
82 | + * Validates a username and password. |
|
83 | + * |
|
84 | + * This method should return true or false depending on if login |
|
85 | + * succeeded. |
|
86 | + * |
|
87 | + * @param string $username |
|
88 | + * @param string $password |
|
89 | + * |
|
90 | + * @return bool |
|
91 | + */ |
|
92 | + public function validateUserPass($username, $password) |
|
93 | + { |
|
94 | + $stmt = $this->pdo->prepare('SELECT '.$this->digestColumn.' FROM '.$this->tableName.' WHERE '.$this->uuidColumn.' = ?'); |
|
95 | + $stmt->execute([$username]); |
|
96 | + $result = $stmt->fetchAll(); |
|
97 | 97 | |
98 | - if (!count($result)) { |
|
99 | - return false; |
|
100 | - } else { |
|
101 | - $digest = $result[0][$this->digestColumn]; |
|
98 | + if (!count($result)) { |
|
99 | + return false; |
|
100 | + } else { |
|
101 | + $digest = $result[0][$this->digestColumn]; |
|
102 | 102 | |
103 | - if (isset($this->digestPrefix)) { |
|
104 | - $digest = substr($digest, strlen($this->digestPrefix)); |
|
105 | - } |
|
103 | + if (isset($this->digestPrefix)) { |
|
104 | + $digest = substr($digest, strlen($this->digestPrefix)); |
|
105 | + } |
|
106 | 106 | |
107 | - if (password_verify($password, $digest)) { |
|
108 | - return true; |
|
109 | - } |
|
107 | + if (password_verify($password, $digest)) { |
|
108 | + return true; |
|
109 | + } |
|
110 | 110 | |
111 | - return false; |
|
112 | - } |
|
113 | - } |
|
111 | + return false; |
|
112 | + } |
|
113 | + } |
|
114 | 114 | } |
@@ -13,43 +13,43 @@ |
||
13 | 13 | */ |
14 | 14 | class PDO extends AbstractDigest |
15 | 15 | { |
16 | - /** |
|
17 | - * Reference to PDO connection. |
|
18 | - * |
|
19 | - * @var PDO |
|
20 | - */ |
|
21 | - protected $pdo; |
|
16 | + /** |
|
17 | + * Reference to PDO connection. |
|
18 | + * |
|
19 | + * @var PDO |
|
20 | + */ |
|
21 | + protected $pdo; |
|
22 | 22 | |
23 | - /** |
|
24 | - * PDO table name we'll be using. |
|
25 | - * |
|
26 | - * @var string |
|
27 | - */ |
|
28 | - public $tableName = 'users'; |
|
23 | + /** |
|
24 | + * PDO table name we'll be using. |
|
25 | + * |
|
26 | + * @var string |
|
27 | + */ |
|
28 | + public $tableName = 'users'; |
|
29 | 29 | |
30 | - /** |
|
31 | - * Creates the backend object. |
|
32 | - * |
|
33 | - * If the filename argument is passed in, it will parse out the specified file fist. |
|
34 | - */ |
|
35 | - public function __construct(\PDO $pdo) |
|
36 | - { |
|
37 | - $this->pdo = $pdo; |
|
38 | - } |
|
30 | + /** |
|
31 | + * Creates the backend object. |
|
32 | + * |
|
33 | + * If the filename argument is passed in, it will parse out the specified file fist. |
|
34 | + */ |
|
35 | + public function __construct(\PDO $pdo) |
|
36 | + { |
|
37 | + $this->pdo = $pdo; |
|
38 | + } |
|
39 | 39 | |
40 | - /** |
|
41 | - * Returns the digest hash for a user. |
|
42 | - * |
|
43 | - * @param string $realm |
|
44 | - * @param string $username |
|
45 | - * |
|
46 | - * @return string|null |
|
47 | - */ |
|
48 | - public function getDigestHash($realm, $username) |
|
49 | - { |
|
50 | - $stmt = $this->pdo->prepare('SELECT digesta1 FROM '.$this->tableName.' WHERE username = ?'); |
|
51 | - $stmt->execute([$username]); |
|
40 | + /** |
|
41 | + * Returns the digest hash for a user. |
|
42 | + * |
|
43 | + * @param string $realm |
|
44 | + * @param string $username |
|
45 | + * |
|
46 | + * @return string|null |
|
47 | + */ |
|
48 | + public function getDigestHash($realm, $username) |
|
49 | + { |
|
50 | + $stmt = $this->pdo->prepare('SELECT digesta1 FROM '.$this->tableName.' WHERE username = ?'); |
|
51 | + $stmt->execute([$username]); |
|
52 | 52 | |
53 | - return $stmt->fetchColumn() ?: null; |
|
54 | - } |
|
53 | + return $stmt->fetchColumn() ?: null; |
|
54 | + } |
|
55 | 55 | } |
@@ -13,70 +13,70 @@ |
||
13 | 13 | */ |
14 | 14 | class IMAP extends AbstractBasic |
15 | 15 | { |
16 | - /** |
|
17 | - * IMAP server in the form {host[:port][/flag1/flag2...]}. |
|
18 | - * |
|
19 | - * @see http://php.net/manual/en/function.imap-open.php |
|
20 | - * |
|
21 | - * @var string |
|
22 | - */ |
|
23 | - protected $mailbox; |
|
16 | + /** |
|
17 | + * IMAP server in the form {host[:port][/flag1/flag2...]}. |
|
18 | + * |
|
19 | + * @see http://php.net/manual/en/function.imap-open.php |
|
20 | + * |
|
21 | + * @var string |
|
22 | + */ |
|
23 | + protected $mailbox; |
|
24 | 24 | |
25 | - /** |
|
26 | - * Creates the backend object. |
|
27 | - * |
|
28 | - * @param string $mailbox |
|
29 | - */ |
|
30 | - public function __construct($mailbox) |
|
31 | - { |
|
32 | - $this->mailbox = $mailbox; |
|
33 | - } |
|
25 | + /** |
|
26 | + * Creates the backend object. |
|
27 | + * |
|
28 | + * @param string $mailbox |
|
29 | + */ |
|
30 | + public function __construct($mailbox) |
|
31 | + { |
|
32 | + $this->mailbox = $mailbox; |
|
33 | + } |
|
34 | 34 | |
35 | - /** |
|
36 | - * Connects to an IMAP server and tries to authenticate. |
|
37 | - * |
|
38 | - * @param string $username |
|
39 | - * @param string $password |
|
40 | - * |
|
41 | - * @return bool |
|
42 | - */ |
|
43 | - protected function imapOpen($username, $password) |
|
44 | - { |
|
45 | - $success = false; |
|
35 | + /** |
|
36 | + * Connects to an IMAP server and tries to authenticate. |
|
37 | + * |
|
38 | + * @param string $username |
|
39 | + * @param string $password |
|
40 | + * |
|
41 | + * @return bool |
|
42 | + */ |
|
43 | + protected function imapOpen($username, $password) |
|
44 | + { |
|
45 | + $success = false; |
|
46 | 46 | |
47 | - try { |
|
48 | - $imap = imap_open($this->mailbox, $username, $password, OP_HALFOPEN | OP_READONLY, 1); |
|
49 | - if ($imap) { |
|
50 | - $success = true; |
|
51 | - } |
|
52 | - } catch (\ErrorException $e) { |
|
53 | - error_log($e->getMessage()); |
|
54 | - } |
|
47 | + try { |
|
48 | + $imap = imap_open($this->mailbox, $username, $password, OP_HALFOPEN | OP_READONLY, 1); |
|
49 | + if ($imap) { |
|
50 | + $success = true; |
|
51 | + } |
|
52 | + } catch (\ErrorException $e) { |
|
53 | + error_log($e->getMessage()); |
|
54 | + } |
|
55 | 55 | |
56 | - $errors = imap_errors(); |
|
57 | - if ($errors) { |
|
58 | - foreach ($errors as $error) { |
|
59 | - error_log($error); |
|
60 | - } |
|
61 | - } |
|
56 | + $errors = imap_errors(); |
|
57 | + if ($errors) { |
|
58 | + foreach ($errors as $error) { |
|
59 | + error_log($error); |
|
60 | + } |
|
61 | + } |
|
62 | 62 | |
63 | - if (isset($imap) && $imap) { |
|
64 | - imap_close($imap); |
|
65 | - } |
|
63 | + if (isset($imap) && $imap) { |
|
64 | + imap_close($imap); |
|
65 | + } |
|
66 | 66 | |
67 | - return $success; |
|
68 | - } |
|
67 | + return $success; |
|
68 | + } |
|
69 | 69 | |
70 | - /** |
|
71 | - * Validates a username and password by trying to authenticate against IMAP. |
|
72 | - * |
|
73 | - * @param string $username |
|
74 | - * @param string $password |
|
75 | - * |
|
76 | - * @return bool |
|
77 | - */ |
|
78 | - protected function validateUserPass($username, $password) |
|
79 | - { |
|
80 | - return $this->imapOpen($username, $password); |
|
81 | - } |
|
70 | + /** |
|
71 | + * Validates a username and password by trying to authenticate against IMAP. |
|
72 | + * |
|
73 | + * @param string $username |
|
74 | + * @param string $password |
|
75 | + * |
|
76 | + * @return bool |
|
77 | + */ |
|
78 | + protected function validateUserPass($username, $password) |
|
79 | + { |
|
80 | + return $this->imapOpen($username, $password); |
|
81 | + } |
|
82 | 82 | } |
@@ -22,228 +22,228 @@ |
||
22 | 22 | */ |
23 | 23 | class Plugin extends DAV\ServerPlugin |
24 | 24 | { |
25 | - /** |
|
26 | - * Reference to server object. |
|
27 | - * |
|
28 | - * @var DAV\Server |
|
29 | - */ |
|
30 | - protected $server; |
|
31 | - |
|
32 | - const SYNCTOKEN_PREFIX = 'http://sabre.io/ns/sync/'; |
|
33 | - |
|
34 | - /** |
|
35 | - * Returns a plugin name. |
|
36 | - * |
|
37 | - * Using this name other plugins will be able to access other plugins |
|
38 | - * using \Sabre\DAV\Server::getPlugin |
|
39 | - * |
|
40 | - * @return string |
|
41 | - */ |
|
42 | - public function getPluginName() |
|
43 | - { |
|
44 | - return 'sync'; |
|
45 | - } |
|
46 | - |
|
47 | - /** |
|
48 | - * Initializes the plugin. |
|
49 | - * |
|
50 | - * This is when the plugin registers it's hooks. |
|
51 | - */ |
|
52 | - public function initialize(DAV\Server $server) |
|
53 | - { |
|
54 | - $this->server = $server; |
|
55 | - $server->xml->elementMap['{DAV:}sync-collection'] = 'Sabre\\DAV\\Xml\\Request\\SyncCollectionReport'; |
|
56 | - |
|
57 | - $self = $this; |
|
58 | - |
|
59 | - $server->on('report', function ($reportName, $dom, $uri) use ($self) { |
|
60 | - if ('{DAV:}sync-collection' === $reportName) { |
|
61 | - $this->server->transactionType = 'report-sync-collection'; |
|
62 | - $self->syncCollection($uri, $dom); |
|
63 | - |
|
64 | - return false; |
|
65 | - } |
|
66 | - }); |
|
67 | - |
|
68 | - $server->on('propFind', [$this, 'propFind']); |
|
69 | - $server->on('validateTokens', [$this, 'validateTokens']); |
|
70 | - } |
|
71 | - |
|
72 | - /** |
|
73 | - * Returns a list of reports this plugin supports. |
|
74 | - * |
|
75 | - * This will be used in the {DAV:}supported-report-set property. |
|
76 | - * Note that you still need to subscribe to the 'report' event to actually |
|
77 | - * implement them |
|
78 | - * |
|
79 | - * @param string $uri |
|
80 | - * |
|
81 | - * @return array |
|
82 | - */ |
|
83 | - public function getSupportedReportSet($uri) |
|
84 | - { |
|
85 | - $node = $this->server->tree->getNodeForPath($uri); |
|
86 | - if ($node instanceof ISyncCollection && $node->getSyncToken()) { |
|
87 | - return [ |
|
88 | - '{DAV:}sync-collection', |
|
89 | - ]; |
|
90 | - } |
|
91 | - |
|
92 | - return []; |
|
93 | - } |
|
94 | - |
|
95 | - /** |
|
96 | - * This method handles the {DAV:}sync-collection HTTP REPORT. |
|
97 | - * |
|
98 | - * @param string $uri |
|
99 | - */ |
|
100 | - public function syncCollection($uri, SyncCollectionReport $report) |
|
101 | - { |
|
102 | - // Getting the data |
|
103 | - $node = $this->server->tree->getNodeForPath($uri); |
|
104 | - if (!$node instanceof ISyncCollection) { |
|
105 | - throw new DAV\Exception\ReportNotSupported('The {DAV:}sync-collection REPORT is not supported on this url.'); |
|
106 | - } |
|
107 | - $token = $node->getSyncToken(); |
|
108 | - if (!$token) { |
|
109 | - throw new DAV\Exception\ReportNotSupported('No sync information is available at this node'); |
|
110 | - } |
|
111 | - |
|
112 | - $syncToken = $report->syncToken; |
|
113 | - if (!is_null($syncToken)) { |
|
114 | - // Sync-token must start with our prefix |
|
115 | - if (self::SYNCTOKEN_PREFIX !== substr($syncToken, 0, strlen(self::SYNCTOKEN_PREFIX))) { |
|
116 | - throw new DAV\Exception\InvalidSyncToken('Invalid or unknown sync token'); |
|
117 | - } |
|
118 | - |
|
119 | - $syncToken = substr($syncToken, strlen(self::SYNCTOKEN_PREFIX)); |
|
120 | - } |
|
121 | - $changeInfo = $node->getChanges($syncToken, $report->syncLevel, $report->limit); |
|
122 | - |
|
123 | - if (is_null($changeInfo)) { |
|
124 | - throw new DAV\Exception\InvalidSyncToken('Invalid or unknown sync token'); |
|
125 | - } |
|
126 | - |
|
127 | - if (!array_key_exists('result_truncated', $changeInfo)) { |
|
128 | - $changeInfo['result_truncated'] = false; |
|
129 | - } |
|
130 | - |
|
131 | - // Encoding the response |
|
132 | - $this->sendSyncCollectionResponse( |
|
133 | - $changeInfo['syncToken'], |
|
134 | - $uri, |
|
135 | - $changeInfo['added'], |
|
136 | - $changeInfo['modified'], |
|
137 | - $changeInfo['deleted'], |
|
138 | - $report->properties, |
|
139 | - $changeInfo['result_truncated'] |
|
140 | - ); |
|
141 | - } |
|
142 | - |
|
143 | - /** |
|
144 | - * Sends the response to a sync-collection request. |
|
145 | - * |
|
146 | - * @param string $syncToken |
|
147 | - * @param string $collectionUrl |
|
148 | - */ |
|
149 | - protected function sendSyncCollectionResponse($syncToken, $collectionUrl, array $added, array $modified, array $deleted, array $properties, bool $resultTruncated = false) |
|
150 | - { |
|
151 | - $fullPaths = []; |
|
152 | - |
|
153 | - // Pre-fetching children, if this is possible. |
|
154 | - foreach (array_merge($added, $modified) as $item) { |
|
155 | - $fullPath = $collectionUrl.'/'.$item; |
|
156 | - $fullPaths[] = $fullPath; |
|
157 | - } |
|
158 | - |
|
159 | - $responses = []; |
|
160 | - foreach ($this->server->getPropertiesForMultiplePaths($fullPaths, $properties) as $fullPath => $props) { |
|
161 | - // The 'Property_Response' class is responsible for generating a |
|
162 | - // single {DAV:}response xml element. |
|
163 | - $responses[] = new DAV\Xml\Element\Response($fullPath, $props); |
|
164 | - } |
|
165 | - |
|
166 | - // Deleted items also show up as 'responses'. They have no properties, |
|
167 | - // and a single {DAV:}status element set as 'HTTP/1.1 404 Not Found'. |
|
168 | - foreach ($deleted as $item) { |
|
169 | - $fullPath = $collectionUrl.'/'.$item; |
|
170 | - $responses[] = new DAV\Xml\Element\Response($fullPath, [], 404); |
|
171 | - } |
|
172 | - if ($resultTruncated) { |
|
173 | - $responses[] = new DAV\Xml\Element\Response($collectionUrl.'/', [], 507); |
|
174 | - } |
|
175 | - |
|
176 | - $multiStatus = new DAV\Xml\Response\MultiStatus($responses, self::SYNCTOKEN_PREFIX.$syncToken); |
|
177 | - |
|
178 | - $this->server->httpResponse->setStatus(207); |
|
179 | - $this->server->httpResponse->setHeader('Content-Type', 'application/xml; charset=utf-8'); |
|
180 | - $this->server->httpResponse->setBody( |
|
181 | - $this->server->xml->write('{DAV:}multistatus', $multiStatus, $this->server->getBaseUri()) |
|
182 | - ); |
|
183 | - } |
|
184 | - |
|
185 | - /** |
|
186 | - * This method is triggered whenever properties are requested for a node. |
|
187 | - * We intercept this to see if we must return a {DAV:}sync-token. |
|
188 | - */ |
|
189 | - public function propFind(DAV\PropFind $propFind, DAV\INode $node) |
|
190 | - { |
|
191 | - $propFind->handle('{DAV:}sync-token', function () use ($node) { |
|
192 | - if (!$node instanceof ISyncCollection || !$token = $node->getSyncToken()) { |
|
193 | - return; |
|
194 | - } |
|
195 | - |
|
196 | - return self::SYNCTOKEN_PREFIX.$token; |
|
197 | - }); |
|
198 | - } |
|
199 | - |
|
200 | - /** |
|
201 | - * The validateTokens event is triggered before every request. |
|
202 | - * |
|
203 | - * It's a moment where this plugin can check all the supplied lock tokens |
|
204 | - * in the If: header, and check if they are valid. |
|
205 | - * |
|
206 | - * @param array $conditions |
|
207 | - */ |
|
208 | - public function validateTokens(RequestInterface $request, &$conditions) |
|
209 | - { |
|
210 | - foreach ($conditions as $kk => $condition) { |
|
211 | - foreach ($condition['tokens'] as $ii => $token) { |
|
212 | - // Sync-tokens must always start with our designated prefix. |
|
213 | - if (self::SYNCTOKEN_PREFIX !== substr($token['token'], 0, strlen(self::SYNCTOKEN_PREFIX))) { |
|
214 | - continue; |
|
215 | - } |
|
216 | - |
|
217 | - // Checking if the token is a match. |
|
218 | - $node = $this->server->tree->getNodeForPath($condition['uri']); |
|
219 | - |
|
220 | - if ( |
|
221 | - $node instanceof ISyncCollection && |
|
222 | - $node->getSyncToken() == substr($token['token'], strlen(self::SYNCTOKEN_PREFIX)) |
|
223 | - ) { |
|
224 | - $conditions[$kk]['tokens'][$ii]['validToken'] = true; |
|
225 | - } |
|
226 | - } |
|
227 | - } |
|
228 | - } |
|
229 | - |
|
230 | - /** |
|
231 | - * Returns a bunch of meta-data about the plugin. |
|
232 | - * |
|
233 | - * Providing this information is optional, and is mainly displayed by the |
|
234 | - * Browser plugin. |
|
235 | - * |
|
236 | - * The description key in the returned array may contain html and will not |
|
237 | - * be sanitized. |
|
238 | - * |
|
239 | - * @return array |
|
240 | - */ |
|
241 | - public function getPluginInfo() |
|
242 | - { |
|
243 | - return [ |
|
244 | - 'name' => $this->getPluginName(), |
|
245 | - 'description' => 'Adds support for WebDAV Collection Sync (rfc6578)', |
|
246 | - 'link' => 'http://sabre.io/dav/sync/', |
|
247 | - ]; |
|
248 | - } |
|
25 | + /** |
|
26 | + * Reference to server object. |
|
27 | + * |
|
28 | + * @var DAV\Server |
|
29 | + */ |
|
30 | + protected $server; |
|
31 | + |
|
32 | + const SYNCTOKEN_PREFIX = 'http://sabre.io/ns/sync/'; |
|
33 | + |
|
34 | + /** |
|
35 | + * Returns a plugin name. |
|
36 | + * |
|
37 | + * Using this name other plugins will be able to access other plugins |
|
38 | + * using \Sabre\DAV\Server::getPlugin |
|
39 | + * |
|
40 | + * @return string |
|
41 | + */ |
|
42 | + public function getPluginName() |
|
43 | + { |
|
44 | + return 'sync'; |
|
45 | + } |
|
46 | + |
|
47 | + /** |
|
48 | + * Initializes the plugin. |
|
49 | + * |
|
50 | + * This is when the plugin registers it's hooks. |
|
51 | + */ |
|
52 | + public function initialize(DAV\Server $server) |
|
53 | + { |
|
54 | + $this->server = $server; |
|
55 | + $server->xml->elementMap['{DAV:}sync-collection'] = 'Sabre\\DAV\\Xml\\Request\\SyncCollectionReport'; |
|
56 | + |
|
57 | + $self = $this; |
|
58 | + |
|
59 | + $server->on('report', function ($reportName, $dom, $uri) use ($self) { |
|
60 | + if ('{DAV:}sync-collection' === $reportName) { |
|
61 | + $this->server->transactionType = 'report-sync-collection'; |
|
62 | + $self->syncCollection($uri, $dom); |
|
63 | + |
|
64 | + return false; |
|
65 | + } |
|
66 | + }); |
|
67 | + |
|
68 | + $server->on('propFind', [$this, 'propFind']); |
|
69 | + $server->on('validateTokens', [$this, 'validateTokens']); |
|
70 | + } |
|
71 | + |
|
72 | + /** |
|
73 | + * Returns a list of reports this plugin supports. |
|
74 | + * |
|
75 | + * This will be used in the {DAV:}supported-report-set property. |
|
76 | + * Note that you still need to subscribe to the 'report' event to actually |
|
77 | + * implement them |
|
78 | + * |
|
79 | + * @param string $uri |
|
80 | + * |
|
81 | + * @return array |
|
82 | + */ |
|
83 | + public function getSupportedReportSet($uri) |
|
84 | + { |
|
85 | + $node = $this->server->tree->getNodeForPath($uri); |
|
86 | + if ($node instanceof ISyncCollection && $node->getSyncToken()) { |
|
87 | + return [ |
|
88 | + '{DAV:}sync-collection', |
|
89 | + ]; |
|
90 | + } |
|
91 | + |
|
92 | + return []; |
|
93 | + } |
|
94 | + |
|
95 | + /** |
|
96 | + * This method handles the {DAV:}sync-collection HTTP REPORT. |
|
97 | + * |
|
98 | + * @param string $uri |
|
99 | + */ |
|
100 | + public function syncCollection($uri, SyncCollectionReport $report) |
|
101 | + { |
|
102 | + // Getting the data |
|
103 | + $node = $this->server->tree->getNodeForPath($uri); |
|
104 | + if (!$node instanceof ISyncCollection) { |
|
105 | + throw new DAV\Exception\ReportNotSupported('The {DAV:}sync-collection REPORT is not supported on this url.'); |
|
106 | + } |
|
107 | + $token = $node->getSyncToken(); |
|
108 | + if (!$token) { |
|
109 | + throw new DAV\Exception\ReportNotSupported('No sync information is available at this node'); |
|
110 | + } |
|
111 | + |
|
112 | + $syncToken = $report->syncToken; |
|
113 | + if (!is_null($syncToken)) { |
|
114 | + // Sync-token must start with our prefix |
|
115 | + if (self::SYNCTOKEN_PREFIX !== substr($syncToken, 0, strlen(self::SYNCTOKEN_PREFIX))) { |
|
116 | + throw new DAV\Exception\InvalidSyncToken('Invalid or unknown sync token'); |
|
117 | + } |
|
118 | + |
|
119 | + $syncToken = substr($syncToken, strlen(self::SYNCTOKEN_PREFIX)); |
|
120 | + } |
|
121 | + $changeInfo = $node->getChanges($syncToken, $report->syncLevel, $report->limit); |
|
122 | + |
|
123 | + if (is_null($changeInfo)) { |
|
124 | + throw new DAV\Exception\InvalidSyncToken('Invalid or unknown sync token'); |
|
125 | + } |
|
126 | + |
|
127 | + if (!array_key_exists('result_truncated', $changeInfo)) { |
|
128 | + $changeInfo['result_truncated'] = false; |
|
129 | + } |
|
130 | + |
|
131 | + // Encoding the response |
|
132 | + $this->sendSyncCollectionResponse( |
|
133 | + $changeInfo['syncToken'], |
|
134 | + $uri, |
|
135 | + $changeInfo['added'], |
|
136 | + $changeInfo['modified'], |
|
137 | + $changeInfo['deleted'], |
|
138 | + $report->properties, |
|
139 | + $changeInfo['result_truncated'] |
|
140 | + ); |
|
141 | + } |
|
142 | + |
|
143 | + /** |
|
144 | + * Sends the response to a sync-collection request. |
|
145 | + * |
|
146 | + * @param string $syncToken |
|
147 | + * @param string $collectionUrl |
|
148 | + */ |
|
149 | + protected function sendSyncCollectionResponse($syncToken, $collectionUrl, array $added, array $modified, array $deleted, array $properties, bool $resultTruncated = false) |
|
150 | + { |
|
151 | + $fullPaths = []; |
|
152 | + |
|
153 | + // Pre-fetching children, if this is possible. |
|
154 | + foreach (array_merge($added, $modified) as $item) { |
|
155 | + $fullPath = $collectionUrl.'/'.$item; |
|
156 | + $fullPaths[] = $fullPath; |
|
157 | + } |
|
158 | + |
|
159 | + $responses = []; |
|
160 | + foreach ($this->server->getPropertiesForMultiplePaths($fullPaths, $properties) as $fullPath => $props) { |
|
161 | + // The 'Property_Response' class is responsible for generating a |
|
162 | + // single {DAV:}response xml element. |
|
163 | + $responses[] = new DAV\Xml\Element\Response($fullPath, $props); |
|
164 | + } |
|
165 | + |
|
166 | + // Deleted items also show up as 'responses'. They have no properties, |
|
167 | + // and a single {DAV:}status element set as 'HTTP/1.1 404 Not Found'. |
|
168 | + foreach ($deleted as $item) { |
|
169 | + $fullPath = $collectionUrl.'/'.$item; |
|
170 | + $responses[] = new DAV\Xml\Element\Response($fullPath, [], 404); |
|
171 | + } |
|
172 | + if ($resultTruncated) { |
|
173 | + $responses[] = new DAV\Xml\Element\Response($collectionUrl.'/', [], 507); |
|
174 | + } |
|
175 | + |
|
176 | + $multiStatus = new DAV\Xml\Response\MultiStatus($responses, self::SYNCTOKEN_PREFIX.$syncToken); |
|
177 | + |
|
178 | + $this->server->httpResponse->setStatus(207); |
|
179 | + $this->server->httpResponse->setHeader('Content-Type', 'application/xml; charset=utf-8'); |
|
180 | + $this->server->httpResponse->setBody( |
|
181 | + $this->server->xml->write('{DAV:}multistatus', $multiStatus, $this->server->getBaseUri()) |
|
182 | + ); |
|
183 | + } |
|
184 | + |
|
185 | + /** |
|
186 | + * This method is triggered whenever properties are requested for a node. |
|
187 | + * We intercept this to see if we must return a {DAV:}sync-token. |
|
188 | + */ |
|
189 | + public function propFind(DAV\PropFind $propFind, DAV\INode $node) |
|
190 | + { |
|
191 | + $propFind->handle('{DAV:}sync-token', function () use ($node) { |
|
192 | + if (!$node instanceof ISyncCollection || !$token = $node->getSyncToken()) { |
|
193 | + return; |
|
194 | + } |
|
195 | + |
|
196 | + return self::SYNCTOKEN_PREFIX.$token; |
|
197 | + }); |
|
198 | + } |
|
199 | + |
|
200 | + /** |
|
201 | + * The validateTokens event is triggered before every request. |
|
202 | + * |
|
203 | + * It's a moment where this plugin can check all the supplied lock tokens |
|
204 | + * in the If: header, and check if they are valid. |
|
205 | + * |
|
206 | + * @param array $conditions |
|
207 | + */ |
|
208 | + public function validateTokens(RequestInterface $request, &$conditions) |
|
209 | + { |
|
210 | + foreach ($conditions as $kk => $condition) { |
|
211 | + foreach ($condition['tokens'] as $ii => $token) { |
|
212 | + // Sync-tokens must always start with our designated prefix. |
|
213 | + if (self::SYNCTOKEN_PREFIX !== substr($token['token'], 0, strlen(self::SYNCTOKEN_PREFIX))) { |
|
214 | + continue; |
|
215 | + } |
|
216 | + |
|
217 | + // Checking if the token is a match. |
|
218 | + $node = $this->server->tree->getNodeForPath($condition['uri']); |
|
219 | + |
|
220 | + if ( |
|
221 | + $node instanceof ISyncCollection && |
|
222 | + $node->getSyncToken() == substr($token['token'], strlen(self::SYNCTOKEN_PREFIX)) |
|
223 | + ) { |
|
224 | + $conditions[$kk]['tokens'][$ii]['validToken'] = true; |
|
225 | + } |
|
226 | + } |
|
227 | + } |
|
228 | + } |
|
229 | + |
|
230 | + /** |
|
231 | + * Returns a bunch of meta-data about the plugin. |
|
232 | + * |
|
233 | + * Providing this information is optional, and is mainly displayed by the |
|
234 | + * Browser plugin. |
|
235 | + * |
|
236 | + * The description key in the returned array may contain html and will not |
|
237 | + * be sanitized. |
|
238 | + * |
|
239 | + * @return array |
|
240 | + */ |
|
241 | + public function getPluginInfo() |
|
242 | + { |
|
243 | + return [ |
|
244 | + 'name' => $this->getPluginName(), |
|
245 | + 'description' => 'Adds support for WebDAV Collection Sync (rfc6578)', |
|
246 | + 'link' => 'http://sabre.io/dav/sync/', |
|
247 | + ]; |
|
248 | + } |
|
249 | 249 | } |
@@ -56,7 +56,7 @@ discard block |
||
56 | 56 | |
57 | 57 | $self = $this; |
58 | 58 | |
59 | - $server->on('report', function ($reportName, $dom, $uri) use ($self) { |
|
59 | + $server->on('report', function($reportName, $dom, $uri) use ($self) { |
|
60 | 60 | if ('{DAV:}sync-collection' === $reportName) { |
61 | 61 | $this->server->transactionType = 'report-sync-collection'; |
62 | 62 | $self->syncCollection($uri, $dom); |
@@ -188,7 +188,7 @@ discard block |
||
188 | 188 | */ |
189 | 189 | public function propFind(DAV\PropFind $propFind, DAV\INode $node) |
190 | 190 | { |
191 | - $propFind->handle('{DAV:}sync-token', function () use ($node) { |
|
191 | + $propFind->handle('{DAV:}sync-token', function() use ($node) { |
|
192 | 192 | if (!$node instanceof ISyncCollection || !$token = $node->getSyncToken()) { |
193 | 193 | return; |
194 | 194 | } |
@@ -13,35 +13,35 @@ |
||
13 | 13 | */ |
14 | 14 | class Service extends \Sabre\Xml\Service |
15 | 15 | { |
16 | - /** |
|
17 | - * This is a list of XML elements that we automatically map to PHP classes. |
|
18 | - * |
|
19 | - * For instance, this list may contain an entry `{DAV:}propfind` that would |
|
20 | - * be mapped to Sabre\DAV\Xml\Request\PropFind |
|
21 | - */ |
|
22 | - public $elementMap = [ |
|
23 | - '{DAV:}multistatus' => 'Sabre\\DAV\\Xml\\Response\\MultiStatus', |
|
24 | - '{DAV:}response' => 'Sabre\\DAV\\Xml\\Element\\Response', |
|
16 | + /** |
|
17 | + * This is a list of XML elements that we automatically map to PHP classes. |
|
18 | + * |
|
19 | + * For instance, this list may contain an entry `{DAV:}propfind` that would |
|
20 | + * be mapped to Sabre\DAV\Xml\Request\PropFind |
|
21 | + */ |
|
22 | + public $elementMap = [ |
|
23 | + '{DAV:}multistatus' => 'Sabre\\DAV\\Xml\\Response\\MultiStatus', |
|
24 | + '{DAV:}response' => 'Sabre\\DAV\\Xml\\Element\\Response', |
|
25 | 25 | |
26 | - // Requests |
|
27 | - '{DAV:}propfind' => 'Sabre\\DAV\\Xml\\Request\\PropFind', |
|
28 | - '{DAV:}propertyupdate' => 'Sabre\\DAV\\Xml\\Request\\PropPatch', |
|
29 | - '{DAV:}mkcol' => 'Sabre\\DAV\\Xml\\Request\\MkCol', |
|
26 | + // Requests |
|
27 | + '{DAV:}propfind' => 'Sabre\\DAV\\Xml\\Request\\PropFind', |
|
28 | + '{DAV:}propertyupdate' => 'Sabre\\DAV\\Xml\\Request\\PropPatch', |
|
29 | + '{DAV:}mkcol' => 'Sabre\\DAV\\Xml\\Request\\MkCol', |
|
30 | 30 | |
31 | - // Properties |
|
32 | - '{DAV:}resourcetype' => 'Sabre\\DAV\\Xml\\Property\\ResourceType', |
|
33 | - ]; |
|
31 | + // Properties |
|
32 | + '{DAV:}resourcetype' => 'Sabre\\DAV\\Xml\\Property\\ResourceType', |
|
33 | + ]; |
|
34 | 34 | |
35 | - /** |
|
36 | - * This is a default list of namespaces. |
|
37 | - * |
|
38 | - * If you are defining your own custom namespace, add it here to reduce |
|
39 | - * bandwidth and improve legibility of xml bodies. |
|
40 | - * |
|
41 | - * @var array |
|
42 | - */ |
|
43 | - public $namespaceMap = [ |
|
44 | - 'DAV:' => 'd', |
|
45 | - 'http://sabredav.org/ns' => 's', |
|
46 | - ]; |
|
35 | + /** |
|
36 | + * This is a default list of namespaces. |
|
37 | + * |
|
38 | + * If you are defining your own custom namespace, add it here to reduce |
|
39 | + * bandwidth and improve legibility of xml bodies. |
|
40 | + * |
|
41 | + * @var array |
|
42 | + */ |
|
43 | + public $namespaceMap = [ |
|
44 | + 'DAV:' => 'd', |
|
45 | + 'http://sabredav.org/ns' => 's', |
|
46 | + ]; |
|
47 | 47 | } |
@@ -22,168 +22,168 @@ |
||
22 | 22 | */ |
23 | 23 | class Sharee implements Element |
24 | 24 | { |
25 | - /** |
|
26 | - * A URL. Usually a mailto: address, could also be a principal url. |
|
27 | - * This uniquely identifies the sharee. |
|
28 | - * |
|
29 | - * @var string |
|
30 | - */ |
|
31 | - public $href; |
|
32 | - |
|
33 | - /** |
|
34 | - * A local principal path. The server will do its best to locate the |
|
35 | - * principal uri based on the given uri. If we could find a local matching |
|
36 | - * principal uri, this property will contain the value. |
|
37 | - * |
|
38 | - * @var string|null |
|
39 | - */ |
|
40 | - public $principal; |
|
41 | - |
|
42 | - /** |
|
43 | - * A list of WebDAV properties that describe the sharee. This might for |
|
44 | - * example contain a {DAV:}displayname with the real name of the user. |
|
45 | - * |
|
46 | - * @var array |
|
47 | - */ |
|
48 | - public $properties = []; |
|
49 | - |
|
50 | - /** |
|
51 | - * Share access level. One of the Sabre\DAV\Sharing\Plugin::ACCESS |
|
52 | - * constants. |
|
53 | - * |
|
54 | - * Can be one of: |
|
55 | - * |
|
56 | - * ACCESS_READ |
|
57 | - * ACCESS_READWRITE |
|
58 | - * ACCESS_SHAREDOWNER |
|
59 | - * ACCESS_NOACCESS |
|
60 | - * |
|
61 | - * depending on context. |
|
62 | - * |
|
63 | - * @var int |
|
64 | - */ |
|
65 | - public $access; |
|
66 | - |
|
67 | - /** |
|
68 | - * When a sharee is originally invited to a share, the sharer may add |
|
69 | - * a comment. This will be placed in this property. |
|
70 | - * |
|
71 | - * @var string |
|
72 | - */ |
|
73 | - public $comment; |
|
74 | - |
|
75 | - /** |
|
76 | - * The status of the invite, should be one of the |
|
77 | - * Sabre\DAV\Sharing\Plugin::INVITE constants. |
|
78 | - * |
|
79 | - * @var int |
|
80 | - */ |
|
81 | - public $inviteStatus; |
|
82 | - |
|
83 | - /** |
|
84 | - * Creates the object. |
|
85 | - * |
|
86 | - * $properties will be used to populate all internal properties. |
|
87 | - */ |
|
88 | - public function __construct(array $properties = []) |
|
89 | - { |
|
90 | - foreach ($properties as $k => $v) { |
|
91 | - if (property_exists($this, $k)) { |
|
92 | - $this->$k = $v; |
|
93 | - } else { |
|
94 | - throw new \InvalidArgumentException('Unknown property: '.$k); |
|
95 | - } |
|
96 | - } |
|
97 | - } |
|
98 | - |
|
99 | - /** |
|
100 | - * The xmlSerialize method is called during xml writing. |
|
101 | - * |
|
102 | - * Use the $writer argument to write its own xml serialization. |
|
103 | - * |
|
104 | - * An important note: do _not_ create a parent element. Any element |
|
105 | - * implementing XmlSerializable should only ever write what's considered |
|
106 | - * its 'inner xml'. |
|
107 | - * |
|
108 | - * The parent of the current element is responsible for writing a |
|
109 | - * containing element. |
|
110 | - * |
|
111 | - * This allows serializers to be re-used for different element names. |
|
112 | - * |
|
113 | - * If you are opening new elements, you must also close them again. |
|
114 | - */ |
|
115 | - public function xmlSerialize(Writer $writer) |
|
116 | - { |
|
117 | - $writer->write([ |
|
118 | - new Href($this->href), |
|
119 | - '{DAV:}prop' => $this->properties, |
|
120 | - '{DAV:}share-access' => new ShareAccess($this->access), |
|
121 | - ]); |
|
122 | - switch ($this->inviteStatus) { |
|
123 | - case Plugin::INVITE_NORESPONSE: |
|
124 | - $writer->writeElement('{DAV:}invite-noresponse'); |
|
125 | - break; |
|
126 | - case Plugin::INVITE_ACCEPTED: |
|
127 | - $writer->writeElement('{DAV:}invite-accepted'); |
|
128 | - break; |
|
129 | - case Plugin::INVITE_DECLINED: |
|
130 | - $writer->writeElement('{DAV:}invite-declined'); |
|
131 | - break; |
|
132 | - case Plugin::INVITE_INVALID: |
|
133 | - $writer->writeElement('{DAV:}invite-invalid'); |
|
134 | - break; |
|
135 | - } |
|
136 | - } |
|
137 | - |
|
138 | - /** |
|
139 | - * The deserialize method is called during xml parsing. |
|
140 | - * |
|
141 | - * This method is called statically, this is because in theory this method |
|
142 | - * may be used as a type of constructor, or factory method. |
|
143 | - * |
|
144 | - * Often you want to return an instance of the current class, but you are |
|
145 | - * free to return other data as well. |
|
146 | - * |
|
147 | - * You are responsible for advancing the reader to the next element. Not |
|
148 | - * doing anything will result in a never-ending loop. |
|
149 | - * |
|
150 | - * If you just want to skip parsing for this element altogether, you can |
|
151 | - * just call $reader->next(); |
|
152 | - * |
|
153 | - * $reader->parseInnerTree() will parse the entire sub-tree, and advance to |
|
154 | - * the next element. |
|
155 | - * |
|
156 | - * @return mixed |
|
157 | - */ |
|
158 | - public static function xmlDeserialize(Reader $reader) |
|
159 | - { |
|
160 | - // Temporarily override configuration |
|
161 | - $reader->pushContext(); |
|
162 | - $reader->elementMap['{DAV:}share-access'] = 'Sabre\DAV\Xml\Property\ShareAccess'; |
|
163 | - $reader->elementMap['{DAV:}prop'] = 'Sabre\Xml\Deserializer\keyValue'; |
|
164 | - |
|
165 | - $elems = Deserializer\keyValue($reader, 'DAV:'); |
|
166 | - |
|
167 | - // Restore previous configuration |
|
168 | - $reader->popContext(); |
|
169 | - |
|
170 | - $sharee = new self(); |
|
171 | - if (!isset($elems['href'])) { |
|
172 | - throw new BadRequest('Every {DAV:}sharee must have a {DAV:}href child-element'); |
|
173 | - } |
|
174 | - $sharee->href = $elems['href']; |
|
175 | - |
|
176 | - if (isset($elems['prop'])) { |
|
177 | - $sharee->properties = $elems['prop']; |
|
178 | - } |
|
179 | - if (isset($elems['comment'])) { |
|
180 | - $sharee->comment = $elems['comment']; |
|
181 | - } |
|
182 | - if (!isset($elems['share-access'])) { |
|
183 | - throw new BadRequest('Every {DAV:}sharee must have a {DAV:}share-access child element'); |
|
184 | - } |
|
185 | - $sharee->access = $elems['share-access']->getValue(); |
|
186 | - |
|
187 | - return $sharee; |
|
188 | - } |
|
25 | + /** |
|
26 | + * A URL. Usually a mailto: address, could also be a principal url. |
|
27 | + * This uniquely identifies the sharee. |
|
28 | + * |
|
29 | + * @var string |
|
30 | + */ |
|
31 | + public $href; |
|
32 | + |
|
33 | + /** |
|
34 | + * A local principal path. The server will do its best to locate the |
|
35 | + * principal uri based on the given uri. If we could find a local matching |
|
36 | + * principal uri, this property will contain the value. |
|
37 | + * |
|
38 | + * @var string|null |
|
39 | + */ |
|
40 | + public $principal; |
|
41 | + |
|
42 | + /** |
|
43 | + * A list of WebDAV properties that describe the sharee. This might for |
|
44 | + * example contain a {DAV:}displayname with the real name of the user. |
|
45 | + * |
|
46 | + * @var array |
|
47 | + */ |
|
48 | + public $properties = []; |
|
49 | + |
|
50 | + /** |
|
51 | + * Share access level. One of the Sabre\DAV\Sharing\Plugin::ACCESS |
|
52 | + * constants. |
|
53 | + * |
|
54 | + * Can be one of: |
|
55 | + * |
|
56 | + * ACCESS_READ |
|
57 | + * ACCESS_READWRITE |
|
58 | + * ACCESS_SHAREDOWNER |
|
59 | + * ACCESS_NOACCESS |
|
60 | + * |
|
61 | + * depending on context. |
|
62 | + * |
|
63 | + * @var int |
|
64 | + */ |
|
65 | + public $access; |
|
66 | + |
|
67 | + /** |
|
68 | + * When a sharee is originally invited to a share, the sharer may add |
|
69 | + * a comment. This will be placed in this property. |
|
70 | + * |
|
71 | + * @var string |
|
72 | + */ |
|
73 | + public $comment; |
|
74 | + |
|
75 | + /** |
|
76 | + * The status of the invite, should be one of the |
|
77 | + * Sabre\DAV\Sharing\Plugin::INVITE constants. |
|
78 | + * |
|
79 | + * @var int |
|
80 | + */ |
|
81 | + public $inviteStatus; |
|
82 | + |
|
83 | + /** |
|
84 | + * Creates the object. |
|
85 | + * |
|
86 | + * $properties will be used to populate all internal properties. |
|
87 | + */ |
|
88 | + public function __construct(array $properties = []) |
|
89 | + { |
|
90 | + foreach ($properties as $k => $v) { |
|
91 | + if (property_exists($this, $k)) { |
|
92 | + $this->$k = $v; |
|
93 | + } else { |
|
94 | + throw new \InvalidArgumentException('Unknown property: '.$k); |
|
95 | + } |
|
96 | + } |
|
97 | + } |
|
98 | + |
|
99 | + /** |
|
100 | + * The xmlSerialize method is called during xml writing. |
|
101 | + * |
|
102 | + * Use the $writer argument to write its own xml serialization. |
|
103 | + * |
|
104 | + * An important note: do _not_ create a parent element. Any element |
|
105 | + * implementing XmlSerializable should only ever write what's considered |
|
106 | + * its 'inner xml'. |
|
107 | + * |
|
108 | + * The parent of the current element is responsible for writing a |
|
109 | + * containing element. |
|
110 | + * |
|
111 | + * This allows serializers to be re-used for different element names. |
|
112 | + * |
|
113 | + * If you are opening new elements, you must also close them again. |
|
114 | + */ |
|
115 | + public function xmlSerialize(Writer $writer) |
|
116 | + { |
|
117 | + $writer->write([ |
|
118 | + new Href($this->href), |
|
119 | + '{DAV:}prop' => $this->properties, |
|
120 | + '{DAV:}share-access' => new ShareAccess($this->access), |
|
121 | + ]); |
|
122 | + switch ($this->inviteStatus) { |
|
123 | + case Plugin::INVITE_NORESPONSE: |
|
124 | + $writer->writeElement('{DAV:}invite-noresponse'); |
|
125 | + break; |
|
126 | + case Plugin::INVITE_ACCEPTED: |
|
127 | + $writer->writeElement('{DAV:}invite-accepted'); |
|
128 | + break; |
|
129 | + case Plugin::INVITE_DECLINED: |
|
130 | + $writer->writeElement('{DAV:}invite-declined'); |
|
131 | + break; |
|
132 | + case Plugin::INVITE_INVALID: |
|
133 | + $writer->writeElement('{DAV:}invite-invalid'); |
|
134 | + break; |
|
135 | + } |
|
136 | + } |
|
137 | + |
|
138 | + /** |
|
139 | + * The deserialize method is called during xml parsing. |
|
140 | + * |
|
141 | + * This method is called statically, this is because in theory this method |
|
142 | + * may be used as a type of constructor, or factory method. |
|
143 | + * |
|
144 | + * Often you want to return an instance of the current class, but you are |
|
145 | + * free to return other data as well. |
|
146 | + * |
|
147 | + * You are responsible for advancing the reader to the next element. Not |
|
148 | + * doing anything will result in a never-ending loop. |
|
149 | + * |
|
150 | + * If you just want to skip parsing for this element altogether, you can |
|
151 | + * just call $reader->next(); |
|
152 | + * |
|
153 | + * $reader->parseInnerTree() will parse the entire sub-tree, and advance to |
|
154 | + * the next element. |
|
155 | + * |
|
156 | + * @return mixed |
|
157 | + */ |
|
158 | + public static function xmlDeserialize(Reader $reader) |
|
159 | + { |
|
160 | + // Temporarily override configuration |
|
161 | + $reader->pushContext(); |
|
162 | + $reader->elementMap['{DAV:}share-access'] = 'Sabre\DAV\Xml\Property\ShareAccess'; |
|
163 | + $reader->elementMap['{DAV:}prop'] = 'Sabre\Xml\Deserializer\keyValue'; |
|
164 | + |
|
165 | + $elems = Deserializer\keyValue($reader, 'DAV:'); |
|
166 | + |
|
167 | + // Restore previous configuration |
|
168 | + $reader->popContext(); |
|
169 | + |
|
170 | + $sharee = new self(); |
|
171 | + if (!isset($elems['href'])) { |
|
172 | + throw new BadRequest('Every {DAV:}sharee must have a {DAV:}href child-element'); |
|
173 | + } |
|
174 | + $sharee->href = $elems['href']; |
|
175 | + |
|
176 | + if (isset($elems['prop'])) { |
|
177 | + $sharee->properties = $elems['prop']; |
|
178 | + } |
|
179 | + if (isset($elems['comment'])) { |
|
180 | + $sharee->comment = $elems['comment']; |
|
181 | + } |
|
182 | + if (!isset($elems['share-access'])) { |
|
183 | + throw new BadRequest('Every {DAV:}sharee must have a {DAV:}share-access child element'); |
|
184 | + } |
|
185 | + $sharee->access = $elems['share-access']->getValue(); |
|
186 | + |
|
187 | + return $sharee; |
|
188 | + } |
|
189 | 189 | } |
@@ -180,7 +180,7 @@ |
||
180 | 180 | // called. But we don't want this, because a singular element without |
181 | 181 | // child-elements implies 'no value' in {DAV:}prop, so we want to skip |
182 | 182 | // deserializers and just set null for those. |
183 | - $reader->elementMap['{DAV:}prop'] = function (Reader $reader) { |
|
183 | + $reader->elementMap['{DAV:}prop'] = function(Reader $reader) { |
|
184 | 184 | if ($reader->isEmptyElement) { |
185 | 185 | $reader->next(); |
186 | 186 |
@@ -21,98 +21,98 @@ discard block |
||
21 | 21 | */ |
22 | 22 | class Response implements Element |
23 | 23 | { |
24 | - /** |
|
25 | - * Url for the response. |
|
26 | - * |
|
27 | - * @var string |
|
28 | - */ |
|
29 | - protected $href; |
|
24 | + /** |
|
25 | + * Url for the response. |
|
26 | + * |
|
27 | + * @var string |
|
28 | + */ |
|
29 | + protected $href; |
|
30 | 30 | |
31 | - /** |
|
32 | - * Propertylist, ordered by HTTP status code. |
|
33 | - * |
|
34 | - * @var array |
|
35 | - */ |
|
36 | - protected $responseProperties; |
|
31 | + /** |
|
32 | + * Propertylist, ordered by HTTP status code. |
|
33 | + * |
|
34 | + * @var array |
|
35 | + */ |
|
36 | + protected $responseProperties; |
|
37 | 37 | |
38 | - /** |
|
39 | - * The HTTP status for an entire response. |
|
40 | - * |
|
41 | - * This is currently only used in WebDAV-Sync |
|
42 | - * |
|
43 | - * @var string|null |
|
44 | - */ |
|
45 | - protected $httpStatus; |
|
38 | + /** |
|
39 | + * The HTTP status for an entire response. |
|
40 | + * |
|
41 | + * This is currently only used in WebDAV-Sync |
|
42 | + * |
|
43 | + * @var string|null |
|
44 | + */ |
|
45 | + protected $httpStatus; |
|
46 | 46 | |
47 | - /** |
|
48 | - * The href argument is a url relative to the root of the server. This |
|
49 | - * class will calculate the full path. |
|
50 | - * |
|
51 | - * The responseProperties argument is a list of properties |
|
52 | - * within an array with keys representing HTTP status codes |
|
53 | - * |
|
54 | - * Besides specific properties, the entire {DAV:}response element may also |
|
55 | - * have a http status code. |
|
56 | - * In most cases you don't need it. |
|
57 | - * |
|
58 | - * This is currently used by the Sync extension to indicate that a node is |
|
59 | - * deleted. |
|
60 | - * |
|
61 | - * @param string $href |
|
62 | - * @param string $httpStatus |
|
63 | - */ |
|
64 | - public function __construct($href, array $responseProperties, $httpStatus = null) |
|
65 | - { |
|
66 | - $this->href = $href; |
|
67 | - $this->responseProperties = $responseProperties; |
|
68 | - $this->httpStatus = $httpStatus; |
|
69 | - } |
|
47 | + /** |
|
48 | + * The href argument is a url relative to the root of the server. This |
|
49 | + * class will calculate the full path. |
|
50 | + * |
|
51 | + * The responseProperties argument is a list of properties |
|
52 | + * within an array with keys representing HTTP status codes |
|
53 | + * |
|
54 | + * Besides specific properties, the entire {DAV:}response element may also |
|
55 | + * have a http status code. |
|
56 | + * In most cases you don't need it. |
|
57 | + * |
|
58 | + * This is currently used by the Sync extension to indicate that a node is |
|
59 | + * deleted. |
|
60 | + * |
|
61 | + * @param string $href |
|
62 | + * @param string $httpStatus |
|
63 | + */ |
|
64 | + public function __construct($href, array $responseProperties, $httpStatus = null) |
|
65 | + { |
|
66 | + $this->href = $href; |
|
67 | + $this->responseProperties = $responseProperties; |
|
68 | + $this->httpStatus = $httpStatus; |
|
69 | + } |
|
70 | 70 | |
71 | - /** |
|
72 | - * Returns the url. |
|
73 | - * |
|
74 | - * @return string |
|
75 | - */ |
|
76 | - public function getHref() |
|
77 | - { |
|
78 | - return $this->href; |
|
79 | - } |
|
71 | + /** |
|
72 | + * Returns the url. |
|
73 | + * |
|
74 | + * @return string |
|
75 | + */ |
|
76 | + public function getHref() |
|
77 | + { |
|
78 | + return $this->href; |
|
79 | + } |
|
80 | 80 | |
81 | - /** |
|
82 | - * Returns the httpStatus value. |
|
83 | - * |
|
84 | - * @return string |
|
85 | - */ |
|
86 | - public function getHttpStatus() |
|
87 | - { |
|
88 | - return $this->httpStatus; |
|
89 | - } |
|
81 | + /** |
|
82 | + * Returns the httpStatus value. |
|
83 | + * |
|
84 | + * @return string |
|
85 | + */ |
|
86 | + public function getHttpStatus() |
|
87 | + { |
|
88 | + return $this->httpStatus; |
|
89 | + } |
|
90 | 90 | |
91 | - /** |
|
92 | - * Returns the property list. |
|
93 | - * |
|
94 | - * @return array |
|
95 | - */ |
|
96 | - public function getResponseProperties() |
|
97 | - { |
|
98 | - return $this->responseProperties; |
|
99 | - } |
|
91 | + /** |
|
92 | + * Returns the property list. |
|
93 | + * |
|
94 | + * @return array |
|
95 | + */ |
|
96 | + public function getResponseProperties() |
|
97 | + { |
|
98 | + return $this->responseProperties; |
|
99 | + } |
|
100 | 100 | |
101 | - /** |
|
102 | - * The serialize method is called during xml writing. |
|
103 | - * |
|
104 | - * It should use the $writer argument to encode this object into XML. |
|
105 | - * |
|
106 | - * Important note: it is not needed to create the parent element. The |
|
107 | - * parent element is already created, and we only have to worry about |
|
108 | - * attributes, child elements and text (if any). |
|
109 | - * |
|
110 | - * Important note 2: If you are writing any new elements, you are also |
|
111 | - * responsible for closing them. |
|
112 | - */ |
|
113 | - public function xmlSerialize(Writer $writer) |
|
114 | - { |
|
115 | - /* |
|
101 | + /** |
|
102 | + * The serialize method is called during xml writing. |
|
103 | + * |
|
104 | + * It should use the $writer argument to encode this object into XML. |
|
105 | + * |
|
106 | + * Important note: it is not needed to create the parent element. The |
|
107 | + * parent element is already created, and we only have to worry about |
|
108 | + * attributes, child elements and text (if any). |
|
109 | + * |
|
110 | + * Important note 2: If you are writing any new elements, you are also |
|
111 | + * responsible for closing them. |
|
112 | + */ |
|
113 | + public function xmlSerialize(Writer $writer) |
|
114 | + { |
|
115 | + /* |
|
116 | 116 | * Accordingly to the RFC the element looks like: |
117 | 117 | * <!ELEMENT response (href, ((href*, status)|(propstat+)), error?, responsedescription? , location?) > |
118 | 118 | * |
@@ -121,30 +121,30 @@ discard block |
||
121 | 121 | * - EITHER a status and additional href(s) |
122 | 122 | * OR one or more propstat(s) |
123 | 123 | */ |
124 | - $writer->writeElement('{DAV:}href', $writer->contextUri.\Sabre\HTTP\encodePath($this->getHref())); |
|
124 | + $writer->writeElement('{DAV:}href', $writer->contextUri.\Sabre\HTTP\encodePath($this->getHref())); |
|
125 | 125 | |
126 | - $empty = true; |
|
127 | - $httpStatus = $this->getHTTPStatus(); |
|
126 | + $empty = true; |
|
127 | + $httpStatus = $this->getHTTPStatus(); |
|
128 | 128 | |
129 | - // Add propstat elements |
|
130 | - foreach ($this->getResponseProperties() as $status => $properties) { |
|
131 | - // Skipping empty lists |
|
132 | - if (!$properties || (!is_int($status) && !ctype_digit($status))) { |
|
133 | - continue; |
|
134 | - } |
|
135 | - $empty = false; |
|
136 | - $writer->startElement('{DAV:}propstat'); |
|
137 | - $writer->writeElement('{DAV:}prop', $properties); |
|
138 | - $writer->writeElement('{DAV:}status', 'HTTP/1.1 '.$status.' '.\Sabre\HTTP\Response::$statusCodes[$status]); |
|
139 | - $writer->endElement(); // {DAV:}propstat |
|
140 | - } |
|
129 | + // Add propstat elements |
|
130 | + foreach ($this->getResponseProperties() as $status => $properties) { |
|
131 | + // Skipping empty lists |
|
132 | + if (!$properties || (!is_int($status) && !ctype_digit($status))) { |
|
133 | + continue; |
|
134 | + } |
|
135 | + $empty = false; |
|
136 | + $writer->startElement('{DAV:}propstat'); |
|
137 | + $writer->writeElement('{DAV:}prop', $properties); |
|
138 | + $writer->writeElement('{DAV:}status', 'HTTP/1.1 '.$status.' '.\Sabre\HTTP\Response::$statusCodes[$status]); |
|
139 | + $writer->endElement(); // {DAV:}propstat |
|
140 | + } |
|
141 | 141 | |
142 | - // The WebDAV spec only allows the status element on responses _without_ a propstat |
|
143 | - if ($empty) { |
|
144 | - if (null !== $httpStatus) { |
|
145 | - $writer->writeElement('{DAV:}status', 'HTTP/1.1 '.$httpStatus.' '.\Sabre\HTTP\Response::$statusCodes[$httpStatus]); |
|
146 | - } else { |
|
147 | - /* |
|
142 | + // The WebDAV spec only allows the status element on responses _without_ a propstat |
|
143 | + if ($empty) { |
|
144 | + if (null !== $httpStatus) { |
|
145 | + $writer->writeElement('{DAV:}status', 'HTTP/1.1 '.$httpStatus.' '.\Sabre\HTTP\Response::$statusCodes[$httpStatus]); |
|
146 | + } else { |
|
147 | + /* |
|
148 | 148 | * The WebDAV spec _requires_ at least one DAV:propstat to appear for |
149 | 149 | * every DAV:response if there is no status. |
150 | 150 | * In some circumstances however, there are no properties to encode. |
@@ -152,116 +152,116 @@ discard block |
||
152 | 152 | * In those cases we MUST specify at least one DAV:propstat anyway, with |
153 | 153 | * no properties. |
154 | 154 | */ |
155 | - $writer->writeElement('{DAV:}propstat', [ |
|
156 | - '{DAV:}prop' => [], |
|
157 | - '{DAV:}status' => 'HTTP/1.1 418 '.\Sabre\HTTP\Response::$statusCodes[418], |
|
158 | - ]); |
|
159 | - } |
|
160 | - } |
|
161 | - } |
|
155 | + $writer->writeElement('{DAV:}propstat', [ |
|
156 | + '{DAV:}prop' => [], |
|
157 | + '{DAV:}status' => 'HTTP/1.1 418 '.\Sabre\HTTP\Response::$statusCodes[418], |
|
158 | + ]); |
|
159 | + } |
|
160 | + } |
|
161 | + } |
|
162 | 162 | |
163 | - /** |
|
164 | - * The deserialize method is called during xml parsing. |
|
165 | - * |
|
166 | - * This method is called statically, this is because in theory this method |
|
167 | - * may be used as a type of constructor, or factory method. |
|
168 | - * |
|
169 | - * Often you want to return an instance of the current class, but you are |
|
170 | - * free to return other data as well. |
|
171 | - * |
|
172 | - * You are responsible for advancing the reader to the next element. Not |
|
173 | - * doing anything will result in a never-ending loop. |
|
174 | - * |
|
175 | - * If you just want to skip parsing for this element altogether, you can |
|
176 | - * just call $reader->next(); |
|
177 | - * |
|
178 | - * $reader->parseInnerTree() will parse the entire sub-tree, and advance to |
|
179 | - * the next element. |
|
180 | - * |
|
181 | - * @return mixed |
|
182 | - */ |
|
183 | - public static function xmlDeserialize(Reader $reader) |
|
184 | - { |
|
185 | - $reader->pushContext(); |
|
163 | + /** |
|
164 | + * The deserialize method is called during xml parsing. |
|
165 | + * |
|
166 | + * This method is called statically, this is because in theory this method |
|
167 | + * may be used as a type of constructor, or factory method. |
|
168 | + * |
|
169 | + * Often you want to return an instance of the current class, but you are |
|
170 | + * free to return other data as well. |
|
171 | + * |
|
172 | + * You are responsible for advancing the reader to the next element. Not |
|
173 | + * doing anything will result in a never-ending loop. |
|
174 | + * |
|
175 | + * If you just want to skip parsing for this element altogether, you can |
|
176 | + * just call $reader->next(); |
|
177 | + * |
|
178 | + * $reader->parseInnerTree() will parse the entire sub-tree, and advance to |
|
179 | + * the next element. |
|
180 | + * |
|
181 | + * @return mixed |
|
182 | + */ |
|
183 | + public static function xmlDeserialize(Reader $reader) |
|
184 | + { |
|
185 | + $reader->pushContext(); |
|
186 | 186 | |
187 | - $reader->elementMap['{DAV:}propstat'] = 'Sabre\\Xml\\Element\\KeyValue'; |
|
187 | + $reader->elementMap['{DAV:}propstat'] = 'Sabre\\Xml\\Element\\KeyValue'; |
|
188 | 188 | |
189 | - // We are overriding the parser for {DAV:}prop. This deserializer is |
|
190 | - // almost identical to the one for Sabre\Xml\Element\KeyValue. |
|
191 | - // |
|
192 | - // The difference is that if there are any child-elements inside of |
|
193 | - // {DAV:}prop, that have no value, normally any deserializers are |
|
194 | - // called. But we don't want this, because a singular element without |
|
195 | - // child-elements implies 'no value' in {DAV:}prop, so we want to skip |
|
196 | - // deserializers and just set null for those. |
|
197 | - $reader->elementMap['{DAV:}prop'] = function (Reader $reader) { |
|
198 | - if ($reader->isEmptyElement) { |
|
199 | - $reader->next(); |
|
189 | + // We are overriding the parser for {DAV:}prop. This deserializer is |
|
190 | + // almost identical to the one for Sabre\Xml\Element\KeyValue. |
|
191 | + // |
|
192 | + // The difference is that if there are any child-elements inside of |
|
193 | + // {DAV:}prop, that have no value, normally any deserializers are |
|
194 | + // called. But we don't want this, because a singular element without |
|
195 | + // child-elements implies 'no value' in {DAV:}prop, so we want to skip |
|
196 | + // deserializers and just set null for those. |
|
197 | + $reader->elementMap['{DAV:}prop'] = function (Reader $reader) { |
|
198 | + if ($reader->isEmptyElement) { |
|
199 | + $reader->next(); |
|
200 | 200 | |
201 | - return []; |
|
202 | - } |
|
201 | + return []; |
|
202 | + } |
|
203 | 203 | |
204 | - if (!$reader->read()) { |
|
205 | - $reader->next(); |
|
204 | + if (!$reader->read()) { |
|
205 | + $reader->next(); |
|
206 | 206 | |
207 | - return []; |
|
208 | - } |
|
207 | + return []; |
|
208 | + } |
|
209 | 209 | |
210 | - if (Reader::END_ELEMENT === $reader->nodeType) { |
|
211 | - $reader->next(); |
|
210 | + if (Reader::END_ELEMENT === $reader->nodeType) { |
|
211 | + $reader->next(); |
|
212 | 212 | |
213 | - return []; |
|
214 | - } |
|
213 | + return []; |
|
214 | + } |
|
215 | 215 | |
216 | - $values = []; |
|
216 | + $values = []; |
|
217 | 217 | |
218 | - do { |
|
219 | - if (Reader::ELEMENT === $reader->nodeType) { |
|
220 | - $clark = $reader->getClark(); |
|
218 | + do { |
|
219 | + if (Reader::ELEMENT === $reader->nodeType) { |
|
220 | + $clark = $reader->getClark(); |
|
221 | 221 | |
222 | - if ($reader->isEmptyElement) { |
|
223 | - $values[$clark] = null; |
|
224 | - $reader->next(); |
|
225 | - } else { |
|
226 | - $values[$clark] = $reader->parseCurrentElement()['value']; |
|
227 | - } |
|
228 | - } else { |
|
229 | - if (!$reader->read()) { |
|
230 | - break; |
|
231 | - } |
|
232 | - } |
|
233 | - } while (Reader::END_ELEMENT !== $reader->nodeType); |
|
222 | + if ($reader->isEmptyElement) { |
|
223 | + $values[$clark] = null; |
|
224 | + $reader->next(); |
|
225 | + } else { |
|
226 | + $values[$clark] = $reader->parseCurrentElement()['value']; |
|
227 | + } |
|
228 | + } else { |
|
229 | + if (!$reader->read()) { |
|
230 | + break; |
|
231 | + } |
|
232 | + } |
|
233 | + } while (Reader::END_ELEMENT !== $reader->nodeType); |
|
234 | 234 | |
235 | - $reader->read(); |
|
235 | + $reader->read(); |
|
236 | 236 | |
237 | - return $values; |
|
238 | - }; |
|
239 | - $elems = $reader->parseInnerTree(); |
|
240 | - $reader->popContext(); |
|
237 | + return $values; |
|
238 | + }; |
|
239 | + $elems = $reader->parseInnerTree(); |
|
240 | + $reader->popContext(); |
|
241 | 241 | |
242 | - $href = null; |
|
243 | - $propertyLists = []; |
|
244 | - $statusCode = null; |
|
242 | + $href = null; |
|
243 | + $propertyLists = []; |
|
244 | + $statusCode = null; |
|
245 | 245 | |
246 | - foreach ($elems as $elem) { |
|
247 | - switch ($elem['name']) { |
|
248 | - case '{DAV:}href': |
|
249 | - $href = $elem['value']; |
|
250 | - break; |
|
251 | - case '{DAV:}propstat': |
|
252 | - $status = $elem['value']['{DAV:}status']; |
|
253 | - list(, $status) = explode(' ', $status, 3); |
|
254 | - $properties = isset($elem['value']['{DAV:}prop']) ? $elem['value']['{DAV:}prop'] : []; |
|
255 | - if ($properties) { |
|
256 | - $propertyLists[$status] = $properties; |
|
257 | - } |
|
258 | - break; |
|
259 | - case '{DAV:}status': |
|
260 | - list(, $statusCode) = explode(' ', $elem['value'], 3); |
|
261 | - break; |
|
262 | - } |
|
263 | - } |
|
246 | + foreach ($elems as $elem) { |
|
247 | + switch ($elem['name']) { |
|
248 | + case '{DAV:}href': |
|
249 | + $href = $elem['value']; |
|
250 | + break; |
|
251 | + case '{DAV:}propstat': |
|
252 | + $status = $elem['value']['{DAV:}status']; |
|
253 | + list(, $status) = explode(' ', $status, 3); |
|
254 | + $properties = isset($elem['value']['{DAV:}prop']) ? $elem['value']['{DAV:}prop'] : []; |
|
255 | + if ($properties) { |
|
256 | + $propertyLists[$status] = $properties; |
|
257 | + } |
|
258 | + break; |
|
259 | + case '{DAV:}status': |
|
260 | + list(, $statusCode) = explode(' ', $elem['value'], 3); |
|
261 | + break; |
|
262 | + } |
|
263 | + } |
|
264 | 264 | |
265 | - return new self($href, $propertyLists, $statusCode); |
|
266 | - } |
|
265 | + return new self($href, $propertyLists, $statusCode); |
|
266 | + } |
|
267 | 267 | } |
@@ -21,90 +21,90 @@ |
||
21 | 21 | */ |
22 | 22 | class Prop implements XmlDeserializable |
23 | 23 | { |
24 | - /** |
|
25 | - * The deserialize method is called during xml parsing. |
|
26 | - * |
|
27 | - * This method is called statically, this is because in theory this method |
|
28 | - * may be used as a type of constructor, or factory method. |
|
29 | - * |
|
30 | - * Often you want to return an instance of the current class, but you are |
|
31 | - * free to return other data as well. |
|
32 | - * |
|
33 | - * You are responsible for advancing the reader to the next element. Not |
|
34 | - * doing anything will result in a never-ending loop. |
|
35 | - * |
|
36 | - * If you just want to skip parsing for this element altogether, you can |
|
37 | - * just call $reader->next(); |
|
38 | - * |
|
39 | - * $reader->parseInnerTree() will parse the entire sub-tree, and advance to |
|
40 | - * the next element. |
|
41 | - * |
|
42 | - * @return mixed |
|
43 | - */ |
|
44 | - public static function xmlDeserialize(Reader $reader) |
|
45 | - { |
|
46 | - // If there's no children, we don't do anything. |
|
47 | - if ($reader->isEmptyElement) { |
|
48 | - $reader->next(); |
|
24 | + /** |
|
25 | + * The deserialize method is called during xml parsing. |
|
26 | + * |
|
27 | + * This method is called statically, this is because in theory this method |
|
28 | + * may be used as a type of constructor, or factory method. |
|
29 | + * |
|
30 | + * Often you want to return an instance of the current class, but you are |
|
31 | + * free to return other data as well. |
|
32 | + * |
|
33 | + * You are responsible for advancing the reader to the next element. Not |
|
34 | + * doing anything will result in a never-ending loop. |
|
35 | + * |
|
36 | + * If you just want to skip parsing for this element altogether, you can |
|
37 | + * just call $reader->next(); |
|
38 | + * |
|
39 | + * $reader->parseInnerTree() will parse the entire sub-tree, and advance to |
|
40 | + * the next element. |
|
41 | + * |
|
42 | + * @return mixed |
|
43 | + */ |
|
44 | + public static function xmlDeserialize(Reader $reader) |
|
45 | + { |
|
46 | + // If there's no children, we don't do anything. |
|
47 | + if ($reader->isEmptyElement) { |
|
48 | + $reader->next(); |
|
49 | 49 | |
50 | - return []; |
|
51 | - } |
|
50 | + return []; |
|
51 | + } |
|
52 | 52 | |
53 | - $values = []; |
|
53 | + $values = []; |
|
54 | 54 | |
55 | - $reader->read(); |
|
56 | - do { |
|
57 | - if (Reader::ELEMENT === $reader->nodeType) { |
|
58 | - $clark = $reader->getClark(); |
|
59 | - $values[$clark] = self::parseCurrentElement($reader)['value']; |
|
60 | - } else { |
|
61 | - $reader->read(); |
|
62 | - } |
|
63 | - } while (Reader::END_ELEMENT !== $reader->nodeType); |
|
55 | + $reader->read(); |
|
56 | + do { |
|
57 | + if (Reader::ELEMENT === $reader->nodeType) { |
|
58 | + $clark = $reader->getClark(); |
|
59 | + $values[$clark] = self::parseCurrentElement($reader)['value']; |
|
60 | + } else { |
|
61 | + $reader->read(); |
|
62 | + } |
|
63 | + } while (Reader::END_ELEMENT !== $reader->nodeType); |
|
64 | 64 | |
65 | - $reader->read(); |
|
65 | + $reader->read(); |
|
66 | 66 | |
67 | - return $values; |
|
68 | - } |
|
67 | + return $values; |
|
68 | + } |
|
69 | 69 | |
70 | - /** |
|
71 | - * This function behaves similar to Sabre\Xml\Reader::parseCurrentElement, |
|
72 | - * but instead of creating deep xml array structures, it will turn any |
|
73 | - * top-level element it doesn't recognize into either a string, or an |
|
74 | - * XmlFragment class. |
|
75 | - * |
|
76 | - * This method returns arn array with 2 properties: |
|
77 | - * * name - A clark-notation XML element name. |
|
78 | - * * value - The parsed value. |
|
79 | - * |
|
80 | - * @return array |
|
81 | - */ |
|
82 | - private static function parseCurrentElement(Reader $reader) |
|
83 | - { |
|
84 | - $name = $reader->getClark(); |
|
70 | + /** |
|
71 | + * This function behaves similar to Sabre\Xml\Reader::parseCurrentElement, |
|
72 | + * but instead of creating deep xml array structures, it will turn any |
|
73 | + * top-level element it doesn't recognize into either a string, or an |
|
74 | + * XmlFragment class. |
|
75 | + * |
|
76 | + * This method returns arn array with 2 properties: |
|
77 | + * * name - A clark-notation XML element name. |
|
78 | + * * value - The parsed value. |
|
79 | + * |
|
80 | + * @return array |
|
81 | + */ |
|
82 | + private static function parseCurrentElement(Reader $reader) |
|
83 | + { |
|
84 | + $name = $reader->getClark(); |
|
85 | 85 | |
86 | - if (array_key_exists($name, $reader->elementMap)) { |
|
87 | - $deserializer = $reader->elementMap[$name]; |
|
88 | - if (is_subclass_of($deserializer, 'Sabre\\Xml\\XmlDeserializable')) { |
|
89 | - $value = call_user_func([$deserializer, 'xmlDeserialize'], $reader); |
|
90 | - } elseif (is_callable($deserializer)) { |
|
91 | - $value = call_user_func($deserializer, $reader); |
|
92 | - } else { |
|
93 | - $type = gettype($deserializer); |
|
94 | - if ('string' === $type) { |
|
95 | - $type .= ' ('.$deserializer.')'; |
|
96 | - } elseif ('object' === $type) { |
|
97 | - $type .= ' ('.get_class($deserializer).')'; |
|
98 | - } |
|
99 | - throw new \LogicException('Could not use this type as a deserializer: '.$type); |
|
100 | - } |
|
101 | - } else { |
|
102 | - $value = Complex::xmlDeserialize($reader); |
|
103 | - } |
|
86 | + if (array_key_exists($name, $reader->elementMap)) { |
|
87 | + $deserializer = $reader->elementMap[$name]; |
|
88 | + if (is_subclass_of($deserializer, 'Sabre\\Xml\\XmlDeserializable')) { |
|
89 | + $value = call_user_func([$deserializer, 'xmlDeserialize'], $reader); |
|
90 | + } elseif (is_callable($deserializer)) { |
|
91 | + $value = call_user_func($deserializer, $reader); |
|
92 | + } else { |
|
93 | + $type = gettype($deserializer); |
|
94 | + if ('string' === $type) { |
|
95 | + $type .= ' ('.$deserializer.')'; |
|
96 | + } elseif ('object' === $type) { |
|
97 | + $type .= ' ('.get_class($deserializer).')'; |
|
98 | + } |
|
99 | + throw new \LogicException('Could not use this type as a deserializer: '.$type); |
|
100 | + } |
|
101 | + } else { |
|
102 | + $value = Complex::xmlDeserialize($reader); |
|
103 | + } |
|
104 | 104 | |
105 | - return [ |
|
106 | - 'name' => $name, |
|
107 | - 'value' => $value, |
|
108 | - ]; |
|
109 | - } |
|
105 | + return [ |
|
106 | + 'name' => $name, |
|
107 | + 'value' => $value, |
|
108 | + ]; |
|
109 | + } |
|
110 | 110 | } |