├── .github └── workflows │ └── php.yml ├── .travis.yml ├── BibtexbrowserTest.php ├── README.wiki ├── bibacid-utf8.bib ├── bibtex-to-cff.php ├── bibtexbrowser-cli.php ├── bibtexbrowser-users.wiki ├── bibtexbrowser.php ├── composer.json ├── reference-output-wp-publications.txt └── tests └── router.php /.github/workflows/php.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | 3 | on: 4 | push: 5 | branches: [ "master" ] 6 | pull_request: 7 | branches: [ "master" ] 8 | 9 | jobs: 10 | build: 11 | 12 | runs-on: ubuntu-latest 13 | 14 | steps: 15 | - uses: actions/checkout@v4 16 | - name: Run test suite 17 | run: | 18 | echo Running the tests of bibtexbrowser 19 | curl -L -o reflectivedoc.php "https://www.monperrus.net/martin/pp4php.php?pp4php_source=reflectivedoc.php" 20 | phpunit BibtexbrowserTest.php 21 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: php 2 | 3 | services: 4 | # wp-publications is a Wordpress plugin, wordpress requires mysql 5 | - mysql 6 | 7 | # doc at https://docs.travis-ci.com/user/languages/php/ 8 | php: 9 | - '7.4' # release 28 November 2019 10 | - '8.0' # release Nov 2020 11 | - '8.1' # release Nov 2021 12 | - '8.2' # release Nov 2022 13 | - '8.3' # release Nov 2023 14 | 15 | script: 16 | - curl -L -o reflectivedoc.php https://www.monperrus.net/martin/reflectivedoc.php.txt 17 | - curl -L -o gakowiki-syntax.php https://www.monperrus.net/martin/gakowiki-syntax.php.txt 18 | - phpunit BibtexbrowserTest.php 19 | 20 | # now testing this version of bibtexbrowser with wp-publications 21 | # Installing WP-CLI 22 | - curl -O https://raw.githubusercontent.com/wp-cli/builds/gh-pages/phar/wp-cli.phar 23 | - chmod 755 wp-cli.phar 24 | - WPCLI=/tmp/wp 25 | - mv wp-cli.phar $WPCLI 26 | # Installing wordpress with wp-cli 27 | - $WPCLI core download 28 | - mysql -u travis -e "CREATE DATABASE IF NOT EXISTS wp" 29 | - $WPCLI config create --dbname=wp --dbuser=travis 30 | - $WPCLI core install --url=http://bibtexbrowser.com --title="bibtexbrowser wordpress" --admin_user=root --admin_email=martin.monperrus@gnieh.org 31 | # installing wp-cli/restful, which is required to render shortcodes with wp-cli 32 | - $WPCLI package install wp-cli/restful 33 | - $WPCLI core version 34 | # installing plugin wp-publications 35 | - $WPCLI plugin install https://github.com/monperrus/wp-publications/archive/refs/heads/master.zip --activate 36 | # there is no need to create a post, because one activation task of wp-publications is to create a fake post 37 | #- $WPCLI post create --post_title=test --post_content='[wp-publications bib="sample.bib" all=true]' 38 | - cp bibtexbrowser.php ./wp-content/plugins/wp-publications/ 39 | - echo "" > ./wp-content/plugins/wp-publications/bibtexbrowser.local.php 40 | - $WPCLI rest post list --slug=wp-publications-example --field=content | tee before.txt 41 | # do we still have the reference output? (useful for detecting changes in Wordpress or WP-CLI) (diff exits with 1 if there is a difference) 42 | - diff reference-output-wp-publications.txt before.txt 43 | 44 | sudo: false 45 | -------------------------------------------------------------------------------- /BibtexbrowserTest.php: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env phpunit 2 | setIndicesInIncreasingOrderChangingEveryYear(); 60 | } 61 | } 62 | 63 | 64 | class BibtexbrowserTest extends PHPUnit_Framework_TestCase { 65 | 66 | public function setUp():void { 67 | // resetting the default link style 68 | bibtexbrowser_configure('BIBTEXBROWSER_LINK_STYLE','bib2links_default'); 69 | bibtexbrowser_configure('ABBRV_TYPE','index'); 70 | bibtexbrowser_configure('BIBTEXBROWSER_USE_PROGRESSIVE_ENHANCEMENT', false); 71 | } 72 | 73 | function createDB() { 74 | return $this->_createDB("@book{aKey,title={A Book},author={Martin Monperrus},publisher={Springer},year=2009}\n" 75 | ."@book{aKey/withSlash,title={Slash Dangerous for web servers},author={Ap Ache},editor={Martin Monperrus},publisher={Springer},year=2010}\n" 76 | ."@article{aKeyA,title={An Article},author={Foo Bar and Jane Doe},volume=5,journal=\"New Results\",year=2009,pages={1-2}}\n"); 77 | } 78 | 79 | function _createDB($content, $fakefilename="inline") { 80 | $test_data = fopen('php://memory','x+'); 81 | fwrite($test_data, $content); 82 | fseek($test_data,0); 83 | $btb = new BibDataBase(); 84 | $btb->update_internal($fakefilename, $test_data); 85 | return $btb; 86 | } 87 | 88 | 89 | function test_bibentry_to_html_book() { 90 | $btb = $this->createDB(); 91 | $first_entry=$btb->getEntryByKey('aKey'); 92 | 93 | // default style 94 | $this->assertEquals("A Book (Martin Monperrus), Springer, 2009. [bibtex]",strip_tags($first_entry->toHTML())); 95 | $this->assertEquals('A Book (), Springer, . [bibtex]',$first_entry->toHTML()); 96 | 97 | // IEEE style 98 | bibtexbrowser_configure('BIBLIOGRAPHYSTYLE','JanosBibliographyStyle'); 99 | $this->assertEquals("Martin Monperrus, \"A Book\", Springer, 2009.\n [bibtex]",strip_tags($first_entry->toHTML())); 100 | 101 | // Vancouver style 102 | bibtexbrowser_configure('BIBLIOGRAPHYSTYLE','VancouverBibliographyStyle'); 103 | $this->assertEquals("Martin Monperrus. A Book. Springer; 2009.\n [bibtex]",strip_tags($first_entry->toHTML())); 104 | 105 | // other methods 106 | $this->assertEquals('[bibtex]',$first_entry->bib2links()); 107 | $this->assertEquals('',$first_entry->anchor()); 108 | } 109 | 110 | function extract_css_classes($str) { 111 | $xml = new SimpleXMLElement($str); 112 | $css_classes = array(); 113 | foreach($xml->xpath('//node()/@class') as $v) { 114 | $css_classes[] = $v->__toString(); 115 | }; 116 | sort($css_classes); 117 | return $css_classes; 118 | } 119 | 120 | function test_bibentry_to_html_article() { 121 | $btb = $this->createDB(); 122 | $first_entry=$btb->getEntryByKey('aKeyA'); 123 | $this->assertEquals("1-2",$first_entry->getField("pages")); 124 | $this->assertEquals("1",$first_entry->getPages()[0]); 125 | $this->assertEquals("2",$first_entry->getPages()[1]); 126 | 127 | // default style 128 | bibtexbrowser_configure('BIBLIOGRAPHYSTYLE','DefaultBibliographyStyle'); 129 | bibtexbrowser_configure('BIBTEXBROWSER_LINK_STYLE','nothing'); 130 | $this->assertEquals("An Article (Foo Bar and Jane Doe), In New Results, volume 5, 2009. ",strip_tags($first_entry->toHTML())); 131 | $this->assertEquals('An Article ( and ), In New Results, volume 5, . ',$first_entry->toHTML()); 132 | 133 | // listing the CSS classes 134 | $css_classes_before = $this->extract_css_classes($first_entry->toHTML()); 135 | 136 | // IEEE style 137 | bibtexbrowser_configure('BIBLIOGRAPHYSTYLE','JanosBibliographyStyle'); 138 | $this->assertEquals("Foo Bar and Jane Doe, \"An Article\", New Results, vol. 5, pp. 1-2, 2009.\n ",strip_tags($first_entry->toHTML())); 139 | $css_classes_after = $this->extract_css_classes($first_entry->toHTML()); 140 | // contract: make sure the Janos style and default style use the same CSS classes 141 | $this->assertEquals($css_classes_before, $css_classes_after); 142 | 143 | // Vancouver style 144 | bibtexbrowser_configure('BIBLIOGRAPHYSTYLE','VancouverBibliographyStyle'); 145 | $this->assertEquals("Foo Bar and Jane Doe. An Article. New Results. 2009;5:1-2.\n ",strip_tags($first_entry->toHTML())); 146 | 147 | // changing the target 148 | bibtexbrowser_configure('BIBLIOGRAPHYSTYLE','DefaultBibliographyStyle'); 149 | bibtexbrowser_configure('BIBTEXBROWSER_LINKS_TARGET','_top'); 150 | $this->assertEquals('An Article ( and ), In New Results, volume 5, . ',$first_entry->toHTML()); 151 | 152 | // testing ABBRV_TYPE 153 | bibtexbrowser_configure('ABBRV_TYPE','year'); 154 | $this->assertEquals("[2009]",$first_entry->getAbbrv()); 155 | bibtexbrowser_configure('ABBRV_TYPE','key'); 156 | $this->assertEquals("[aKeyA]",$first_entry->getAbbrv()); 157 | bibtexbrowser_configure('ABBRV_TYPE','index'); 158 | $this->assertEquals("[]",$first_entry->getAbbrv()); 159 | $first_entry->setIndex('foo'); 160 | $this->assertEquals("[foo]",$first_entry->getAbbrv()); 161 | bibtexbrowser_configure('ABBRV_TYPE','none'); 162 | $this->assertEquals("",$first_entry->getAbbrv()); 163 | 164 | } 165 | 166 | function testMultiSearch() { 167 | $btb = $this->createDB(); 168 | $q=array(Q_AUTHOR=>'monperrus'); 169 | $results=$btb->multisearch($q); 170 | $entry = $results[0]; 171 | $this->assertTrue(count($results) == 1); 172 | $this->assertTrue($entry->getTitle() == 'A Book'); 173 | } 174 | 175 | function testMultiSearch2() { 176 | $btb = $this->createDB(); 177 | $q=array(Q_AUTHOR=>'monperrus|ducasse'); 178 | $results=$btb->multisearch($q); 179 | $entry = $results[0]; 180 | $this->assertTrue(count($results) == 1); 181 | $this->assertTrue($entry->getTitle() == 'A Book'); 182 | } 183 | 184 | function testMultiSearch_name_match() { 185 | $btb = $this->createDB(); 186 | $q=array(Q_NAME=>'Martin Monperrus'); 187 | $results=$btb->multisearch($q); 188 | $this->assertTrue(count($results) == 2); 189 | } 190 | 191 | function testMultiSearch_author_name_match() { 192 | $btb = $this->createDB(); 193 | $q=array(Q_AUTHOR_NAME=>'Martin Monperrus'); 194 | $results=$btb->multisearch($q); 195 | $entry = $results[0]; 196 | $this->assertTrue(count($results) == 1); 197 | $this->assertTrue($entry->getTitle() == 'A Book'); 198 | } 199 | 200 | function testMultiSearch_editor_name_match() { 201 | $btb = $this->createDB(); 202 | $q=array(Q_EDITOR_NAME=>'Martin Monperrus'); 203 | $results=$btb->multisearch($q); 204 | $entry = $results[0]; 205 | $this->assertTrue(count($results) == 1); 206 | $this->assertTrue($entry->getTitle() == 'Slash Dangerous for web servers'); 207 | } 208 | 209 | function test_config_value() { 210 | // default value 211 | $this->assertFalse(config_value('BIBTEXBROWSER_NO_DEFAULT')); 212 | 213 | // setting to true 214 | bibtexbrowser_configure('BIBTEXBROWSER_NO_DEFAULT', true); 215 | $this->assertTrue(config_value('BIBTEXBROWSER_NO_DEFAULT')); 216 | ob_start(); 217 | default_message(); 218 | $this->assertEquals('', ob_get_clean()); 219 | 220 | // setting to false 221 | bibtexbrowser_configure('BIBTEXBROWSER_NO_DEFAULT', false); 222 | $this->assertFalse(config_value('BIBTEXBROWSER_NO_DEFAULT')); 223 | ob_start(); 224 | default_message(); 225 | $this->assertStringContainsString('Congratulations', ob_get_clean()); 226 | } 227 | 228 | 229 | function testInternationalization() { 230 | $btb = $this->createDB(); 231 | global $BIBTEXBROWSER_LANG; 232 | $BIBTEXBROWSER_LANG=array(); 233 | $BIBTEXBROWSER_LANG['Refereed Conference Papers']="foo"; 234 | $this->assertEquals("foo",__("Refereed Conference Papers")); 235 | 236 | $BIBTEXBROWSER_LANG['Books']="Livres"; 237 | $d = new AcademicDisplay(); 238 | $d->setDB($btb); 239 | ob_start(); 240 | $d->display(); 241 | $data = ob_get_clean(); 242 | $this->assertStringContainsString('Livres', $data); 243 | } 244 | 245 | 246 | function testNoSlashInKey() { 247 | $btb = $this->createDB(); 248 | $q=array(Q_SEARCH=>'Slash'); 249 | $results=$btb->multisearch($q); 250 | $this->assertTrue(count($results) == 1); 251 | $entry = $results[0]; 252 | $this->assertStringContainsString("aKey-withSlash",$entry->toHTML()); 253 | 254 | $q=array(Q_KEY=>'aKey-withSlash'); 255 | $results=$btb->multisearch($q); 256 | $entry2 = $results[0]; 257 | $this->assertSame($entry2,$entry); 258 | } 259 | 260 | function test_string_should_be_deleted_after_update() { 261 | $test_data = fopen('php://memory','x+'); 262 | fwrite($test_data, "@book{aKey,title={A Book},author={Martin Monperrus},publisher={Springer},year=2009}\n". 263 | "@String{x=2008}\n" 264 | ); 265 | fseek($test_data,0); 266 | $btb = new BibDataBase(); 267 | $btb->update_internal("inline", $test_data); 268 | // print_r($btb->stringdb); 269 | $this->assertEquals(1,count($btb->stringdb)); 270 | 271 | // replacing the existing one 272 | $test_data = fopen('php://memory','x+'); 273 | fwrite($test_data, "@book{aKey2,title={A Book},author={Martin Monperrus},publisher={Springer},year=2009}\n". 274 | "@String{x=2009}\n" 275 | ); 276 | fseek($test_data,0); 277 | $btb = new BibDataBase(); 278 | $btb->update_internal("inline2", $test_data); 279 | // print_r($btb->stringdb); 280 | $this->assertEquals(1,count($btb->stringdb)); 281 | $this->assertEquals("2009",$btb->stringdb['x']->value);// 282 | 283 | // now adding another one and removing the string 284 | $test_data2 = fopen('php://memory','x+'); 285 | fwrite($test_data2, "@book{aKey,title={A Book},author={Martin Monperrus},publisher={Springer},year=2009}\n". 286 | "@String{y=2010}\n" 287 | ); 288 | fseek($test_data2,0); 289 | $btb->update_internal("inline2", $test_data2); 290 | $this->assertEquals(1,count($btb->stringdb));// 291 | $this->assertEquals("2010",$btb->stringdb['y']->value);// 292 | 293 | } 294 | 295 | function test_mastersthesis() { 296 | $test_data = fopen('php://memory','x+'); 297 | fwrite($test_data, "@mastersthesis{aKey,title={A Thing},author={Martin Monperrus},year=2009,school={School of Nowhere}}\n". 298 | "@String{x=2008}\n" 299 | ); 300 | fseek($test_data,0); 301 | $db = new BibDataBase(); 302 | $db->update_internal("inline", $test_data); 303 | $this->assertEquals("A Thing (Martin Monperrus), Master's thesis, School of Nowhere, 2009. [bibtex]",strip_tags($db->getEntryByKey('aKey')->toHTML())); 304 | } 305 | 306 | function test_google_scholar_metadata() { 307 | bibtexbrowser_configure('METADATA_GS', true); 308 | $test_data = fopen('php://memory','x+'); 309 | fwrite($test_data, "@article{aKey,title={A Book},author={Martin Monperrus},publisher={Springer},year=2009,pages={42--4242},number=1}\n". 310 | "@String{x=2008}\n" 311 | ); 312 | fseek($test_data,0); 313 | $db = new BibDataBase(); 314 | $db->update_internal("inline", $test_data); 315 | $dis = new BibEntryDisplay($db->getEntryByKey('aKey')); 316 | $metadata = $dis->metadata_dict(); 317 | //print_r($metadata); 318 | $this->assertEquals("A Book",$metadata['citation_title']); 319 | $this->assertEquals("2009",$metadata['citation_date']); 320 | $this->assertEquals("2009",$metadata['citation_year']); 321 | $this->assertEquals("42",$metadata['citation_firstpage']); 322 | $this->assertEquals("4242",$metadata['citation_lastpage']); 323 | $this->assertEquals("1",$metadata['citation_issue']); 324 | 325 | } 326 | 327 | function test_metadata_opengraph() { 328 | $test_data = fopen('php://memory','x+'); 329 | fwrite($test_data, "@article{aKey,title={A Book},author={Martin Monperrus},url={http://foo.com/},publisher={Springer},year=2009,pages={42--4242},number=1}\n". 330 | "@String{x=2008}\n" 331 | ); 332 | fseek($test_data,0); 333 | $db = new BibDataBase(); 334 | $db->update_internal("inline", $test_data); 335 | $dis = new BibEntryDisplay($db->getEntryByKey('aKey')); 336 | $metadata = $dis->metadata_dict(); 337 | 338 | //print_r($metadata); 339 | $this->assertEquals("A Book",$metadata['og:title']); 340 | $this->assertEquals("article",$metadata['og:type']); 341 | $this->assertTrue(1 == preg_match("/http:.*author=Martin\+Monperrus/",$metadata['og:author'])); 342 | $this->assertEquals("2009",$metadata['og:published_time']); 343 | } 344 | 345 | 346 | function test_math_cal() { 347 | $test_data = fopen('php://memory','x+'); 348 | fwrite($test_data, "@book{aKey,title={{A {Book} $\mbox{foo}$ tt $\boo{t}$}} ,author={Martin Monperrus},publisher={Springer},year=2009}\n". 349 | "@String{x=2008}\n" 350 | ); 351 | fseek($test_data,0); 352 | $btb = new BibDataBase(); 353 | $btb->update_internal("inline", $test_data); 354 | $first_entry=$btb->bibdb[array_keys($btb->bibdb)[0]]; 355 | // $this->assertTrue(strpos('A Book{} $\mbox{foo}$',$first_entry->toHTML()); 356 | $this->assertEquals('A Book $\mbox{foo}$ tt $\boo{t}$',$first_entry->getTitle()); 357 | } 358 | 359 | function test_link_configuration() { 360 | bibtexbrowser_configure('BIBTEXBROWSER_LINKS_TARGET','_self'); 361 | $test_data = fopen('php://memory','x+'); 362 | fwrite($test_data, "@book{aKey,pdf={myarticle.pdf}}\n@book{bKey,url={myarticle.pdf}}\n@book{cKey,url={myarticle.xyz}}\n" 363 | ); 364 | fseek($test_data,0); 365 | $btb = new BibDataBase(); 366 | $btb->update_internal("inline", $test_data); 367 | $first_entry=$btb->bibdb[array_keys($btb->bibdb)[0]]; 368 | $this->assertEquals('[pdf]',$first_entry->getLink('pdf')); 369 | $this->assertEquals('[pdf]',$first_entry->getPdfLink()); 370 | $this->assertEquals('[pdf]',$first_entry->getLink('pdf','pdficon.png')); 371 | $this->assertEquals('[see]',$first_entry->getLink('pdf',NULL,'see')); 372 | $second_entry=$btb->bibdb[array_keys($btb->bibdb)[1]]; 373 | $this->assertEquals('[pdf]',$second_entry->getPdfLink()); 374 | $third_entry=$btb->bibdb[array_keys($btb->bibdb)[2]]; 375 | $this->assertEquals('[url]',$third_entry->getPdfLink()); 376 | } 377 | 378 | // see https://github.com/monperrus/bibtexbrowser/pull/14 379 | function test_zotero() { 380 | bibtexbrowser_configure('BIBTEXBROWSER_LINKS_TARGET','_self'); 381 | $test_data = fopen('php://memory','x+'); 382 | fwrite($test_data, "@book{aKey,file={myarticle.pdf}}\n" 383 | ); 384 | fseek($test_data,0); 385 | $btb = new BibDataBase(); 386 | $btb->update_internal("inline", $test_data); 387 | $first_entry=$btb->bibdb[array_keys($btb->bibdb)[0]]; 388 | $this->assertEquals('[pdf]',$first_entry->getPdfLink()); 389 | } 390 | 391 | // https://github.com/monperrus/bibtexbrowser/issues/40 392 | function test_doi_url() { 393 | bibtexbrowser_configure('BIBTEXBROWSER_LINKS_TARGET','_self'); 394 | $test_data = fopen('php://memory','x+'); 395 | fwrite($test_data, "@Article{Baldwin2014Quantum,Doi={10.1103/PhysRevA.90.012110},Url={http://link.aps.org/doi/10.1103/PhysRevA.90.012110}}" 396 | ); 397 | fseek($test_data,0); 398 | $btb = new BibDataBase(); 399 | $btb->update_internal("inline", $test_data); 400 | $first_entry=$btb->bibdb[array_keys($btb->bibdb)[0]]; 401 | $this->assertEquals('
@Article{Baldwin2014Quantum,Doi={10.1103/PhysRevA.90.012110},Url={http://link.aps.org/doi/10.1103/PhysRevA.90.012110}}
',$first_entry->toEntryUnformatted()); 402 | } 403 | 404 | function test_filter_view() { 405 | $test_data = fopen('php://memory','x+'); 406 | fwrite($test_data, "@article{aKey,title={A Book},author={Martin M\'e},publisher={Springer},year=2009,pages={42--4242},number=1}\n"); 407 | fseek($test_data,0); 408 | $db = new BibDataBase(); 409 | $db->update_internal("inline", $test_data); 410 | $dis = $db->getEntryByKey('aKey'); 411 | $this->assertEquals("@article{aKey,title={A Book},author={Martin M\'e},publisher={Springer},year=2009,pages={42--4242},number=1}",$dis->getText()); 412 | 413 | // now ith option 414 | bibtexbrowser_configure('BIBTEXBROWSER_BIBTEX_VIEW', 'reconstructed'); 415 | bibtexbrowser_configure('BIBTEXBROWSER_BIBTEX_VIEW_FILTEREDOUT', 'pages|number'); 416 | $this->assertEquals("@article{aKey,\n title = {A Book},\n author = {Martin M\'e},\n publisher = {Springer},\n year = {2009},\n}\n", $dis->getText()); 417 | } 418 | 419 | function test_BIBTEXBROWSER_USE_LATEX2HTML() { 420 | $bibtex = "@article{aKey,title={\`a Book},author={J\'e Lo},publisher={Springer},year=2009,pages={42--4242},number=1}\n"; 421 | 422 | bibtexbrowser_configure('BIBTEXBROWSER_USE_LATEX2HTML', true); 423 | $test_data = fopen('php://memory','x+'); 424 | fwrite($test_data, $bibtex); 425 | fseek($test_data,0); 426 | $db = new BibDataBase(); 427 | $db->update_internal("inline", $test_data); 428 | $dis = $db->getEntryByKey('aKey'); 429 | $this->assertEquals("à Book",$dis->getTitle()); 430 | $this->assertEquals("Jé Lo",$dis->getFormattedAuthorsString()); 431 | 432 | // ensure that it is comma separated, used for metadata 433 | $this->assertEquals("Lo, Jé",$dis->getArrayOfCommaSeparatedAuthors()[0]); 434 | 435 | bibtexbrowser_configure('BIBTEXBROWSER_USE_LATEX2HTML', false); 436 | $test_data = fopen('php://memory','x+'); 437 | fwrite($test_data, $bibtex); 438 | fseek($test_data,0); 439 | $db = new BibDataBase(); 440 | $db->update_internal("inline", $test_data); 441 | $dis = $db->getEntryByKey('aKey'); 442 | $this->assertEquals("\`a Book",$dis->getTitle()); 443 | $this->assertEquals("J\'e Lo",$dis->getFormattedAuthorsString()); 444 | } 445 | 446 | 447 | function test_PagedDisplay() { 448 | $PAGE_SIZE = 4; 449 | bibtexbrowser_configure('BIBTEXBROWSER_DEFAULT_DISPLAY', 'PagedDisplay'); 450 | bibtexbrowser_configure('PAGE_SIZE', $PAGE_SIZE); 451 | $db = new BibDataBase(); 452 | $db->load('bibacid-utf8.bib'); 453 | $d = new PagedDisplay(); 454 | $d->setEntries($db->bibdb); 455 | ob_start(); 456 | $d->display(); 457 | $content = "
".ob_get_clean()."
"; 458 | $xml = new SimpleXMLElement($content); 459 | $result = $xml->xpath('//td[@class=\'bibref\']'); 460 | $this->assertEquals($PAGE_SIZE,count($result)); 461 | } 462 | 463 | function test_getKeywords() { 464 | $bibtex = "@article{aKey,title={\`a Book},keywords={foo,bar},author={Martin Monperrus},publisher={Springer},year=2009,pages={42--4242},number=1}\n"; 465 | 466 | bibtexbrowser_configure('BIBTEXBROWSER_USE_LATEX2HTML', true); 467 | $test_data = fopen('php://memory','x+'); 468 | fwrite($test_data, $bibtex); 469 | fseek($test_data,0); 470 | $db = new BibDataBase(); 471 | $db->update_internal("inline", $test_data); 472 | $dis = $db->getEntryByKey('aKey'); 473 | $this->assertEquals(2,count($dis->getKeywords())); 474 | } 475 | 476 | # https://github.com/monperrus/bibtexbrowser/pull/51 477 | function test_emptyGetPdfLink() { 478 | bibtexbrowser_configure('BIBTEXBROWSER_LINKS_TARGET','_self'); 479 | $bibtex = " 480 | @article{aKey, 481 | title={\`a Book}, 482 | author={Martin Monperrus}, 483 | publisher={Springer}, 484 | year=2009, 485 | pages={42--4242}, 486 | number=1 487 | } 488 | @article{bKey, 489 | url={magic.pdf}, 490 | } 491 | @article{cKey, 492 | pdf={magic2.pdf}, 493 | url={magic3} 494 | }"; 495 | $test_data = fopen('php://memory','x+'); 496 | fwrite($test_data, $bibtex); 497 | fseek($test_data,0); 498 | $db = new BibDataBase(); 499 | $db->update_internal("inline", $test_data); 500 | 501 | $dis = $db->getEntryByKey('aKey'); 502 | $this->assertEquals("",$dis->getPdfLink()); 503 | 504 | $dis = $db->getEntryByKey('bKey'); 505 | $this->assertEquals('[pdf]',$dis->getPdfLink()); 506 | 507 | $dis = $db->getEntryByKey('cKey'); 508 | $this->assertEquals('[pdf]',$dis->getPdfLink()); 509 | } 510 | 511 | function test_formatting() { 512 | 513 | $bibtex = "@article{aKey61,title={An article Book},author = {Meyer, Heribert and {Advanced Air and Ground Research Team} and Foo Bar}}\n@article{bKey61,title={An article Book},author = {Meyer, Heribert and Foo Bar}}\n"; 514 | $test_data = fopen('php://memory','x+'); 515 | fwrite($test_data, $bibtex); 516 | fseek($test_data,0); 517 | $db = new BibDataBase(); 518 | $db->update_internal("inline", $test_data); 519 | $entry = $db->getEntryByKey('aKey61'); 520 | 521 | // test with formatting with default options same as getRawAuthors() 522 | $authors = $entry->getFormattedAuthorsArray(); 523 | $this->assertEquals(3, count($authors)); 524 | $this->assertEquals("Meyer, Heribert", $authors[0]); 525 | $this->assertEquals("Advanced Air and Ground Research Team", $authors[1]); 526 | $this->assertEquals("Foo Bar", $authors[2]); 527 | $this->assertEquals("Meyer, Heribert, Advanced Air and Ground Research Team and Foo Bar", $entry->getFormattedAuthorsString()); 528 | 529 | // test with formatting (first name before) 530 | bibtexbrowser_configure('USE_COMMA_AS_NAME_SEPARATOR_IN_OUTPUT', true); 531 | $authors = $entry->getFormattedAuthorsArray(); 532 | $this->assertEquals(3, count($authors)); 533 | $this->assertEquals("Meyer, Heribert", $authors[0]); 534 | $this->assertEquals("Team, Advanced Air and Ground Research", $authors[1]); 535 | $this->assertEquals("Bar, Foo", $authors[2]); 536 | $this->assertEquals("Meyer, Heribert; Team, Advanced Air and Ground Research and Bar, Foo", $entry->getFormattedAuthorsString()); 537 | 538 | // test with formatting (with initials) formatAuthorInitials 539 | bibtexbrowser_configure('USE_COMMA_AS_NAME_SEPARATOR_IN_OUTPUT', false); 540 | bibtexbrowser_configure('USE_INITIALS_FOR_NAMES', true); 541 | $authors = $entry->getFormattedAuthorsArray(); 542 | $this->assertEquals(3, count($authors)); 543 | $this->assertEquals("Meyer H", $authors[0]); 544 | $this->assertEquals("Team AAand GR", $authors[1]); 545 | $this->assertEquals("Bar F", $authors[2]); 546 | $this->assertEquals("Meyer H, Team AAand GR and Bar F", $entry->getFormattedAuthorsString()); 547 | 548 | // test with first_name last_name formatAuthorCanonical 549 | bibtexbrowser_configure('USE_COMMA_AS_NAME_SEPARATOR_IN_OUTPUT', false); 550 | bibtexbrowser_configure('USE_INITIALS_FOR_NAMES', false); 551 | bibtexbrowser_configure('USE_FIRST_THEN_LAST', true); 552 | $authors = $entry->getFormattedAuthorsArray(); 553 | $this->assertEquals(3, count($authors)); 554 | $this->assertEquals("Heribert Meyer", $authors[0]); 555 | $this->assertEquals("Advanced Air and Ground Research Team", $authors[1]); 556 | $this->assertEquals("Foo Bar", $authors[2]); 557 | $this->assertEquals("Heribert Meyer, Advanced Air and Ground Research Team and Foo Bar", $entry->getFormattedAuthorsString()); 558 | 559 | // test Oxford comma with default options 560 | bibtexbrowser_configure('USE_COMMA_AS_NAME_SEPARATOR_IN_OUTPUT', false); 561 | bibtexbrowser_configure('USE_INITIALS_FOR_NAMES', false); 562 | bibtexbrowser_configure('USE_FIRST_THEN_LAST', false); 563 | bibtexbrowser_configure('USE_OXFORD_COMMA', true); 564 | $this->assertEquals("Meyer, Heribert, Advanced Air and Ground Research Team, and Foo Bar", $entry->getFormattedAuthorsString()); 565 | $entry = $db->getEntryByKey('bKey61'); 566 | $this->assertEquals("Meyer, Heribert and Foo Bar", $entry->getFormattedAuthorsString()); 567 | bibtexbrowser_configure('USE_OXFORD_COMMA', false); 568 | } 569 | 570 | function test_parsing_author_list() { 571 | // specify parsing of author list 572 | 573 | bibtexbrowser_configure('USE_COMMA_AS_NAME_SEPARATOR_IN_OUTPUT', false); 574 | bibtexbrowser_configure('USE_FIRST_THEN_LAST', false); 575 | 576 | // default case: one authors 577 | $bibtex = "@article{aKey61,title={An article Book},author = {Meyer, Heribert}}\n"; 578 | $test_data = fopen('php://memory','x+'); 579 | fwrite($test_data, $bibtex); 580 | fseek($test_data,0); 581 | $db = new BibDataBase(); 582 | $db->update_internal("inline", $test_data); 583 | $entry = $db->getEntryByKey('aKey61'); 584 | $authors = $entry->getRawAuthors(); 585 | $this->assertEquals(1,count($authors)); 586 | $this->assertEquals("Meyer, Heribert", $authors[0]); 587 | 588 | // default case: no sub list 589 | $bibtex = "@article{aKey61,title={An article Book},author = {Meyer, Heribert and Foo Bar}}\n"; 590 | $test_data = fopen('php://memory','x+'); 591 | fwrite($test_data, $bibtex); 592 | fseek($test_data,0); 593 | $db = new BibDataBase(); 594 | $db->update_internal("inline", $test_data); 595 | $entry = $db->getEntryByKey('aKey61'); 596 | $authors = $entry->getRawAuthors(); 597 | $this->assertEquals(2,count($authors)); 598 | $this->assertEquals("Meyer, Heribert", $authors[0]); 599 | $this->assertEquals("Meyer, Heribert and Foo Bar", $entry->getFormattedAuthorsString()); 600 | 601 | // Github issue 61 602 | $bibtex = "@article{aKey61,title={An article Book},author = {Meyer, Heribert and {Advanced Air and Ground Research Team} and Foo Bar and J{\'e} Ko and J{\'e} Le and Fd L{\'e}}}\n"; 603 | // wrong parsing of author names 604 | $test_data = fopen('php://memory','x+'); 605 | fwrite($test_data, $bibtex); 606 | fseek($test_data,0); 607 | $db = new BibDataBase(); 608 | $db->update_internal("inline", $test_data); 609 | $entry = $db->getEntryByKey('aKey61'); 610 | $authors = $entry->getRawAuthors(); 611 | $this->assertEquals(6, count($authors)); 612 | $this->assertEquals("Meyer, Heribert", $authors[0]); 613 | $this->assertEquals("Advanced Air and Ground Research Team", $authors[1]); 614 | $this->assertEquals("Foo Bar", $authors[2]); 615 | $this->assertEquals("J{\'e} Ko", $authors[3]); 616 | $this->assertEquals("J{\'e} Le", $authors[4]); 617 | $this->assertEquals("Fd L{\'e}", $authors[5]); 618 | } 619 | 620 | function test_latex2html() { 621 | $this->assertEquals('"', latex2html("``")); 622 | $this->assertEquals('"', latex2html("''")); 623 | $this->assertEquals('é', latex2html("\'e")); 624 | $this->assertEquals('é', latex2html("{\'e}")); 625 | } 626 | 627 | function test_homepage_link() { 628 | bibtexbrowser_configure('USE_COMMA_AS_NAME_SEPARATOR_IN_OUTPUT', false); 629 | bibtexbrowser_configure('USE_FIRST_THEN_LAST', false); 630 | $bibtex = "@string{hp_MartinMonperrus={http://www.monperrus.net/~martin},hp_FooAcé={http://example.net/}},@article{aKey61,title={An article Book},author = {Martin Monperrus and Foo Acé and Monperrus, Martin}}\n"; 631 | $test_data = fopen('php://memory','x+'); 632 | fwrite($test_data, $bibtex); 633 | fseek($test_data,0); 634 | $db = new BibDataBase(); 635 | $db->update_internal("inline", $test_data); 636 | $entry = $db->getEntryByKey('aKey61'); 637 | $authors = $entry->getFormattedAuthorsArray(); 638 | $this->assertEquals('Martin Monperrus', $authors[0]); 639 | $this->assertEquals('Foo Acé', $authors[1]); 640 | $this->assertEquals('Monperrus, Martin', $authors[2]); 641 | } 642 | 643 | function test_author_index() { 644 | bibtexbrowser_configure('USE_FIRST_THEN_LAST', true); 645 | 646 | $bibtex = "@string{hp_MartinMonperrus={http://www.monperrus.net/martin},hp_FooAcé={http://example.net/}},@article{aKey61,title={An article Book},author = {Martin Monperrus and Foo Ac\'e and Monperrus, Martin}}\n"; 647 | $test_data = fopen('php://memory','x+'); 648 | fwrite($test_data, $bibtex); 649 | fseek($test_data,0); 650 | $db = new BibDataBase(); 651 | $db->update_internal("inline", $test_data); 652 | 653 | $index = var_export($db->authorIndex(), true); 654 | $this->assertEquals("array (\n 'Foo Acé' => 'Foo Acé',\n 'Martin Monperrus' => 'Martin Monperrus',\n)", $index); 655 | } 656 | 657 | function test_string_entries() { 658 | $btb = new BibDataBase(); 659 | $btb->load('bibacid-utf8.bib'); 660 | $this->assertEquals(5, count($btb->stringdb)); 661 | $this->assertEquals("@string{foo={Foo}}",$btb->stringdb['foo']->toString()); 662 | } 663 | 664 | function test_indices() { 665 | $btb = $this->createDB(); 666 | $this->assertEquals("[]", $btb->getEntryByKey('aKey')->getAbbrv()); 667 | 668 | $d = new SimpleDisplay(); 669 | $d->setDB($btb); 670 | ob_start(); 671 | $d->display(); 672 | ob_get_clean(); 673 | 674 | // the indices have been set by SimpleDisplay 675 | $this->assertEquals("[3]", $btb->getEntryByKey('aKey')->getAbbrv()); 676 | $this->assertEquals("[1]", $btb->getEntryByKey('aKey-withSlash')->getAbbrv()); 677 | 678 | // SimpleDisplayExt sets the indices differently, using setIndicesInIncreasingOrderChangingEveryYear 679 | $d = new SimpleDisplayExt(); 680 | $d->setDB($btb); 681 | ob_start(); 682 | $d->display(); 683 | ob_get_clean(); 684 | $this->assertEquals("[1]", $btb->getEntryByKey('aKey')->getAbbrv()); 685 | $this->assertEquals("[1]", $btb->getEntryByKey('aKey-withSlash')->getAbbrv()); 686 | 687 | } 688 | 689 | function test_identity() { 690 | $btb = new BibDataBase(); 691 | $btb->load('bibacid-utf8.bib'); 692 | bibtexbrowser_configure('BIBTEXBROWSER_BIBTEX_VIEW_FILTEREDOUT', ''); 693 | 694 | // computing the representation 695 | $d = new SimpleDisplay(); 696 | $d->setDB($btb); 697 | ob_start(); 698 | $d->display(); 699 | $rep = ob_get_clean(); 700 | 701 | $nref = count($btb->bibdb); 702 | $bibtex = $btb->toBibtex(); 703 | 704 | // reparsing the new content 705 | $btb2 = $this->_createDB($bibtex, 'bibacid-utf8.bib'); 706 | $d->setDB($btb2); 707 | ob_start(); 708 | $d->display(); 709 | $rep2 = ob_get_clean(); 710 | // there is the same number of entries 711 | $this->assertEquals($nref, count($btb2->bibdb)); 712 | $this->assertEquals($bibtex, $btb2->toBibtex()); 713 | $this->assertEquals($rep, $rep2); 714 | } 715 | 716 | function test_cli() { 717 | $test_file="test_cli.bib"; 718 | copy('bibacid-utf8.bib', $test_file); 719 | system('php bibtexbrowser-cli.php '.$test_file." --id classical --set-title \"a new title\""); 720 | $db = new BibDataBase(); 721 | $db->load($test_file); 722 | $this->assertEquals("a new title", $db->getEntryByKey('classical')->getField('title')); 723 | 724 | // multiple changes 725 | system('php bibtexbrowser-cli.php '.$test_file." --id classical --set-title \"a new title\" --id with_abstract --set-title \"a new title\" --set-year 1990"); 726 | $db = new BibDataBase(); 727 | $db->load($test_file); 728 | $this->assertEquals("a new title", $db->getEntryByKey('classical')->getField('title')); 729 | $this->assertEquals("a new title", $db->getEntryByKey('with_abstract')->getField('title')); 730 | $this->assertEquals("1990", $db->getEntryByKey('with_abstract')->getField('year')); 731 | 732 | unlink($test_file); 733 | } 734 | 735 | function test_removeField() { 736 | $btb = $this->createDB(); 737 | $first_entry=$btb->getEntryByKey('aKey'); 738 | $this->assertTrue($first_entry->hasField('author')); 739 | $first_entry->removeField('author'); 740 | $this->assertFalse($first_entry->hasField('author')); 741 | } 742 | 743 | function testdefaultkey() { 744 | bibtexbrowser_configure('BIBTEXBROWSER_BIBTEX_VIEW', 'original'); 745 | $bibtex = "@article{title={An article Book},author = {Martin Monperrus and Foo Ac\'e and Monperrus, Martin}}"; 746 | $key = md5($bibtex); 747 | $test_data = fopen('php://memory','x+'); 748 | fwrite($test_data, $bibtex); 749 | fseek($test_data,0); 750 | $db = new BibDataBase(); 751 | $db->update_internal("inline", $test_data); 752 | 753 | $entry=$db->getEntryByKey($key); 754 | $this->assertEquals($bibtex, $entry->getText()); 755 | } 756 | 757 | function testscholarlink() { 758 | bibtexbrowser_configure('BIBTEXBROWSER_LINKS_TARGET','_self'); 759 | bibtexbrowser_configure('BIBTEXBROWSER_BIBTEX_VIEW', 'original'); 760 | $bibtex = "@article{key,title={An article Book},gsid={1234},author = {Martin Monperrus and Foo Ac\'e and Monperrus, Martin}}"; 761 | $test_data = fopen('php://memory','x+'); 762 | fwrite($test_data, $bibtex); 763 | fseek($test_data,0); 764 | $db = new BibDataBase(); 765 | $db->update_internal("inline", $test_data); 766 | $entry=$db->getEntryByKey("key"); 767 | $this->assertStringContainsString('[citations]', $entry->toHTML()); 768 | } 769 | 770 | 771 | function test_before() { 772 | // contract: the ordering is chronological 773 | $bibtex = "@article{doe2000,title={An article},author={Jane Doe},journal={The Wordpress Journal},year=2000}@book{doo2001,title={A book},author={Jane Doe},year=2001}"; 774 | $test_data = fopen('php://memory','x+'); 775 | fwrite($test_data, $bibtex); 776 | fseek($test_data,0); 777 | $db = new BibDataBase(); 778 | $_GET[Q_FILE] = 'sample.bib'; 779 | $db->update_internal("inline", $test_data); 780 | 781 | $d = new SimpleDisplay(); 782 | $d->setDB($db); 783 | ob_start(); 784 | NoWrapper($d); 785 | $output = ob_get_clean(); 786 | $res = eval("return ".file_get_contents('reference-output-wp-publications.txt').";"); 787 | $this->assertEquals(strip_tags($res['rendered']), "[wp-publications bib=sample.bib all=1] gives:\n".strip_tags($output)."\n"); 788 | } 789 | 790 | function test80() { 791 | // contract: entries without year are at the top 792 | $bibtex = "@article{keyWithoutYear,title={First article},author = {Martin}},@article{key2,title={Second article},author = {Martin}, year=2007}"; 793 | $test_data = fopen('php://memory','x+'); 794 | fwrite($test_data, $bibtex); 795 | fseek($test_data,0); 796 | $db = new BibDataBase(); 797 | $db->update_internal("inline", $test_data); 798 | 799 | $d = new SimpleDisplay(); 800 | $d->setDB($db); 801 | ob_start(); 802 | $d->display(); 803 | $output = ob_get_clean(); 804 | // print($output); 805 | $this->assertEquals("keyWithoutYear", $d->entries[0]->getKey()); 806 | $this->assertEquals("key2", $d->entries[1]->getKey()); 807 | // the indices have been set by SimpleDisplay, by default the one at the top is the one withuut year (the first in $d->entries) 808 | $this->assertEquals("[2]", $db->getEntryByKey('keyWithoutYear')->getAbbrv()); 809 | $this->assertEquals("[1]", $db->getEntryByKey('key2')->getAbbrv()); 810 | } 811 | 812 | function test_bug_201808() { 813 | $btb = new BibDataBase(); 814 | $btb->load('bibacid-utf8.bib'); 815 | $this->assertEquals(4,count($btb->bibdb['arXiv-1807.05030']->getRawAuthors())); 816 | $this->assertEquals(4,count($btb->bibdb['arXiv-1807.05030']->getFormattedAuthorsArray())); 817 | $this->assertEquals("Oscar Luis Vera-Pérez, Benjamin Danglot, Martin Monperrus and Benoit Baudry",$btb->bibdb['arXiv-1807.05030']->getAuthor()); 818 | 819 | bibtexbrowser_configure('BIBTEXBROWSER_LINK_STYLE','nothing'); 820 | bibtexbrowser_configure('BIBLIOGRAPHYSTYLE','JanosBibliographyStyle'); 821 | $this->assertEquals("Oscar Luis Vera-Pérez, Benjamin Danglot, Martin Monperrus and Benoit Baudry, \"A Comprehensive Study of Pseudo-tested Methods\", Technical report, arXiv 1807.05030, 2018.\n ",strip_tags($btb->bibdb['arXiv-1807.05030']->toHTML())); 822 | 823 | } 824 | 825 | 826 | function test_multiple_table() { 827 | ob_start(); 828 | 829 | $btb = new BibDataBase(); 830 | $btb->load('bibacid-utf8.bib'); 831 | 832 | $display = new SimpleDisplay($btb, array(Q_YEAR => '1997')); 833 | $display->display(); 834 | 835 | $display = new SimpleDisplay($btb, array(Q_YEAR => '2010')); 836 | $display->display(); 837 | 838 | $output = ob_get_clean(); 839 | 840 | // assertion: we have two tables in the output 841 | $xml = new SimpleXMLElement("".$output.""); 842 | $result = $xml->xpath('//table'); 843 | $this->assertEquals(2,count($result)); 844 | 845 | } 846 | 847 | function test_cff() { 848 | 849 | $btb = new BibDataBase(); 850 | $btb->load('bibacid-utf8.bib'); 851 | $entry = $btb->bibdb['arXiv-1807.05030']; 852 | $expected = "cff-version: 1.2.0\n". 853 | "# CITATION.cff created with https://github.com/monperrus/bibtexbrowser/\n". 854 | "preferred-citation:\n". 855 | " title: \"A Comprehensive Study of Pseudo-tested Methods\"\n". 856 | " year: \"2018\"\n". 857 | " authors:\n". 858 | " - family-names: Vera-Pérez\n". 859 | " given-names: Oscar Luis\n". 860 | " - family-names: Danglot\n". 861 | " given-names: Benjamin\n". 862 | " - family-names: Monperrus\n". 863 | " given-names: Martin\n". 864 | " - family-names: Baudry\n". 865 | " given-names: Benoit\n"; 866 | 867 | $this->assertEquals($expected,$entry->toCFF()); 868 | 869 | } 870 | 871 | function test_uppercase() { 872 | print(preg_replace_callback('/\\\\uppercase\{(.*)\}/',"strtolowercallback", "$\uppercase{B}")); 873 | 874 | $bibtex = "@article{doe2000,title={Preferential polarization and its reversal in polycrystalline $\uppercase{B}i\uppercase{F}e\uppercase{O}_{3}$/$\uppercase{L}a_{0. 5}\uppercase{S}r_{0.5} \uppercase{C}o\uppercase{O}_{3}$ heterostructures},author={Jane Doe},journal={The Wordpress Journal},year=2000}"; 875 | $test_data = fopen('php://memory','x+'); 876 | fwrite($test_data, $bibtex); 877 | fseek($test_data,0); 878 | $db = new BibDataBase(); 879 | $_GET[Q_FILE] = 'sample.bib'; 880 | $db->update_internal("inline", $test_data); 881 | $this->assertEquals('Preferential polarization and its reversal in polycrystalline $BiFeO_{3}$/$La_{0. 5}Sr_{0.5} CoO_{3}$ heterostructures', $db->bibdb['doe2000']->getTitle()); 882 | } 883 | 884 | function test_sorting_year() { 885 | $bibtex = "@article{doe2004,year=2004},@article{doe1999,year=1999},@article{doe2000,year=2000}"; 886 | $test_data = fopen('php://memory','x+'); 887 | fwrite($test_data, $bibtex); 888 | fseek($test_data,0); 889 | $db = new BibDataBase(); 890 | $db->update_internal("inline", $test_data); 891 | // print_r($db); 892 | $data = array_values($db->bibdb); 893 | $this->assertEquals("2004", $data[0]->getYear()); 894 | $this->assertEquals("1999", $data[1]->getYear()); 895 | $this->assertEquals("2000", $data[2]->getYear()); 896 | usort($data, 'compare_bib_entry_by_year'); 897 | 898 | $this->assertEquals("1999", $data[0]->getYear()); 899 | $this->assertEquals("2000", $data[1]->getYear()); 900 | $this->assertEquals("2004", $data[2]->getYear()); 901 | 902 | $bibtex = "@article{doe2004,year=2004},@article{doe1999,year=1999},@article{doe2000,year=2000}"; 903 | 904 | } 905 | 906 | function test_sorting_month() { 907 | $bibtex = "@article{doe2004,year=2004, month={may}},@article{doe1999,year=2004,month={jan}},@article{doe2000,year=2000, month={dec}}"; 908 | $test_data = fopen('php://memory','x+'); 909 | fwrite($test_data, $bibtex); 910 | fseek($test_data,0); 911 | $db = new BibDataBase(); 912 | $db->update_internal("inline", $test_data); 913 | // print_r($db); 914 | $data = array_values($db->bibdb); 915 | $this->assertEquals("may", $data[0]->getField("month")); 916 | usort($data, 'compare_bib_entry_by_month'); 917 | 918 | $this->assertEquals("jan", $data[0]->getField("month")); 919 | $this->assertEquals("may", $data[1]->getField("month")); 920 | $this->assertEquals("dec", $data[2]->getField("month")); 921 | 922 | } 923 | 924 | function test_misc() { 925 | bibtexbrowser_configure('BIBLIOGRAPHYSTYLE','DefaultBibliographyStyle'); 926 | $bibtex = "@misc{doe2004,title={foo bar title}, publisher={publisher}, howpublished={howpublished}}"; 927 | $test_data = fopen('php://memory','x+'); 928 | fwrite($test_data, $bibtex); 929 | fseek($test_data,0); 930 | $db = new BibDataBase(); 931 | $db->update_internal("inline", $test_data); 932 | // print_r($db); 933 | $data = array_values($db->bibdb); 934 | $this->assertEquals('foo bar title, howpublished. [bibtex]', strip_tags($data[0]->toHTML())); 935 | } 936 | 937 | function test_note() { 938 | // fix https://github.com/monperrus/bibtexbrowser/issues/131 939 | bibtexbrowser_configure('BIBLIOGRAPHYSTYLE','DefaultBibliographyStyle'); 940 | bibtexbrowser_configure('BIBTEXBROWSER_BIBTEX_LINKS',false); 941 | bibtexbrowser_configure('BIBTEXBROWSER_PDF_LINKS',false); 942 | $bibtex = " 943 | @inproceedings{exampleEntry, 944 | author = {Aurora Macías and Elena Navarro and Carlos E. Cuesta and Uwe Zdun}, 945 | title = {Architecting Digital Twins Using a Domain-Driven Design-Based Approach}, 946 | booktitle = {XXVII Jornadas de Ingenier'{\i}a del Software y Bases de Datos (JISBD 2023)}, 947 | month = {September}, 948 | note = {handle: 11705/JISBD/2023/7321}, 949 | year = {2023}, 950 | url = {https://hdl.handle.net/11705/JISBD/2023/7321}, 951 | month = {September}, 952 | pages = {1--1}, 953 | publisher = {SISTEDES}, 954 | editor = {Amador Dur'{a}n Toro}, 955 | }"; 956 | $test_data = fopen('php://memory','x+'); 957 | fwrite($test_data, $bibtex); 958 | fseek($test_data,0); 959 | $db = new BibDataBase(); 960 | $db->update_internal("inline", $test_data); 961 | // print_r($db); 962 | $data = array_values($db->bibdb); 963 | $this->assertEquals(' Architecting Digital Twins Using a Domain-Driven Design-Based Approach (Aurora Macías, Elena Navarro, Carlos E. Cuesta and Uwe Zdun), In XXVII Jornadas de Ingenier\'ia del Software y Bases de Datos (JISBD 2023) (Amador Dur\'an Toro, ed.), SISTEDES, 2023, handle: 11705/JISBD/2023/7321. ', strip_tags($data[0]->toHTML())); 964 | } 965 | 966 | 967 | function test_keyword() { 968 | bibtexbrowser_configure('BIBLIOGRAPHYSTYLE','DefaultBibliographyStyle'); 969 | $bibtex = "@misc{doe2004,title={foo bar title}, publisher={publisher}, howpublished={howpublished}} @misc{doe2,title={baz}, keywords={bar}, howpublished={howpublished}}"; 970 | $test_data = fopen('php://memory','x+'); 971 | fwrite($test_data, $bibtex); 972 | fseek($test_data,0); 973 | $db = new BibDataBase(); 974 | $db->update_internal("inline", $test_data); 975 | // print_r($db); 976 | 977 | // no keyword 978 | $entry = array_values($db->bibdb)[0]; 979 | $entry->addKeyword("foo"); 980 | $this->assertEquals('foo', $entry->getField("keywords")); 981 | 982 | // already one keyword 983 | $entry = array_values($db->bibdb)[1]; 984 | $entry->addKeyword("foo"); 985 | $this->assertEquals('bar;foo', $entry->getField("keywords")); 986 | 987 | } 988 | 989 | public function testYearDisplay() { 990 | // Create test entries 991 | $entry2020 = new RawBibEntry(); 992 | $entry2020->setField('year', '2020'); 993 | $entry2020->setField('title', 'Paper 2020'); 994 | $entry2020->setField('author', 'Author A'); 995 | 996 | // assert getKey 997 | $this->assertEquals('97c46f8bdf428ce28cfa05cdedba2ec1', $entry2020->getKey()); 998 | 999 | $entry2019a = new RawBibEntry(); 1000 | $entry2019a->setField('year', '2019'); 1001 | $entry2019a->setField('title', 'Paper 2019 A'); 1002 | $entry2019a->setField('author', 'Author B'); 1003 | 1004 | $entry2019b = new RawBibEntry(); 1005 | $entry2019b->setField('year', '2019'); 1006 | $entry2019b->setField('title', 'Paper 2019 B'); 1007 | $entry2019b->setField('author', 'Author C'); 1008 | 1009 | // Create YearDisplay 1010 | $display = new YearDisplay(); 1011 | 1012 | // Set test entries 1013 | $entries = array( 1014 | 'key2020' => $entry2020, 1015 | 'key2019a' => $entry2019a, 1016 | 'key2019b' => $entry2019b 1017 | ); 1018 | $display->setEntries($entries); 1019 | 1020 | // Get year index and verify 1021 | $yearIndex = $display->yearIndex; 1022 | $this->assertEquals("2020", $yearIndex[2020]); 1023 | 1024 | // Capture output 1025 | ob_start(); 1026 | $display->display(); 1027 | $output = ob_get_clean(); 1028 | 1029 | // Verify output contains years and titles 1030 | // split output by line 1031 | $lines = explode("\n", $output); 1032 | $this->assertEquals('
2020
', $lines[0]); 1033 | } 1034 | 1035 | public function testXMLPrettyPrinter() { 1036 | // Create sample BibTeX entry with various fields to test 1037 | $bibtex = "@article{test2023, 1038 | author = {Test Author}, 1039 | title = {A Test Title with Special Characters: & < >}, 1040 | journal = {Test Journal}, 1041 | year = {2023}, 1042 | volume = {1}, 1043 | number = {2}, 1044 | pages = {100--200} 1045 | }"; 1046 | 1047 | // Set up input stream with BibTeX content 1048 | $stream = fopen('php://memory', 'r+'); 1049 | fwrite($stream, $bibtex); 1050 | rewind($stream); 1051 | 1052 | // Create XMLPrettyPrinter and parse 1053 | $printer = new XMLPrettyPrinter(); 1054 | $printer->header = false; 1055 | $parser = new StateBasedBibtexParser($printer); 1056 | 1057 | // Capture output 1058 | ob_start(); 1059 | $parser->parse($stream); 1060 | $output = ob_get_clean(); 1061 | 1062 | // Verify XML structure and content 1063 | $this->assertStringContainsString('assertStringContainsString('', $output); 1065 | $this->assertStringContainsString('', $output); 1066 | 1067 | // Verify entry type 1068 | $this->assertStringContainsString('article', $output); 1069 | 1070 | // Verify fields are present 1071 | $this->assertStringContainsString('author', $output); 1072 | $this->assertStringContainsString('Test Author', $output); 1073 | 1074 | // Verify special characters are escaped 1075 | $this->assertStringContainsString('&', $output); 1076 | $this->assertStringContainsString('<', $output); 1077 | $this->assertStringContainsString('>', $output); 1078 | 1079 | fclose($stream); 1080 | } 1081 | 1082 | public function testBibtexDisplay() { 1083 | // Create test entries 1084 | $entry1 = new RawBibEntry(); 1085 | $entry1->setType('article'); 1086 | $entry1->setField('title', 'Test Title'); 1087 | $entry1->setField('author', 'Test Author'); 1088 | $entry1->setField('year', '2023'); 1089 | $entry1->setField('journal', 'Test Journal'); 1090 | 1091 | $entry2 = new RawBibEntry(); 1092 | $entry2->setType('inproceedings'); 1093 | $entry2->setField('title', 'Another Title with Special Chars: é'); 1094 | $entry2->setField('author', 'Another Author'); 1095 | $entry2->setField('year', '2022'); 1096 | $entry2->setField('booktitle', 'Test Conference'); 1097 | 1098 | // Create BibtexDisplay instance 1099 | $display = new BibtexDisplay(); 1100 | $display->header = false; 1101 | $display->setTitle('Test Export'); 1102 | $display->setEntries(array($entry1, $entry2)); 1103 | 1104 | // assert entries in $display 1105 | $this->assertEquals(2, count($display->entries)); 1106 | 1107 | // set BIBTEXBROWSER_BIBTEX_VIEW to reconstructed 1108 | bibtexbrowser_configure('BIBTEXBROWSER_BIBTEX_VIEW', 'reconstructed'); 1109 | 1110 | // Capture output 1111 | ob_start(); 1112 | $display->display(); 1113 | $output = ob_get_clean(); 1114 | 1115 | // Verify output contains expected elements 1116 | // Header comments 1117 | $this->assertStringContainsString('% generated by bibtexbrowser', $output); 1118 | $this->assertStringContainsString('% Test Export', $output); 1119 | $this->assertStringContainsString('% Encoding: UTF-8', $output); 1120 | 1121 | // Entry 1 content 1122 | $this->assertStringContainsString('@article{', $output); 1123 | $this->assertStringContainsString('title = {Test Title}', $output); 1124 | $this->assertStringContainsString('author = {Test Author}', $output); 1125 | $this->assertStringContainsString('year = {2023}', $output); 1126 | $this->assertStringContainsString('journal = {Test Journal}', $output); 1127 | 1128 | // Entry 2 content 1129 | $this->assertStringContainsString('@inproceedings{', $output); 1130 | $this->assertStringContainsString('title = {Another Title with Special Chars: é}', $output); 1131 | $this->assertStringContainsString('author = {Another Author}', $output); 1132 | $this->assertStringContainsString('year = {2022}', $output); 1133 | $this->assertStringContainsString('booktitle = {Test Conference}', $output); 1134 | 1135 | } 1136 | 1137 | public function testCreateBibEntryDisplay() { 1138 | // Test instance creation 1139 | $display = createBibEntryDisplay(); 1140 | $this->assertInstanceOf('BibEntryDisplay', $display); 1141 | 1142 | // Create test entry 1143 | $entry = new RawBibEntry(); 1144 | $entry->setType('article'); 1145 | $entry->setField('title', 'Test Title'); 1146 | $entry->setField('author', 'Test Author'); 1147 | $entry->setField('year', '2023'); 1148 | $entry->setField('journal', 'Test Journal'); 1149 | $entry->setField('abstract', 'Test Abstract'); 1150 | $entry->setField('url', 'http://example.com'); 1151 | 1152 | // assertion on toString 1153 | $this->assertEquals('article 4a9ba73904f4f22a7b37e18750ee5454', $entry->__toString()); 1154 | 1155 | // Test display with entry 1156 | $display->setEntries(array($entry)); 1157 | 1158 | // Capture output 1159 | ob_start(); 1160 | $display->display(); 1161 | $output = ob_get_clean(); 1162 | 1163 | // Verify display output contains expected elements 1164 | $this->assertStringContainsString('Test Title', $output); 1165 | $this->assertStringContainsString('Test Author', $output); 1166 | $this->assertStringContainsString('Test Journal', $output); 1167 | $this->assertStringContainsString('Test Abstract', $output); 1168 | 1169 | // Test metadata generation 1170 | $metadata = $display->metadata(); 1171 | $this->assertIsArray($metadata); 1172 | 1173 | // Verify metadata contains essential fields 1174 | $foundTitle = false; 1175 | $foundAuthor = false; 1176 | foreach($metadata as $meta) { 1177 | if($meta[0] == 'citation_title' && $meta[1] == 'Test Title') { 1178 | $foundTitle = true; 1179 | } 1180 | if($meta[0] == 'citation_author' && $meta[1] == 'Author, Test') { 1181 | $foundAuthor = true; 1182 | } 1183 | } 1184 | $this->assertTrue($foundTitle); 1185 | $this->assertTrue($foundAuthor); 1186 | 1187 | // Test title generation 1188 | $this->assertEquals('Test Title (bibtex)', $display->getTitle()); 1189 | } 1190 | 1191 | public function testParserDelegate() { 1192 | // Create test delegate 1193 | $delegate = new TestParserDelegate(); 1194 | 1195 | // Create parser with delegate 1196 | $parser = new StateBasedBibtexParser($delegate); 1197 | 1198 | // Create test bibtex content 1199 | $bibtex = "@article{test2023, 1200 | author = {Test Author}, 1201 | title = {Test Title}, 1202 | journal = {Test Journal}, 1203 | year = {2023}, 1204 | abstract = {Test Abstract} 1205 | }"; 1206 | 1207 | // Create memory stream with test content 1208 | $stream = fopen('php://memory', 'r+'); 1209 | fwrite($stream, $bibtex); 1210 | rewind($stream); 1211 | 1212 | // Parse the content 1213 | $parser->parse($stream); 1214 | 1215 | // Verify event sequence 1216 | $expected = array( 1217 | 'beginFile', 1218 | 'beginEntry', 1219 | 'setEntryType:article', 1220 | 'setEntryKey:test2023', 1221 | 'setEntryField:author:Test Author', 1222 | 'setEntryField:title:Test Title', 1223 | 'setEntryField:journal:Test Journal', 1224 | 'setEntryField:year:2023', 1225 | 'setEntryField:abstract:Test Abstract', 1226 | 'endEntry', 1227 | 'endFile' 1228 | ); 1229 | 1230 | $this->assertEquals($expected, $delegate->events); 1231 | 1232 | fclose($stream); 1233 | } 1234 | 1235 | public function testRSSDisplay() { 1236 | // Create test entries with various data to test RSS generation 1237 | $entry1 = new RawBibEntry(); 1238 | $entry1->setType('article'); 1239 | $entry1->setField('title', 'Test Title with Special Chars: & < >'); 1240 | $entry1->setField('author', 'Test Author'); 1241 | $entry1->setField('year', '2023'); 1242 | $entry1->setField('journal', 'Test Journal'); 1243 | $entry1->setField('abstract', 'Test Abstract with HTML tags'); 1244 | $entry1->setField('url', 'http://example.com'); 1245 | 1246 | $entry2 = new RawBibEntry(); 1247 | $entry2->setType('inproceedings'); 1248 | $entry2->setField('title', 'Another Test Title'); 1249 | $entry2->setField('author', 'Another Author'); 1250 | $entry2->setField('year', '2022'); 1251 | $entry2->setField('booktitle', 'Test Conference'); 1252 | 1253 | // Create RSSDisplay instance 1254 | $display = new RSSDisplay(); 1255 | $display->header = false; 1256 | $display->setTitle('Test RSS Feed'); 1257 | $display->setEntries(array($entry1, $entry2)); 1258 | 1259 | // Capture output 1260 | ob_start(); 1261 | $display->display(); 1262 | $output = ob_get_clean(); 1263 | 1264 | // Verify XML declaration 1265 | $this->assertStringContainsString('', $output); 1266 | 1267 | // Verify RSS structure 1268 | $this->assertStringContainsString('assertStringContainsString('', $output); 1270 | $this->assertStringContainsString('Test RSS Feed', $output); 1271 | 1272 | // Verify entries 1273 | $this->assertStringContainsString('', $output); 1274 | $this->assertStringContainsString('Test Title with Special Chars: & < >', $output); 1275 | $this->assertStringContainsString('Another Test Title', $output); 1276 | 1277 | // Verify text encoding 1278 | $rss = $display->text2rss('Test & Text bold with HTML é'); 1279 | $this->assertEquals('Test & Text bold with HTML ', $rss); 1280 | 1281 | // Verify metadata handling 1282 | $this->assertStringContainsString('', $output); 1283 | $this->assertStringContainsString('', $output); 1284 | $this->assertStringContainsString('assertInstanceOf('SimpleXMLElement', $xml); 1289 | } 1290 | 1291 | public function testHTMLTemplate() { 1292 | // Create mock content object that implements required methods 1293 | $mockContent = new class { 1294 | public function display() { 1295 | echo '
Test Content
'; 1296 | } 1297 | 1298 | public function getTitle() { 1299 | return 'Test Title'; 1300 | } 1301 | 1302 | public function metadata() { 1303 | return array( 1304 | array('description', 'Test Description'), 1305 | array('keywords', 'test, bibtex') 1306 | ); 1307 | } 1308 | }; 1309 | 1310 | // Capture output 1311 | bibtexbrowser_configure('BIBTEXBROWSER_USE_PROGRESSIVE_ENHANCEMENT', true); 1312 | ob_start(); 1313 | HTMLTemplate($mockContent, false); 1314 | $output = ob_get_clean(); 1315 | 1316 | // Verify basic HTML structure 1317 | $this->assertStringContainsString('assertStringContainsString('', $output); 1319 | $this->assertStringContainsString('', $output); 1320 | 1321 | // Verify HEAD section 1322 | $this->assertStringContainsString('assertStringContainsString('assertStringContainsString('Test Title', $output); 1331 | 1332 | // Verify CSS inclusion 1333 | $this->assertStringContainsString('