public function toHTML($asSimpleXML=false) { $html = new SimpleXMLElement('<table/>'); /* // Title $tr = $html->addChild('tr'); $tr->addAttribute('class', 'title'); $tr->addChild('th', Zotero_ItemFields::getLocalizedString(false, 'title')); $tr->addChild('td', htmlspecialchars($item->getDisplayTitle(true))); */ // Item type Zotero_Atom::addHTMLRow( $html, "itemType", Zotero_ItemFields::getLocalizedString(false, 'itemType'), Zotero_ItemTypes::getLocalizedString($this->itemTypeID) ); // Creators $creators = $this->getCreators(); if ($creators) { $displayText = ''; foreach ($creators as $creator) { // Two fields if ($creator['ref']->fieldMode == 0) { $displayText = $creator['ref']->firstName . ' ' . $creator['ref']->lastName; } // Single field else if ($creator['ref']->fieldMode == 1) { $displayText = $creator['ref']->lastName; } else { // TODO } Zotero_Atom::addHTMLRow( $html, "creator", Zotero_CreatorTypes::getLocalizedString($creator['creatorTypeID']), trim($displayText) ); } } $primaryFields = array(); $fields = array_merge($primaryFields, $this->getUsedFields()); foreach ($fields as $field) { if (Zotero_Items::isPrimaryField($field)) { $fieldName = $field; } else { $fieldName = Zotero_ItemFields::getName($field); } // Skip certain fields switch ($fieldName) { case '': case 'userID': case 'libraryID': case 'key': case 'itemTypeID': case 'itemID': case 'title': case 'serverDateModified': case 'version': continue 2; } if (Zotero_ItemFields::isFieldOfBase($fieldName, 'title')) { continue; } $localizedFieldName = Zotero_ItemFields::getLocalizedString(false, $field); $value = $this->getField($field); $value = trim($value); // Skip empty fields if (!$value) { continue; } $fieldText = ''; // Shorten long URLs manually until Firefox wraps at ? // (like Safari) or supports the CSS3 word-wrap property if (false && preg_match("'https?://'", $value)) { $fieldText = $value; $firstSpace = strpos($value, ' '); // Break up long uninterrupted string if (($firstSpace === false && strlen($value) > 29) || $firstSpace > 29) { $stripped = false; /* // Strip query string for sites we know don't need it for each(var re in _noQueryStringSites) { if (re.test($field)){ var pos = $field.indexOf('?'); if (pos != -1) { fieldText = $field.substr(0, pos); stripped = true; } break; } } */ if (!$stripped) { // Add a line-break after the ? of long URLs //$fieldText = str_replace($field.replace('?', "?<ZOTEROBREAK/>"); // Strip query string variables from the end while the // query string is longer than the main part $pos = strpos($fieldText, '?'); if ($pos !== false) { while ($pos < (strlen($fieldText) / 2)) { $lastAmp = strrpos($fieldText, '&'); if ($lastAmp === false) { break; } $fieldText = substr($fieldText, 0, $lastAmp); $shortened = true; } // Append '&...' to the end if ($shortened) { $fieldText .= "&…"; } } } } if ($field == 'url') { $linkContainer = new SimpleXMLElement("<container/>"); $linkContainer->a = $value; $linkContainer->a['href'] = $fieldText; } } // Remove SQL date from multipart dates // (e.g. '2006-00-00 Summer 2006' becomes 'Summer 2006') else if ($fieldName == 'date') { $fieldText = $value; } // Convert dates to local format else if ($fieldName == 'accessDate' || $fieldName == 'dateAdded' || $fieldName == 'dateModified') { //$date = Zotero.Date.sqlToDate($field, true) $date = $value; //fieldText = escapeXML(date.toLocaleString()); $fieldText = $date; } else { $fieldText = $value; } if (isset($linkContainer)) { $tr = Zotero_Atom::addHTMLRow($html, $fieldName, $localizedFieldName, "", true); $tdNode = dom_import_simplexml($tr->td); $linkNode = dom_import_simplexml($linkContainer->a); $importedNode = $tdNode->ownerDocument->importNode($linkNode, true); $tdNode->appendChild($importedNode); unset($linkContainer); } else { Zotero_Atom::addHTMLRow($html, $fieldName, $localizedFieldName, $fieldText); } } if ($this->isNote() || $this->isAttachment()) { $note = $this->getNote(true); if ($note) { $tr = Zotero_Atom::addHTMLRow($html, "note", "Note", "", true); try { $noteXML = @new SimpleXMLElement("<td>" . $note . "</td>"); $trNode = dom_import_simplexml($tr); $tdNode = $trNode->getElementsByTagName("td")->item(0); $noteNode = dom_import_simplexml($noteXML); $importedNode = $trNode->ownerDocument->importNode($noteNode, true); $trNode->replaceChild($importedNode, $tdNode); unset($noteXML); } catch (Exception $e) { // Store non-HTML notes as <pre> $tr->td->pre = $note; } } } if ($this->isAttachment()) { Zotero_Atom::addHTMLRow($html, "linkMode", "Link Mode", $this->attachmentLinkMode); Zotero_Atom::addHTMLRow($html, "mimeType", "MIME Type", $this->attachmentMIMEType); Zotero_Atom::addHTMLRow($html, "charset", "Character Set", $this->attachmentCharset); // TODO: get from a constant /*if ($this->attachmentLinkMode != 3) { $doc->addField('path', $this->attachmentPath); }*/ } if ($this->getDeleted()) { Zotero_Atom::addHTMLRow($html, "deleted", "Deleted", "Yes"); } if ($asSimpleXML) { return $html; } return str_replace('<?xml version="1.0"?>', '', $html->asXML()); }
public static function multiResponse($options, $overrideFormat = false) { $format = $overrideFormat ? $overrideFormat : $options['requestParams']['format']; if (empty($options['results'])) { $options['results'] = ['results' => [], 'total' => 0]; } if ($options['results'] && isset($options['results']['results'])) { $totalResults = $options['results']['total']; $options['results'] = $options['results']['results']; if ($options['requestParams']['v'] >= 3) { header("Total-Results: {$totalResults}"); } } switch ($format) { case 'atom': case 'csljson': case 'json': case 'keys': case 'versions': $link = Zotero_API::buildLinkHeader($options['action'], $options['uri'], $totalResults, $options['requestParams']); if ($link) { header($link); } break; } if (!empty($options['head'])) { return; } switch ($format) { case 'atom': $t = microtime(true); $response = Zotero_Atom::createAtomFeed($options['action'], $options['title'], $options['uri'], $options['results'], $totalResults, $options['requestParams'], $options['permissions'], isset($options['fixedValues']) ? $options['fixedValues'] : null); StatsD::timing("api." . $options['action'] . ".multiple.createAtomFeed." . implode("-", $options['requestParams']['content']), (microtime(true) - $t) * 1000); return $response; case 'csljson': $json = Zotero_Cite::getJSONFromItems($options['results'], true); echo Zotero_Utilities::formatJSON($json); break; case 'json': echo Zotero_API::createJSONResponse($options['results'], $options['requestParams'], $options['permissions']); break; case 'keys': echo implode("\n", $options['results']) . "\n"; break; case 'versions': if (!empty($options['results'])) { echo Zotero_Utilities::formatJSON($options['results']); } else { echo Zotero_Utilities::formatJSON(new stdClass()); } break; case 'writereport': echo Zotero_Utilities::formatJSON($options['results']); break; default: throw new Exception("Unexpected format '" . $options['requestParams']['format'] . "'"); } }
public function groupUsers() { if (($this->method == 'POST' || $this->method == 'PUT') && !$this->body) { $this->e400("{$this->method} data not provided"); } // For now, only allow root and user access if (!$this->permissions->isSuper()) { $this->e403(); } $groupID = $this->scopeObjectID; $userID = $this->objectID; $group = Zotero_Groups::get($groupID); if (!$group) { $this->e404("Group {$groupID} does not exist"); } // Add multiple users to group if ($this->method == 'POST') { if ($userID) { $this->e400("POST requests cannot end with a userID (did you mean PUT?)"); } // Body can contain multiple <user> blocks, so stuff in root element try { $xml = @new SimpleXMLElement("<root>" . $this->body . "</root>"); } catch (Exception $e) { $this->e400("{$this->method} data is not valid XML"); } $addedUserIDs = array(); Zotero_DB::beginTransaction(); foreach ($xml->user as $user) { $id = (int) $user['id']; $role = (string) $user['role']; if (!$id) { $this->e400("User ID not provided in '" . $user->asXML() . "'"); } if (!$role) { $this->e400("Role not provided in '" . $user->asXML() . "'"); } try { $added = $group->addUser($id, $role); } catch (Exception $e) { if (strpos($e->getMessage(), "Invalid role") === 0) { $this->e400("Invalid role '{$role}' in " . $user->asXML() . "'"); } $this->e500($e->getMessage()); } if ($added) { $addedUserIDs[] = $id; } } // Response after adding $entries = array(); foreach ($addedUserIDs as $addedUserID) { $entries[] = $group->memberToAtom($addedUserID); } $title = "Users added to group '{$group->name}'"; $this->responseXML = Zotero_Atom::createAtomFeed($title, $this->uri, $entries, null, $this->queryParams, $this->apiVersion, $this->permissions); Zotero_DB::commit(); $this->end(); } // Add a single user to group if ($this->method == 'PUT') { if (!$userID) { $this->e400("PUT requests must end with a userID (did you mean POST?)"); } try { $user = @new SimpleXMLElement($this->body); } catch (Exception $e) { $this->e400("{$this->method} data is not valid XML"); } $id = (int) $user['id']; $role = (string) $user['role']; // User id is optional, but, if it's there, make sure it matches if ($id && $id != $userID) { $this->e400("User ID {$id} does not match user ID {$userID} from URI"); } if (!$role) { $this->e400("Role not provided in '{$this->body}'"); } Zotero_DB::beginTransaction(); $changedUserIDs = array(); try { if ($role == 'owner') { if ($userID != $group->ownerUserID) { $changedUserIDs[] = $group->ownerUserID; $group->ownerUserID = $userID; $group->save(); $changedUserIDs[] = $userID; } } else { if ($group->hasUser($userID)) { try { $updated = $group->updateUser($userID, $role); } catch (Exception $e) { switch ($e->getCode()) { case Z_ERROR_CANNOT_DELETE_GROUP_OWNER: $this->e400($e->getMessage()); default: $this->e500($e->getMessage()); } } if ($updated) { $changedUsersIDs[] = $userID; } } else { $added = $group->addUser($userID, $role); if ($added) { $changedUserIDs[] = $userID; } } } } catch (Exception $e) { if (strpos($e->getMessage(), "Invalid role") === 0) { $this->e400("Invalid role '{$role}' in '{$this->body}'"); } $this->e500($e->getMessage()); } // Response after adding $entries = array(); foreach ($changedUserIDs as $changedUserID) { $entries[] = $group->memberToAtom($changedUserID); } $title = "Users changed in group '{$group->name}'"; $this->responseXML = Zotero_Atom::createAtomFeed($title, $this->uri, $entries, null, $this->queryParams, $this->apiVersion, $this->permissions); Zotero_DB::commit(); $this->end(); } if ($this->method == 'DELETE') { if (!$userID) { $this->e400("DELETE requests must end with a userID"); } Zotero_DB::beginTransaction(); try { $group->removeUser($userID); } catch (Exception $e) { switch ($e->getCode()) { case Z_ERROR_CANNOT_DELETE_GROUP_OWNER: $this->e400($e->getMessage()); case Z_ERROR_USER_NOT_GROUP_MEMBER: $this->e404($e->getMessage()); default: $this->e500($e->getMessage()); } } Zotero_DB::commit(); header("HTTP/1.1 204 No Content"); exit; } // Single user if ($userID) { $this->responseXML = $group->memberToAtom($userID); $this->end(); } // Multiple users $title = "Members of '{$group->name}'"; $entries = array(); $memberIDs = array_merge(array($group->ownerUserID), $group->getAdmins(), $group->getMembers()); foreach ($memberIDs as $userID) { $entries[] = $group->memberToAtom($userID); } $totalResults = sizeOf($entries); $this->responseXML = Zotero_Atom::createAtomFeed($title, $this->uri, $entries, $totalResults, $this->queryParams, $this->apiVersion, $this->permissions); $this->end(); }
/** * Converts a Zotero_Tag object to a SimpleXMLElement Atom object * * @param object $tag Zotero_Tag object * @param string $content * @return SimpleXMLElement Tag data as SimpleXML element */ public function toAtom($content = array('none'), $apiVersion = null, $fixedValues = null) { // TEMP: multi-format support $content = $content[0]; $xml = new SimpleXMLElement('<entry xmlns="' . Zotero_Atom::$nsAtom . '" ' . 'xmlns:zapi="' . Zotero_Atom::$nsZoteroAPI . '" ' . 'xmlns:zxfer="' . Zotero_Atom::$nsZoteroTransfer . '"/>'); $xml->title = $this->name; $author = $xml->addChild('author'); $author->name = Zotero_Libraries::getName($this->libraryID); $author->uri = Zotero_URI::getLibraryURI($this->libraryID); $xml->id = Zotero_URI::getTagURI($this); $xml->published = Zotero_Date::sqlToISO8601($this->dateAdded); $xml->updated = Zotero_Date::sqlToISO8601($this->dateModified); $link = $xml->addChild("link"); $link['rel'] = "self"; $link['type'] = "application/atom+xml"; $link['href'] = Zotero_Atom::getTagURI($this); $link = $xml->addChild('link'); $link['rel'] = 'alternate'; $link['type'] = 'text/html'; $link['href'] = Zotero_URI::getTagURI($this); // Count user's linked items if (isset($fixedValues['numItems'])) { $numItems = $fixedValues['numItems']; } else { $itemIDs = $this->getLinkedItems(); $numItems = sizeOf($itemIDs); } $xml->addChild('zapi:numItems', $numItems, Zotero_Atom::$nsZoteroAPI); if ($content == 'html') { $xml->content['type'] = 'xhtml'; //$fullXML = Zotero_Tags::convertTagToXML($tag); $fullStr = "<div/>"; $fullXML = new SimpleXMLElement($fullStr); $fullXML->addAttribute("xmlns", Zotero_Atom::$nsXHTML); $fNode = dom_import_simplexml($xml->content); $subNode = dom_import_simplexml($fullXML); $importedNode = $fNode->ownerDocument->importNode($subNode, true); $fNode->appendChild($importedNode); //$arr = $tag->serialize(); //require_once("views/zotero/tags.php") } else { if ($content == 'full') { $xml->content['type'] = 'application/xml'; $fullXML = $this->toXML(); $fullXML->addAttribute("xmlns", Zotero_Atom::$nsZoteroTransfer); $fNode = dom_import_simplexml($xml->content); $subNode = dom_import_simplexml($fullXML); $importedNode = $fNode->ownerDocument->importNode($subNode, true); $fNode->appendChild($importedNode); } } return $xml; }
/** * Converts group to a SimpleXMLElement item * * @return SimpleXMLElement Group data as SimpleXML element */ public function toHTML() { if (($this->id || $this->libraryID) && !$this->loaded) { $this->load(); } $html = new SimpleXMLElement("<table/>"); $tr = Zotero_Atom::addHTMLRow($html, 'owner', "Owner", "", true); $tr->td->a = Zotero_Users::getUsername($this->ownerUserID); $tr->td->a['href'] = Zotero_URI::getUserURI($this->ownerUserID); Zotero_Atom::addHTMLRow($html, '', "Type", preg_replace('/([a-z])([A-Z])/', '$1 $2', $this->type)); Zotero_Atom::addHTMLRow($html, '', "Description", $this->description); Zotero_Atom::addHTMLRow($html, '', "URL", $this->url); Zotero_Atom::addHTMLRow($html, '', "Library Reading", ucwords($this->libraryReading)); Zotero_Atom::addHTMLRow($html, '', "Library Editing", ucwords($this->libraryEditing)); Zotero_Atom::addHTMLRow($html, '', "File Editing", ucwords($this->fileEditing)); $admins = $this->getAdmins(); if ($admins) { $tr = Zotero_Atom::addHTMLRow($html, '', "Admins", '', true); $ul = $tr->td->addChild('ul'); foreach ($admins as $admin) { $li = $ul->addChild('li'); $li->a = Zotero_Users::getUsername($admin); $li->a['href'] = Zotero_URI::getUserURI($admin); } } return $html; }
/** * Converts a Zotero_Item object to a SimpleXMLElement Atom object * * @param object $item Zotero_Item object * @param string $content * @return SimpleXMLElement Item data as SimpleXML element */ public static function convertItemToAtom(Zotero_Item $item, $queryParams, $apiVersion = null, $permissions = null, $sharedData = null) { $content = $queryParams['content']; $contentIsHTML = sizeOf($content) == 1 && $content[0] == 'html'; $contentParamString = urlencode(implode(',', $content)); $style = $queryParams['style']; $entry = '<entry xmlns="' . Zotero_Atom::$nsAtom . '" xmlns:zapi="' . Zotero_Atom::$nsZoteroAPI . '"/>'; $xml = new SimpleXMLElement($entry); $title = $item->getDisplayTitle(true); $title = $title ? $title : '[Untitled]'; $xml->title = $title; $author = $xml->addChild('author'); $createdByUserID = null; switch (Zotero_Libraries::getType($item->libraryID)) { case 'group': $createdByUserID = $item->createdByUserID; break; } if ($createdByUserID) { $author->name = Zotero_Users::getUsername($createdByUserID); $author->uri = Zotero_URI::getUserURI($createdByUserID); } else { $author->name = Zotero_Libraries::getName($item->libraryID); $author->uri = Zotero_URI::getLibraryURI($item->libraryID); } $id = Zotero_URI::getItemURI($item); /*if (!$contentIsHTML) { $id .= "?content=$content"; }*/ $xml->id = $id; $xml->published = Zotero_Date::sqlToISO8601($item->getField('dateAdded')); $xml->updated = Zotero_Date::sqlToISO8601($item->getField('dateModified')); $link = $xml->addChild("link"); $link['rel'] = "self"; $link['type'] = "application/atom+xml"; $href = Zotero_Atom::getItemURI($item); if (!$contentIsHTML) { $href .= "?content={$contentParamString}"; } $link['href'] = $href; $parent = $item->getSource(); if ($parent) { // TODO: handle group items? $parentItem = Zotero_Items::get($item->libraryID, $parent); $link = $xml->addChild("link"); $link['rel'] = "up"; $link['type'] = "application/atom+xml"; $href = Zotero_Atom::getItemURI($parentItem); if (!$contentIsHTML) { $href .= "?content={$contentParamString}"; } $link['href'] = $href; } $link = $xml->addChild('link'); $link['rel'] = 'alternate'; $link['type'] = 'text/html'; $link['href'] = Zotero_URI::getItemURI($item); // If appropriate permissions and the file is stored in ZFS, get file request link if ($permissions && $permissions->canAccess($item->libraryID, 'files')) { $details = Zotero_S3::getDownloadDetails($item); if ($details) { $link = $xml->addChild('link'); $link['rel'] = 'enclosure'; $type = $item->attachmentMIMEType; if ($type) { $link['type'] = $type; } $link['href'] = $details['url']; if (!empty($details['filename'])) { $link['title'] = $details['filename']; } if (!empty($details['size'])) { $link['length'] = $details['size']; } } } $xml->addChild('zapi:key', $item->key, Zotero_Atom::$nsZoteroAPI); $xml->addChild('zapi:itemType', Zotero_ItemTypes::getName($item->itemTypeID), Zotero_Atom::$nsZoteroAPI); if ($item->isRegularItem()) { $val = $item->creatorSummary; if ($val !== '') { $xml->addChild('zapi:creatorSummary', htmlspecialchars($val), Zotero_Atom::$nsZoteroAPI); } $val = substr($item->getField('date', true, true, true), 0, 4); if ($val !== '' && $val !== '0000') { $xml->addChild('zapi:year', $val, Zotero_Atom::$nsZoteroAPI); } } if (!$parent && $item->isRegularItem()) { if ($permissions && !$permissions->canAccess($item->libraryID, 'notes')) { $numChildren = $item->numAttachments(); } else { $numChildren = $item->numChildren(); } $xml->addChild('zapi:numChildren', $numChildren, Zotero_Atom::$nsZoteroAPI); } $xml->addChild('zapi:numTags', $item->numTags(), Zotero_Atom::$nsZoteroAPI); $xml->content = ''; // // DOM XML from here on out // $contentNode = dom_import_simplexml($xml->content); $domDoc = $contentNode->ownerDocument; $multiFormat = sizeOf($content) > 1; // Create a root XML document for multi-format responses if ($multiFormat) { $contentNode->setAttribute('type', 'application/xml'); /*$multicontent = $domDoc->createElementNS( Zotero_Atom::$nsZoteroAPI, 'multicontent' ); $contentNode->appendChild($multicontent);*/ } foreach ($content as $type) { // Set the target to either the main <content> // or a <multicontent> <content> if (!$multiFormat) { $target = $contentNode; } else { $target = $domDoc->createElementNS(Zotero_Atom::$nsZoteroAPI, 'subcontent'); $contentNode->appendChild($target); } $target->setAttributeNS(Zotero_Atom::$nsZoteroAPI, "zapi:type", $type); if ($type == 'html') { if (!$multiFormat) { $target->setAttribute('type', 'xhtml'); } $div = $domDoc->createElement('div'); $div->setAttribute('xmlns', Zotero_Atom::$nsXHTML); $target->appendChild($div); $html = $item->toHTML(true); $subNode = dom_import_simplexml($html); $importedNode = $domDoc->importNode($subNode, true); $div->appendChild($importedNode); } else { if ($type == 'citation') { if (!$multiFormat) { $target->setAttribute('type', 'xhtml'); } if (isset($sharedData[$type][$item->libraryID . "/" . $item->key])) { $html = $sharedData[$type][$item->libraryID . "/" . $item->key]; } else { if ($sharedData !== null) { error_log("Citation not found in sharedData -- retrieving individually"); } $html = Zotero_Cite::getCitationFromCiteServer($item, $style); } $html = new SimpleXMLElement($html); $html['xmlns'] = Zotero_Atom::$nsXHTML; $subNode = dom_import_simplexml($html); $importedNode = $domDoc->importNode($subNode, true); $target->appendChild($importedNode); } else { if ($type == 'bib') { if (!$multiFormat) { $target->setAttribute('type', 'xhtml'); } if (isset($sharedData[$type][$item->libraryID . "/" . $item->key])) { $html = $sharedData[$type][$item->libraryID . "/" . $item->key]; } else { if ($sharedData !== null) { error_log("Bibliography not found in sharedData -- retrieving individually"); } $html = Zotero_Cite::getBibliographyFromCitationServer(array($item), $style); } $html = new SimpleXMLElement($html); $html['xmlns'] = Zotero_Atom::$nsXHTML; $subNode = dom_import_simplexml($html); $importedNode = $domDoc->importNode($subNode, true); $target->appendChild($importedNode); } else { if ($type == 'json') { $target->setAttributeNS(Zotero_Atom::$nsZoteroAPI, "zapi:etag", $item->etag); $textNode = $domDoc->createTextNode($item->toJSON(false, $queryParams['pprint'], true)); $target->appendChild($textNode); } else { if ($type == 'csljson') { $arr = $item->toCSLItem(); $mask = JSON_HEX_TAG | JSON_HEX_AMP; if ($queryParams['pprint']) { $json = Zotero_Utilities::json_encode_pretty($arr, $mask); } else { $json = json_encode($arr, $mask); } // Until JSON_UNESCAPED_SLASHES is available $json = str_replace('\\/', '/', $json); $textNode = $domDoc->createTextNode($json); $target->appendChild($textNode); } else { if ($type == 'full') { if (!$multiFormat) { $target->setAttribute('type', 'xhtml'); } $fullXML = Zotero_Items::convertItemToXML($item, array(), $apiVersion); $fullXML->addAttribute("xmlns", Zotero_Atom::$nsZoteroTransfer); $subNode = dom_import_simplexml($fullXML); $importedNode = $domDoc->importNode($subNode, true); $target->appendChild($importedNode); } else { if (in_array($type, Zotero_Translate::$exportFormats)) { $export = Zotero_Translate::doExport(array($item), $type); $target->setAttribute('type', $export['mimeType']); // Insert XML into document if (preg_match('/\\+xml$/', $export['mimeType'])) { // Strip prolog $body = preg_replace('/^<\\?xml.+\\n/', "", $export['body']); $subNode = $domDoc->createDocumentFragment(); $subNode->appendXML($body); $target->appendChild($subNode); } else { $textNode = $domDoc->createTextNode($export['body']); $target->appendChild($textNode); } } } } } } } } } return $xml; }
public function itemToAtom($itemID, $apiVersion = null) { if (!is_int($itemID)) { throw new Exception("itemID must be an integer (was " . gettype($itemID) . ")"); } if (!$this->loaded) { $this->load(); } //$groupUserData = $this->getUserData($itemID); $item = Zotero_Items::get($this->libraryID, $itemID); if (!$item) { throw new Exception("Item {$itemID} doesn't exist"); } $xml = new SimpleXMLElement('<entry xmlns="' . Zotero_Atom::$nsAtom . '" ' . 'xmlns:zapi="' . Zotero_Atom::$nsZoteroAPI . '" ' . 'xmlns:xfer="' . Zotero_Atom::$nsZoteroTransfer . '"/>'); $title = $item->getDisplayTitle(true); $title = $title ? $title : '[Untitled]'; // Strip HTML from note titles if ($item->isNote()) { // Clean and strip HTML, giving us an HTML-encoded plaintext string $title = strip_tags($GLOBALS['HTMLPurifier']->purify($title)); // Unencode plaintext string $title = html_entity_decode($title); } $xml->title = $title; $author = $xml->addChild('author'); $author->name = Zotero_Libraries::getName($item->libraryID); $author->uri = Zotero_URI::getLibraryURI($item->libraryID); $xml->id = Zotero_URI::getItemURI($item); $xml->published = Zotero_Date::sqlToISO8601($item->dateAdded); $xml->updated = Zotero_Date::sqlToISO8601($item->dateModified); $link = $xml->addChild("link"); $link['rel'] = "self"; $link['type'] = "application/atom+xml"; $link['href'] = Zotero_Atom::getItemURI($item); $link = $xml->addChild('link'); $link['rel'] = 'alternate'; $link['type'] = 'text/html'; $link['href'] = Zotero_URI::getItemURI($item); $xml->content['type'] = 'application/xml'; $itemXML = new SimpleXMLElement('<item xmlns="' . Zotero_Atom::$nsZoteroTransfer . '"/>'); // This method of adding the element seems to be necessary to get the // namespace prefix to show up $fNode = dom_import_simplexml($xml->content); $subNode = dom_import_simplexml($itemXML); $importedNode = $fNode->ownerDocument->importNode($subNode, true); $fNode->appendChild($importedNode); $xml->content->item['id'] = $itemID; return $xml; }
/** * Converts a Zotero_Collection object to a SimpleXMLElement Atom object * * @param object $item Zotero_Collection object * @param string $content * @return SimpleXMLElement Collection data as SimpleXML element */ public static function convertCollectionToAtom(Zotero_Collection $collection, $content = array('none')) { // TEMP: multi-format support $content = $content[0]; $xml = new SimpleXMLElement('<entry xmlns="' . Zotero_Atom::$nsAtom . '" xmlns:zapi="' . Zotero_Atom::$nsZoteroAPI . '"/>'); $title = $collection->name ? $collection->name : '[Untitled]'; $xml->title = $title; $author = $xml->addChild('author'); // TODO: group item creator $author->name = Zotero_Libraries::getName($collection->libraryID); $author->uri = Zotero_URI::getLibraryURI($collection->libraryID); $xml->id = Zotero_URI::getCollectionURI($collection); $xml->published = Zotero_Date::sqlToISO8601($collection->dateAdded); $xml->updated = Zotero_Date::sqlToISO8601($collection->dateModified); $link = $xml->addChild("link"); $link['rel'] = "self"; $link['type'] = "application/atom+xml"; $link['href'] = Zotero_Atom::getCollectionURI($collection); $parent = $collection->parent; if ($parent) { $parentCol = self::get($collection->libraryID, $parent); $link = $xml->addChild("link"); $link['rel'] = "up"; $link['type'] = "application/atom+xml"; $link['href'] = Zotero_Atom::getCollectionURI($parentCol); } $link = $xml->addChild('link'); $link['rel'] = 'alternate'; $link['type'] = 'text/html'; $link['href'] = Zotero_URI::getCollectionURI($collection); $xml->addChild('zapi:key', $collection->key, Zotero_Atom::$nsZoteroAPI); $collections = $collection->getChildCollections(); $xml->addChild('zapi:numCollections', sizeOf($collections), Zotero_Atom::$nsZoteroAPI); $xml->addChild('zapi:numItems', $collection->numItems(), Zotero_Atom::$nsZoteroAPI); if ($content == 'json') { $xml->content['type'] = 'application/json'; $xml->content->addAttribute('zapi:etag', $collection->etag, Zotero_Atom::$nsZoteroAPI); // TODO: remove non-namespaced attribute $xml->content['etag'] = $collection->etag; $xml->content = $collection->toJSON(); } else { if ($content == 'full') { $xml->content['type'] = 'application/xml'; $fullXML = Zotero_Collections::convertCollectionToXML($collection); $fullXML->addAttribute("xmlns", Zotero_Atom::$nsZoteroTransfer); $fNode = dom_import_simplexml($xml->content); $subNode = dom_import_simplexml($fullXML); $importedNode = $fNode->ownerDocument->importNode($subNode, true); $fNode->appendChild($importedNode); } } return $xml; }
public static function createAtomFeed($title, $url, $entries, $totalResults = null, $queryParams = null, $apiVersion = null, $permissions = null, $fixedValues = array()) { if ($queryParams) { $nonDefaultParams = Zotero_API::getNonDefaultQueryParams($queryParams); // Convert 'content' array to sorted comma-separated string if (isset($nonDefaultParams['content'])) { $nonDefaultParams['content'] = implode(',', $nonDefaultParams['content']); } } else { $nonDefaultParams = array(); } $feed = '<feed xmlns="' . Zotero_Atom::$nsAtom . '" ' . 'xmlns:zapi="' . Zotero_Atom::$nsZoteroAPI . '"'; if ($queryParams && $queryParams['content'][0] == 'full') { $feed .= ' xmlns:zxfer="' . Zotero_Atom::$nsZoteroTransfer . '"'; } $feed .= '/>'; $xml = new SimpleXMLElement($feed); $xml->title = $title; $path = parse_url($url, PHP_URL_PATH); // Generate canonical URI $zoteroURI = Zotero_URI::getBaseURI() . substr($path, 1); if ($nonDefaultParams) { $zoteroURI .= "?" . http_build_query($nonDefaultParams); } $atomURI = Zotero_Atom::getBaseURI() . substr($path, 1); // // Generate URIs for 'self', 'first', 'next' and 'last' links // // 'self' $atomSelfURI = $atomURI; if ($nonDefaultParams) { $atomSelfURI .= "?" . http_build_query($nonDefaultParams); } // 'first' $atomFirstURI = $atomURI; if ($nonDefaultParams) { $p = $nonDefaultParams; unset($p['start']); if ($first = http_build_query($p)) { $atomFirstURI .= "?" . $first; } } // 'last' if (!$queryParams['start'] && $queryParams['limit'] >= $totalResults) { $atomLastURI = $atomSelfURI; } else { // 'start' past results if ($queryParams['start'] >= $totalResults) { $lastStart = $totalResults - $queryParams['limit']; } else { $lastStart = $totalResults - $totalResults % $queryParams['limit']; if ($lastStart == $totalResults) { $lastStart = $totalResults - $queryParams['limit']; } } $p = $nonDefaultParams; if ($lastStart > 0) { $p['start'] = $lastStart; } else { unset($p['start']); } $atomLastURI = $atomURI; if ($last = http_build_query($p)) { $atomLastURI .= "?" . $last; } // 'next' $nextStart = $queryParams['start'] + $queryParams['limit']; if ($nextStart < $totalResults) { $p = $nonDefaultParams; $p['start'] = $nextStart; $atomNextURI = $atomURI . "?" . http_build_query($p); } } $xml->id = $zoteroURI; $link = $xml->addChild("link"); $link['rel'] = "self"; $link['type'] = "application/atom+xml"; $link['href'] = $atomSelfURI; $link = $xml->addChild("link"); $link['rel'] = "first"; $link['type'] = "application/atom+xml"; $link['href'] = $atomFirstURI; if (isset($atomNextURI)) { $link = $xml->addChild("link"); $link['rel'] = "next"; $link['type'] = "application/atom+xml"; $link['href'] = $atomNextURI; } $link = $xml->addChild("link"); $link['rel'] = "last"; $link['type'] = "application/atom+xml"; $link['href'] = $atomLastURI; // Generate alternate URI $alternateURI = Zotero_URI::getBaseURI() . substr($path, 1); if ($nonDefaultParams) { $p = $nonDefaultParams; if (isset($p['content'])) { unset($p['content']); } if ($p) { $alternateURI .= "?" . http_build_query($p); } } $link = $xml->addChild("link"); $link['rel'] = "alternate"; $link['type'] = "text/html"; $link['href'] = $alternateURI; $xml->addChild("zapi:totalResults", is_numeric($totalResults) ? $totalResults : sizeOf($entries), self::$nsZoteroAPI); $xml->addChild("zapi:apiVersion", $apiVersion, self::$nsZoteroAPI); $latestUpdated = ''; // Get bib data using parallel requests $sharedData = array(); if ($entries && $entries[0] instanceof Zotero_Item) { if (in_array('citation', $queryParams['content'])) { $sharedData["citation"] = Zotero_Cite::multiGetFromCiteServer("citation", $entries, $queryParams['style']); } if (in_array('bib', $queryParams['content'])) { $sharedData["bib"] = Zotero_Cite::multiGetFromCiteServer("bib", $entries, $queryParams['style']); } } $xmlEntries = array(); foreach ($entries as $entry) { if ($entry->dateModified > $latestUpdated) { $latestUpdated = $entry->dateModified; } if ($entry instanceof SimpleXMLElement) { $xmlEntries[] = $entry; } else { if ($entry instanceof Zotero_Collection) { $entry = Zotero_Collections::convertCollectionToAtom($entry, $queryParams['content'], $apiVersion); $xmlEntries[] = $entry; } else { if ($entry instanceof Zotero_Creator) { $entry = Zotero_Creators::convertCreatorToAtom($entry, $queryParams['content'], $apiVersion); $xmlEntries[] = $entry; } else { if ($entry instanceof Zotero_Item) { $entry = Zotero_Items::convertItemToAtom($entry, $queryParams, $apiVersion, $permissions, $sharedData); $xmlEntries[] = $entry; } else { if ($entry instanceof Zotero_Search) { $entry = Zotero_Searches::convertSearchToAtom($entry, $queryParams['content'], $apiVersion); $xmlEntries[] = $entry; } else { if ($entry instanceof Zotero_Tag) { $xmlEntries[] = $entry->toAtom($queryParams['content'], $apiVersion, isset($fixedValues[$entry->id]) ? $fixedValues[$entry->id] : null); } else { if ($entry instanceof Zotero_Group) { $entry = $entry->toAtom($queryParams['content'], $apiVersion); $xmlEntries[] = $entry; } } } } } } } } if ($latestUpdated) { $xml->updated = Zotero_Date::sqlToISO8601($latestUpdated); } else { $xml->updated = str_replace("+00:00", "Z", date('c')); } // Import object XML nodes into document $doc = dom_import_simplexml($xml); foreach ($xmlEntries as $xmlEntry) { $subNode = dom_import_simplexml($xmlEntry); $importedNode = $doc->ownerDocument->importNode($subNode, true); $doc->appendChild($importedNode); } return $xml; }