Skip to content

Commit

Permalink
Add support for passing remote style URLs in 'style' param
Browse files Browse the repository at this point in the history
Closes #24
  • Loading branch information
dstillman authored and uniuuu committed May 7, 2023
1 parent 08defec commit e33023d
Show file tree
Hide file tree
Showing 2 changed files with 57 additions and 24 deletions.
14 changes: 9 additions & 5 deletions model/Cite.inc.php
Original file line number Diff line number Diff line change
Expand Up @@ -402,7 +402,7 @@ private static function buildURLPath(array $queryParams, $mode) {
foreach ($queryParams as $param => $value) {
switch ($param) {
case 'style':
if (!is_string($value) || !preg_match('/^[a-zA-Z0-9\-]+$/', $value)) {
if (!is_string($value) || !preg_match('/^(https?|[a-zA-Z0-9\-]+$)/', $value)) {
throw new Exception("Invalid style", Z_ERROR_CITESERVER_INVALID_STYLE);
}
$url .= "&" . $param . "=" . urlencode($value);
Expand Down Expand Up @@ -447,13 +447,17 @@ private static function makeRequest(array $queryParams, $mode, $json) {

$code = curl_getinfo($ch, CURLINFO_HTTP_CODE);

if ($code != 200) {
error_log($code . " from citation server -- trying another "
. "[URL: '$url'] [INPUT: '$json'] [RESPONSE: '$response']");
if ($code == 400) {
throw new Exception("Invalid style", Z_ERROR_CITESERVER_INVALID_STYLE);
}

if ($code == 404) {
throw new Exception("Invalid style", Z_ERROR_CITESERVER_INVALID_STYLE);
throw new Exception("Style not found", Z_ERROR_CITESERVER_INVALID_STYLE);
}

if ($code != 200) {
error_log($code . " from citation server -- trying another "
. "[URL: '$url'] [INPUT: '$json'] [RESPONSE: '$response']");
}

// If no response, try another server
Expand Down
67 changes: 48 additions & 19 deletions tests/remote/tests/API/3/BibTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,12 @@
class BibTests extends APITests {
private static $items;
private static $multiResponses = [];
private static $styles = array("default", "apa");
private static $styles = [
"default",
"apa",
"https://www.zotero.org/styles/apa",
"https://raw.githubusercontent.com/citation-style-language/styles/master/ieee.csl"
];

public static function setUpBeforeClass() {
parent::setUpBeforeClass();
Expand All @@ -54,21 +59,29 @@ public static function setUpBeforeClass() {
'json' => [
"citation" => array(
"default" => '<span>Last, <i>Title</i>.</span>',
"apa" => '<span>(Last, 2014)</span>'
"apa" => '<span>(Last, 2014)</span>',
"https://www.zotero.org/styles/apa" => '<span>(Last, 2014)</span>',
"https://raw.githubusercontent.com/citation-style-language/styles/master/ieee.csl" => '<span>[1]</span>'
),
"bib" => array(
"default" => '<div class="csl-bib-body" style="line-height: 1.35; padding-left: 2em; text-indent:-2em;"><div class="csl-entry">Last, First. <i>Title</i>, 2014.</div></div>',
"apa" => '<div class="csl-bib-body" style="line-height: 2; padding-left: 2em; text-indent:-2em;"><div class="csl-entry">Last, F. (2014). <i>Title</i>.</div></div>'
"apa" => '<div class="csl-bib-body" style="line-height: 2; padding-left: 2em; text-indent:-2em;"><div class="csl-entry">Last, F. (2014). <i>Title</i>.</div></div>',
"https://www.zotero.org/styles/apa" => '<div class="csl-bib-body" style="line-height: 2; padding-left: 2em; text-indent:-2em;"><div class="csl-entry">Last, F. (2014). <i>Title</i>.</div></div>',
"https://raw.githubusercontent.com/citation-style-language/styles/master/ieee.csl" => '<div class="csl-bib-body" style="line-height: 1.35; "><div class="csl-entry" style="clear: left; "><div class="csl-left-margin" style="float: left; padding-right: 0.5em; text-align: right; width: 1em;">[1]</div><div class="csl-right-inline" style="margin: 0 .4em 0 1.5em;">F. Last, <i>Title</i>. 2014.</div></div></div>'
)
],
'atom' => [
"citation" => array(
"default" => '<content xmlns:zapi="http://zotero.org/ns/api" zapi:type="citation" type="xhtml"><span xmlns="http://www.w3.org/1999/xhtml">Last, <i>Title</i>.</span></content>',
"apa" => '<content xmlns:zapi="http://zotero.org/ns/api" zapi:type="citation" type="xhtml"><span xmlns="http://www.w3.org/1999/xhtml">(Last, 2014)</span></content>'
"apa" => '<content xmlns:zapi="http://zotero.org/ns/api" zapi:type="citation" type="xhtml"><span xmlns="http://www.w3.org/1999/xhtml">(Last, 2014)</span></content>',
"https://www.zotero.org/styles/apa" => '<content xmlns:zapi="http://zotero.org/ns/api" zapi:type="citation" type="xhtml"><span xmlns="http://www.w3.org/1999/xhtml">(Last, 2014)</span></content>',
"https://raw.githubusercontent.com/citation-style-language/styles/master/ieee.csl" => '<content xmlns:zapi="http://zotero.org/ns/api" zapi:type="citation" type="xhtml"><span xmlns="http://www.w3.org/1999/xhtml">[1]</span></content>'
),
"bib" => array(
"default" => '<content xmlns:zapi="http://zotero.org/ns/api" zapi:type="bib" type="xhtml"><div xmlns="http://www.w3.org/1999/xhtml" class="csl-bib-body" style="line-height: 1.35; padding-left: 2em; text-indent:-2em;"><div class="csl-entry">Last, First. <i>Title</i>, 2014.</div></div></content>',
"apa" => '<content xmlns:zapi="http://zotero.org/ns/api" zapi:type="bib" type="xhtml"><div xmlns="http://www.w3.org/1999/xhtml" class="csl-bib-body" style="line-height: 2; padding-left: 2em; text-indent:-2em;"><div class="csl-entry">Last, F. (2014). <i>Title</i>.</div></div></content>'
"apa" => '<content xmlns:zapi="http://zotero.org/ns/api" zapi:type="bib" type="xhtml"><div xmlns="http://www.w3.org/1999/xhtml" class="csl-bib-body" style="line-height: 2; padding-left: 2em; text-indent:-2em;"><div class="csl-entry">Last, F. (2014). <i>Title</i>.</div></div></content>',
"https://www.zotero.org/styles/apa" => '<content xmlns:zapi="http://zotero.org/ns/api" zapi:type="bib" type="xhtml"><div xmlns="http://www.w3.org/1999/xhtml" class="csl-bib-body" style="line-height: 2; padding-left: 2em; text-indent:-2em;"><div class="csl-entry">Last, F. (2014). <i>Title</i>.</div></div></content>',
"https://raw.githubusercontent.com/citation-style-language/styles/master/ieee.csl" => '<content xmlns:zapi="http://zotero.org/ns/api" zapi:type="bib" type="xhtml"><div xmlns="http://www.w3.org/1999/xhtml" class="csl-bib-body" style="line-height: 1.35; "><div class="csl-entry" style="clear: left; "><div class="csl-left-margin" style="float: left; padding-right: 0.5em; text-align: right; width: 1em;">[1]</div><div class="csl-right-inline" style="margin: 0 .4em 0 1.5em;">F. Last, <i>Title</i>. 2014.</div></div></div></content>'
)
]
];
Expand All @@ -93,28 +106,38 @@ public static function setUpBeforeClass() {
'json' => [
"citation" => array(
"default" => '<span>Last, <i>Title 2</i>.</span>',
"apa" => '<span>(Last, 2014)</span>'
"apa" => '<span>(Last, 2014)</span>',
"https://www.zotero.org/styles/apa" => '<span>(Last, 2014)</span>',
"https://raw.githubusercontent.com/citation-style-language/styles/master/ieee.csl" => '<span>[1]</span>'
),
"bib" => array(
"default" => '<div class="csl-bib-body" style="line-height: 1.35; padding-left: 2em; text-indent:-2em;"><div class="csl-entry">Last, First. <i>Title 2</i>. Edited by Ed McEditor, 2014.</div></div>',
"apa" => '<div class="csl-bib-body" style="line-height: 2; padding-left: 2em; text-indent:-2em;"><div class="csl-entry">Last, F. (2014). <i>Title 2</i>. (E. McEditor, Ed.).</div></div>'
"apa" => '<div class="csl-bib-body" style="line-height: 2; padding-left: 2em; text-indent:-2em;"><div class="csl-entry">Last, F. (2014). <i>Title 2</i>. (E. McEditor, Ed.).</div></div>',
"https://www.zotero.org/styles/apa" => '<div class="csl-bib-body" style="line-height: 2; padding-left: 2em; text-indent:-2em;"><div class="csl-entry">Last, F. (2014). <i>Title 2</i>. (E. McEditor, Ed.).</div></div>',
"https://raw.githubusercontent.com/citation-style-language/styles/master/ieee.csl" => '<div class="csl-bib-body" style="line-height: 1.35; "><div class="csl-entry" style="clear: left; "><div class="csl-left-margin" style="float: left; padding-right: 0.5em; text-align: right; width: 1em;">[1]</div><div class="csl-right-inline" style="margin: 0 .4em 0 1.5em;">F. Last, <i>Title 2</i>. 2014.</div></div></div>'
)
],
'atom' => [
"citation" => array(
"default" => '<content xmlns:zapi="http://zotero.org/ns/api" zapi:type="citation" type="xhtml"><span xmlns="http://www.w3.org/1999/xhtml">Last, <i>Title 2</i>.</span></content>',
"apa" => '<content xmlns:zapi="http://zotero.org/ns/api" zapi:type="citation" type="xhtml"><span xmlns="http://www.w3.org/1999/xhtml">(Last, 2014)</span></content>'
"apa" => '<content xmlns:zapi="http://zotero.org/ns/api" zapi:type="citation" type="xhtml"><span xmlns="http://www.w3.org/1999/xhtml">(Last, 2014)</span></content>',
"https://www.zotero.org/styles/apa" => '<content xmlns:zapi="http://zotero.org/ns/api" zapi:type="citation" type="xhtml"><span xmlns="http://www.w3.org/1999/xhtml">(Last, 2014)</span></content>',
"https://raw.githubusercontent.com/citation-style-language/styles/master/ieee.csl" => '<content xmlns:zapi="http://zotero.org/ns/api" zapi:type="citation" type="xhtml"><span xmlns="http://www.w3.org/1999/xhtml">[1]</span></content>'
),
"bib" => array(
"default" => '<content xmlns:zapi="http://zotero.org/ns/api" zapi:type="bib" type="xhtml"><div xmlns="http://www.w3.org/1999/xhtml" class="csl-bib-body" style="line-height: 1.35; padding-left: 2em; text-indent:-2em;"><div class="csl-entry">Last, First. <i>Title 2</i>. Edited by Ed McEditor, 2014.</div></div></content>',
"apa" => '<content xmlns:zapi="http://zotero.org/ns/api" zapi:type="bib" type="xhtml"><div xmlns="http://www.w3.org/1999/xhtml" class="csl-bib-body" style="line-height: 2; padding-left: 2em; text-indent:-2em;"><div class="csl-entry">Last, F. (2014). <i>Title 2</i>. (E. McEditor, Ed.).</div></div></content>'
"apa" => '<content xmlns:zapi="http://zotero.org/ns/api" zapi:type="bib" type="xhtml"><div xmlns="http://www.w3.org/1999/xhtml" class="csl-bib-body" style="line-height: 2; padding-left: 2em; text-indent:-2em;"><div class="csl-entry">Last, F. (2014). <i>Title 2</i>. (E. McEditor, Ed.).</div></div></content>',
"https://www.zotero.org/styles/apa" => '<content xmlns:zapi="http://zotero.org/ns/api" zapi:type="bib" type="xhtml"><div xmlns="http://www.w3.org/1999/xhtml" class="csl-bib-body" style="line-height: 2; padding-left: 2em; text-indent:-2em;"><div class="csl-entry">Last, F. (2014). <i>Title 2</i>. (E. McEditor, Ed.).</div></div></content>',
"https://raw.githubusercontent.com/citation-style-language/styles/master/ieee.csl" => '<content xmlns:zapi="http://zotero.org/ns/api" zapi:type="bib" type="xhtml"><div xmlns="http://www.w3.org/1999/xhtml" class="csl-bib-body" style="line-height: 1.35; "><div class="csl-entry" style="clear: left; "><div class="csl-left-margin" style="float: left; padding-right: 0.5em; text-align: right; width: 1em;">[1]</div><div class="csl-right-inline" style="margin: 0 .4em 0 1.5em;">F. Last, <i>Title 2</i>. 2014.</div></div></div></content>'
)
]
];

self::$multiResponses = [
"default" => '<?xml version="1.0"?><div class="csl-bib-body" style="line-height: 1.35; padding-left: 2em; text-indent:-2em;"><div class="csl-entry">Last, First. <i>Title</i>, 2014.</div><div class="csl-entry">&#x2014;&#x2014;&#x2014;. <i>Title 2</i>. Edited by Ed McEditor, 2014.</div></div>',
"apa" => '<?xml version="1.0"?><div class="csl-bib-body" style="line-height: 2; padding-left: 2em; text-indent:-2em;"><div class="csl-entry">Last, F. (2014a). <i>Title</i>.</div><div class="csl-entry">Last, F. (2014b). <i>Title 2</i>. (E. McEditor, Ed.).</div></div>'
"apa" => '<?xml version="1.0"?><div class="csl-bib-body" style="line-height: 2; padding-left: 2em; text-indent:-2em;"><div class="csl-entry">Last, F. (2014a). <i>Title</i>.</div><div class="csl-entry">Last, F. (2014b). <i>Title 2</i>. (E. McEditor, Ed.).</div></div>',
"https://www.zotero.org/styles/apa" => '<?xml version="1.0"?><div class="csl-bib-body" style="line-height: 2; padding-left: 2em; text-indent:-2em;"><div class="csl-entry">Last, F. (2014a). <i>Title</i>.</div><div class="csl-entry">Last, F. (2014b). <i>Title 2</i>. (E. McEditor, Ed.).</div></div>',
"https://raw.githubusercontent.com/citation-style-language/styles/master/ieee.csl" => '<?xml version="1.0"?><div class="csl-bib-body" style="line-height: 1.35; "><div class="csl-entry" style="clear: left; "><div class="csl-left-margin" style="float: left; padding-right: 0.5em; text-align: right; width: 1em;">[1]</div><div class="csl-right-inline" style="margin: 0 .4em 0 1.5em;">F. Last, <i>Title 2</i>. 2014.</div></div><div class="csl-entry" style="clear: left; "><div class="csl-left-margin" style="float: left; padding-right: 0.5em; text-align: right; width: 1em;">[2]</div><div class="csl-right-inline" style="margin: 0 .4em 0 1.5em;">F. Last, <i>Title</i>. 2014.</div></div></div>'
];
}

Expand All @@ -130,7 +153,8 @@ public function testIncludeCitationSingle() {
foreach (self::$items as $key => $expected) {
$response = API::userGet(
self::$config['userID'],
"items/$key?include=citation" . ($style == "default" ? "" : "&style=$style")
"items/$key?include=citation"
. ($style == "default" ? "" : "&style=" . urlencode($style))
);
$this->assert200($response);
$json = API::getJSONFromResponse($response);
Expand All @@ -146,7 +170,8 @@ public function testContentCitationSingle() {
foreach (self::$items as $key => $expected) {
$response = API::userGet(
self::$config['userID'],
"items/$key?content=citation" . ($style == "default" ? "" : "&style=$style")
"items/$key?content=citation"
. ($style == "default" ? "" : "&style=" . urlencode($style))
);
$this->assert200($response);
$content = API::getContentFromResponse($response);
Expand All @@ -167,7 +192,7 @@ public function testIncludeCitationMulti() {
$response = API::userGet(
self::$config['userID'],
"items?itemKey=$keyStr&include=citation"
. ($style == "default" ? "" : "&style=$style")
. ($style == "default" ? "" : "&style=" . urlencode($style))
);
$this->assert200($response);
$this->assertTotalResults(sizeOf($keys), $response);
Expand All @@ -192,7 +217,7 @@ public function testContentCitationMulti() {
$response = API::userGet(
self::$config['userID'],
"items?itemKey=$keyStr&content=citation"
. ($style == "default" ? "" : "&style=$style")
. ($style == "default" ? "" : "&style=" . urlencode($style))
);
$this->assert200($response);
$this->assertTotalResults(sizeOf($keys), $response);
Expand All @@ -217,7 +242,8 @@ public function testIncludeBibSingle() {
foreach (self::$items as $key => $expected) {
$response = API::userGet(
self::$config['userID'],
"items/$key?include=bib" . ($style == "default" ? "" : "&style=$style")
"items/$key?include=bib"
. ($style == "default" ? "" : "&style=" . urlencode($style))
);
$this->assert200($response);
$json = API::getJSONFromResponse($response);
Expand All @@ -233,7 +259,8 @@ public function testContentBibSingle() {
foreach (self::$items as $key => $expected) {
$response = API::userGet(
self::$config['userID'],
"items/$key?content=bib" . ($style == "default" ? "" : "&style=$style")
"items/$key?content=bib"
. ($style == "default" ? "" : "&style=" . urlencode($style))
);
$this->assert200($response);
$content = API::getContentFromResponse($response);
Expand All @@ -253,7 +280,8 @@ public function testIncludeBibMulti() {
foreach (self::$styles as $style) {
$response = API::userGet(
self::$config['userID'],
"items?itemKey=$keyStr&include=bib" . ($style == "default" ? "" : "&style=$style")
"items?itemKey=$keyStr&include=bib"
. ($style == "default" ? "" : "&style=" . urlencode($style))
);
$this->assert200($response);
$this->assertTotalResults(sizeOf($keys), $response);
Expand All @@ -275,7 +303,8 @@ public function testContentBibMulti() {
foreach (self::$styles as $style) {
$response = API::userGet(
self::$config['userID'],
"items?itemKey=$keyStr&content=bib" . ($style == "default" ? "" : "&style=$style")
"items?itemKey=$keyStr&content=bib"
. ($style == "default" ? "" : "&style=" . urlencode($style))
);
$this->assert200($response);
$xml = API::getXMLFromResponse($response);
Expand All @@ -298,7 +327,7 @@ public function testFormatBibMultiple() {
foreach (self::$styles as $style) {
$response = API::userGet(
self::$config['userID'],
"items?format=bib" . ($style == "default" ? "" : "&style=$style")
"items?format=bib" . ($style == "default" ? "" : "&style=" . urlencode($style))
);
$this->assert200($response);
$this->assertXmlStringEqualsXmlString(self::$multiResponses[$style], $response->getBody());
Expand Down

0 comments on commit e33023d

Please sign in to comment.