/** * Draws a table row for a property * * @param string $name * @param mixed $value * @return string */ private function drawPropertyRow($name, $value) { $view = 'unknown'; if (is_string($value)) { $view = 'string'; } elseif ($value instanceof DAV\Property) { $mapping = ['Sabre\\DAV\\Property\\IHref' => 'href', 'Sabre\\DAV\\Property\\HrefList' => 'hreflist', 'Sabre\\DAV\\Property\\SupportedMethodSet' => 'valuelist', 'Sabre\\DAV\\Property\\ResourceType' => 'xmlvaluelist', 'Sabre\\DAV\\Property\\SupportedReportSet' => 'xmlvaluelist', 'Sabre\\DAVACL\\Property\\CurrentUserPrivilegeSet' => 'xmlvaluelist', 'Sabre\\DAVACL\\Property\\SupportedPrivilegeSet' => 'supported-privilege-set']; $view = 'complex'; foreach ($mapping as $class => $val) { if ($value instanceof $class) { $view = $val; break; } } } list($ns, $localName) = DAV\XMLUtil::parseClarkNotation($name); $realName = $name; if (isset($this->server->xmlNamespaces[$ns])) { $name = $this->server->xmlNamespaces[$ns] . ':' . $localName; } ob_start(); $xmlValueDisplay = function ($propName) { $realPropName = $propName; list($ns, $localName) = DAV\XMLUtil::parseClarkNotation($propName); if (isset($this->server->xmlNamespaces[$ns])) { $propName = $this->server->xmlNamespaces[$ns] . ':' . $localName; } return "<span title=\"" . $this->escapeHTML($realPropName) . "\">" . $this->escapeHTML($propName) . "</span>"; }; echo "<tr><th><span title=\"", $this->escapeHTML($realName), "\">", $this->escapeHTML($name), "</span></th><td>"; switch ($view) { case 'href': echo "<a href=\"" . $this->server->getBaseUri() . $value->getHref() . '">' . $this->server->getBaseUri() . $value->getHref() . '</a>'; break; case 'hreflist': echo implode('<br />', array_map(function ($href) { if (stripos($href, 'mailto:') === 0 || stripos($href, '/') === 0 || stripos($href, 'http:') === 0 || stripos($href, 'https:') === 0) { return "<a href=\"" . $this->escapeHTML($href) . '">' . $this->escapeHTML($href) . '</a>'; } else { return "<a href=\"" . $this->escapeHTML($this->server->getBaseUri() . $href) . '">' . $this->escapeHTML($this->server->getBaseUri() . $href) . '</a>'; } }, $value->getHrefs())); break; case 'xmlvaluelist': echo implode(', ', array_map($xmlValueDisplay, $value->getValue())); break; case 'valuelist': echo $this->escapeHTML(implode(', ', $value->getValue())); break; case 'supported-privilege-set': $traverse = function ($priv) use(&$traverse, $xmlValueDisplay) { echo "<li>"; echo $xmlValueDisplay($priv['privilege']); if (isset($priv['abstract']) && $priv['abstract']) { echo " <i>(abstract)</i>"; } if (isset($priv['description'])) { echo " " . $this->escapeHTML($priv['description']); } if (isset($priv['aggregates'])) { echo "\n<ul>\n"; foreach ($priv['aggregates'] as $subPriv) { $traverse($subPriv); } echo "</ul>"; } echo "</li>\n"; }; echo "<ul class=\"tree\">"; $traverse($value->getValue(), ''); echo "</ul>\n"; break; case 'string': echo $this->escapeHTML($value); break; case 'complex': echo '<em title="' . get_class($value) . '">complex</em>'; break; default: echo '<em>unknown</em>'; break; } return ob_get_clean(); }
/** * Updates a list of properties on the server * * The list of properties must have clark-notation properties for the keys, * and the actual (string) value for the value. If the value is null, an * attempt is made to delete the property. * * @param string $url * @param array $properties * @return void */ function propPatch($url, array $properties) { $dom = new \DOMDocument('1.0', 'UTF-8'); $dom->formatOutput = true; $root = $dom->createElementNS('DAV:', 'd:propertyupdate'); foreach ($properties as $propName => $propValue) { list($namespace, $elementName) = XMLUtil::parseClarkNotation($propName); if ($propValue === null) { $remove = $dom->createElement('d:remove'); $prop = $dom->createElement('d:prop'); if ($namespace === 'DAV:') { $element = $dom->createElement('d:' . $elementName); } else { $element = $dom->createElementNS($namespace, 'x:' . $elementName); } $root->appendChild($remove)->appendChild($prop)->appendChild($element); } else { $set = $dom->createElement('d:set'); $prop = $dom->createElement('d:prop'); if ($namespace === 'DAV:') { $element = $dom->createElement('d:' . $elementName); } else { $element = $dom->createElementNS($namespace, 'x:' . $elementName); } if ($propValue instanceof Property) { $propValue->serialize(new Server(), $element); } else { $element->nodeValue = htmlspecialchars($propValue, ENT_NOQUOTES, 'UTF-8'); } $root->appendChild($set)->appendChild($prop)->appendChild($element); } } $dom->appendChild($root); $body = $dom->saveXML(); $url = $this->getAbsoluteUrl($url); $request = new HTTP\Request('PROPPATCH', $url, ['Content-Type' => 'application/xml'], $body); $this->send($request); }
/** * Executes a REPORT request to calDAV server * * @param $url * @param array $properties * @param int $depth * * @return array * @throws Exception * @throws \Sabre\HTTP\ClientException * @throws \Sabre\HTTP\ClientHttpException */ public function propReport($url, array $properties, $depth = 0) { //create dom $dom = new \DOMDocument('1.0', 'UTF-8'); $dom->formatOutput = true; $root = $dom->createElementNS('urn:ietf:params:xml:ns:caldav', 'c:calendar-query'); $root->setAttributeNS('http://www.w3.org/2000/xmlns/', 'xmlns:d', 'DAV:'); $prop = $dom->createElement('d:prop'); $filter = $dom->createElement('c:filter'); $dat = $dom->createElement('c:comp-filter'); $dat->setAttribute('name', 'VCALENDAR'); $filter->appendChild($dat); foreach ($properties as $property) { list($namespace, $elementName) = XMLUtil::parseClarkNotation($property); if ($namespace === 'DAV:') { $element = $dom->createElement('d:' . $elementName); } else { $element = $dom->createElement('c:' . $elementName); } $prop->appendChild($element); } $bla = $dom->appendChild($root); $bla->appendChild($prop); $bla->appendChild($filter); $body = $dom->saveXML(); $url = $this->getAbsoluteUrl($url); $request = new Request('REPORT', $url, ['Depth' => $depth, 'Content-Type' => 'application/xml'], $body); $response = $this->send($request); if ((int) $response->getStatus() >= 400) { throw new Exception('HTTP error: ' . $response->getStatus()); } $result = $this->parseMultiStatus($response->getBodyAsString()); // If depth was 0, we only return the top item if ($depth === 0) { reset($result); $result = current($result); return isset($result[200]) ? $result[200] : []; } $newResult = []; foreach ($result as $href => $statusList) { $newResult[$href] = isset($statusList[200]) ? $statusList[200] : []; } return $newResult; }