LinkDB: move to a proper file, add test coverage
Relates to #71 LinkDB - move to application/LinkDB.php - code cleanup - indentation - whitespaces - formatting - comment cleanup - add missing documentation - unify formatting Test coverage for LinkDB - constructor - public / private access - link-related methods Shaarli utilities (LinkDB dependencies) - move startsWith() and endsWith() functions to application/Utils.php - add test coverage Dev utilities - Composer: add PHPUnit to dev dependencies - Makefile: - update lint targets - add test targets - generate coverage reports Signed-off-by: VirtualTam <virtualtam@flibidi.net>
This commit is contained in:
parent
cbecab7735
commit
ca74886f30
12 changed files with 1231 additions and 257 deletions
2
tests/.htaccess
Normal file
2
tests/.htaccess
Normal file
|
@ -0,0 +1,2 @@
|
|||
Allow from none
|
||||
Deny from all
|
509
tests/LinkDBTest.php
Normal file
509
tests/LinkDBTest.php
Normal file
|
@ -0,0 +1,509 @@
|
|||
<?php
|
||||
/**
|
||||
* Link datastore tests
|
||||
*/
|
||||
|
||||
require_once 'application/LinkDB.php';
|
||||
require_once 'application/Utils.php';
|
||||
require_once 'tests/utils/ReferenceLinkDB.php';
|
||||
|
||||
define('PHPPREFIX', '<?php /* ');
|
||||
define('PHPSUFFIX', ' */ ?>');
|
||||
|
||||
|
||||
/**
|
||||
* Unitary tests for LinkDB
|
||||
*/
|
||||
class LinkDBTest extends PHPUnit_Framework_TestCase
|
||||
{
|
||||
// datastore to test write operations
|
||||
protected static $testDatastore = 'tests/datastore.php';
|
||||
protected static $dummyDatastoreSHA1 = 'e3edea8ea7bb50be4bcb404df53fbb4546a7156e';
|
||||
protected static $refDB = null;
|
||||
protected static $publicLinkDB = null;
|
||||
protected static $privateLinkDB = null;
|
||||
|
||||
/**
|
||||
* Instantiates public and private LinkDBs with test data
|
||||
*
|
||||
* The reference datastore contains public and private links that
|
||||
* will be used to test LinkDB's methods:
|
||||
* - access filtering (public/private),
|
||||
* - link searches:
|
||||
* - by day,
|
||||
* - by tag,
|
||||
* - by text,
|
||||
* - etc.
|
||||
*/
|
||||
public static function setUpBeforeClass()
|
||||
{
|
||||
self::$refDB = new ReferenceLinkDB();
|
||||
self::$refDB->write(self::$testDatastore, PHPPREFIX, PHPSUFFIX);
|
||||
|
||||
$GLOBALS['config']['DATASTORE'] = self::$testDatastore;
|
||||
self::$publicLinkDB = new LinkDB(false);
|
||||
self::$privateLinkDB = new LinkDB(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets test data for each test
|
||||
*/
|
||||
protected function setUp()
|
||||
{
|
||||
$GLOBALS['config']['DATASTORE'] = self::$testDatastore;
|
||||
if (file_exists(self::$testDatastore)) {
|
||||
unlink(self::$testDatastore);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows to test LinkDB's private methods
|
||||
*
|
||||
* @see
|
||||
* https://sebastian-bergmann.de/archives/881-Testing-Your-Privates.html
|
||||
* http://stackoverflow.com/a/2798203
|
||||
*/
|
||||
protected static function getMethod($name)
|
||||
{
|
||||
$class = new ReflectionClass('LinkDB');
|
||||
$method = $class->getMethod($name);
|
||||
$method->setAccessible(true);
|
||||
return $method;
|
||||
}
|
||||
|
||||
/**
|
||||
* Instantiate LinkDB objects - logged in user
|
||||
*/
|
||||
public function testConstructLoggedIn()
|
||||
{
|
||||
new LinkDB(true);
|
||||
$this->assertFileExists(self::$testDatastore);
|
||||
}
|
||||
|
||||
/**
|
||||
* Instantiate LinkDB objects - logged out or public instance
|
||||
*/
|
||||
public function testConstructLoggedOut()
|
||||
{
|
||||
new LinkDB(false);
|
||||
$this->assertFileExists(self::$testDatastore);
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempt to instantiate a LinkDB whereas the datastore is not writable
|
||||
*
|
||||
* @expectedException PHPUnit_Framework_Error_Warning
|
||||
* @expectedExceptionMessageRegExp /failed to open stream: No such file or directory/
|
||||
*/
|
||||
public function testConstructDatastoreNotWriteable()
|
||||
{
|
||||
$GLOBALS['config']['DATASTORE'] = 'null/store.db';
|
||||
new LinkDB(false);
|
||||
}
|
||||
|
||||
/**
|
||||
* The DB doesn't exist, ensure it is created with dummy content
|
||||
*/
|
||||
public function testCheckDBNew()
|
||||
{
|
||||
$linkDB = new LinkDB(false);
|
||||
unlink(self::$testDatastore);
|
||||
$this->assertFileNotExists(self::$testDatastore);
|
||||
|
||||
$checkDB = self::getMethod('checkDB');
|
||||
$checkDB->invokeArgs($linkDB, array());
|
||||
$this->assertFileExists(self::$testDatastore);
|
||||
|
||||
// ensure the correct data has been written
|
||||
$this->assertEquals(
|
||||
self::$dummyDatastoreSHA1,
|
||||
sha1_file(self::$testDatastore)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* The DB exists, don't do anything
|
||||
*/
|
||||
public function testCheckDBLoad()
|
||||
{
|
||||
$linkDB = new LinkDB(false);
|
||||
$this->assertEquals(
|
||||
self::$dummyDatastoreSHA1,
|
||||
sha1_file(self::$testDatastore)
|
||||
);
|
||||
|
||||
$checkDB = self::getMethod('checkDB');
|
||||
$checkDB->invokeArgs($linkDB, array());
|
||||
|
||||
// ensure the datastore is left unmodified
|
||||
$this->assertEquals(
|
||||
self::$dummyDatastoreSHA1,
|
||||
sha1_file(self::$testDatastore)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Load an empty DB
|
||||
*/
|
||||
public function testReadEmptyDB()
|
||||
{
|
||||
file_put_contents(self::$testDatastore, PHPPREFIX.'S7QysKquBQA='.PHPSUFFIX);
|
||||
$emptyDB = new LinkDB(false);
|
||||
$this->assertEquals(0, sizeof($emptyDB));
|
||||
$this->assertEquals(0, count($emptyDB));
|
||||
}
|
||||
|
||||
/**
|
||||
* Load public links from the DB
|
||||
*/
|
||||
public function testReadPublicDB()
|
||||
{
|
||||
$this->assertEquals(
|
||||
self::$refDB->countPublicLinks(),
|
||||
sizeof(self::$publicLinkDB)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Load public and private links from the DB
|
||||
*/
|
||||
public function testReadPrivateDB()
|
||||
{
|
||||
$this->assertEquals(
|
||||
self::$refDB->countLinks(),
|
||||
sizeof(self::$privateLinkDB)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Save the links to the DB
|
||||
*/
|
||||
public function testSaveDB()
|
||||
{
|
||||
$testDB = new LinkDB(true);
|
||||
$dbSize = sizeof($testDB);
|
||||
|
||||
$link = array(
|
||||
'title'=>'an additional link',
|
||||
'url'=>'http://dum.my',
|
||||
'description'=>'One more',
|
||||
'private'=>0,
|
||||
'linkdate'=>'20150518_190000',
|
||||
'tags'=>'unit test'
|
||||
);
|
||||
$testDB[$link['linkdate']] = $link;
|
||||
|
||||
// TODO: move PageCache to a proper class/file
|
||||
function invalidateCaches() {}
|
||||
|
||||
$testDB->savedb();
|
||||
|
||||
$testDB = new LinkDB(true);
|
||||
$this->assertEquals($dbSize + 1, sizeof($testDB));
|
||||
}
|
||||
|
||||
/**
|
||||
* Count existing links
|
||||
*/
|
||||
public function testCount()
|
||||
{
|
||||
$this->assertEquals(
|
||||
self::$refDB->countPublicLinks(),
|
||||
self::$publicLinkDB->count()
|
||||
);
|
||||
$this->assertEquals(
|
||||
self::$refDB->countLinks(),
|
||||
self::$privateLinkDB->count()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* List the days for which links have been posted
|
||||
*/
|
||||
public function testDays()
|
||||
{
|
||||
$this->assertEquals(
|
||||
['20121206', '20130614', '20150310'],
|
||||
self::$publicLinkDB->days()
|
||||
);
|
||||
|
||||
$this->assertEquals(
|
||||
['20121206', '20130614', '20141125', '20150310'],
|
||||
self::$privateLinkDB->days()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* The URL corresponds to an existing entry in the DB
|
||||
*/
|
||||
public function testGetKnownLinkFromURL()
|
||||
{
|
||||
$link = self::$publicLinkDB->getLinkFromUrl('http://mediagoblin.org/');
|
||||
|
||||
$this->assertNotEquals(false, $link);
|
||||
$this->assertEquals(
|
||||
'A free software media publishing platform',
|
||||
$link['description']
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* The URL is not in the DB
|
||||
*/
|
||||
public function testGetUnknownLinkFromURL()
|
||||
{
|
||||
$this->assertEquals(
|
||||
false,
|
||||
self::$publicLinkDB->getLinkFromUrl('http://dev.null')
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Lists all tags
|
||||
*/
|
||||
public function testAllTags()
|
||||
{
|
||||
$this->assertEquals(
|
||||
[
|
||||
'web' => 3,
|
||||
'cartoon' => 2,
|
||||
'gnu' => 2,
|
||||
'dev' => 1,
|
||||
'samba' => 1,
|
||||
'media' => 1,
|
||||
'software' => 1,
|
||||
'stallman' => 1,
|
||||
'free' => 1
|
||||
],
|
||||
self::$publicLinkDB->allTags()
|
||||
);
|
||||
|
||||
$this->assertEquals(
|
||||
[
|
||||
'web' => 4,
|
||||
'cartoon' => 3,
|
||||
'gnu' => 2,
|
||||
'dev' => 2,
|
||||
'samba' => 1,
|
||||
'media' => 1,
|
||||
'software' => 1,
|
||||
'stallman' => 1,
|
||||
'free' => 1,
|
||||
'html' => 1,
|
||||
'w3c' => 1,
|
||||
'css' => 1,
|
||||
'Mercurial' => 1
|
||||
],
|
||||
self::$privateLinkDB->allTags()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Filter links using a tag
|
||||
*/
|
||||
public function testFilterOneTag()
|
||||
{
|
||||
$this->assertEquals(
|
||||
3,
|
||||
sizeof(self::$publicLinkDB->filterTags('web', false))
|
||||
);
|
||||
|
||||
$this->assertEquals(
|
||||
4,
|
||||
sizeof(self::$privateLinkDB->filterTags('web', false))
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Filter links using a tag - case-sensitive
|
||||
*/
|
||||
public function testFilterCaseSensitiveTag()
|
||||
{
|
||||
$this->assertEquals(
|
||||
0,
|
||||
sizeof(self::$privateLinkDB->filterTags('mercurial', true))
|
||||
);
|
||||
|
||||
$this->assertEquals(
|
||||
1,
|
||||
sizeof(self::$privateLinkDB->filterTags('Mercurial', true))
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Filter links using a tag combination
|
||||
*/
|
||||
public function testFilterMultipleTags()
|
||||
{
|
||||
$this->assertEquals(
|
||||
1,
|
||||
sizeof(self::$publicLinkDB->filterTags('dev cartoon', false))
|
||||
);
|
||||
|
||||
$this->assertEquals(
|
||||
2,
|
||||
sizeof(self::$privateLinkDB->filterTags('dev cartoon', false))
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Filter links using a non-existent tag
|
||||
*/
|
||||
public function testFilterUnknownTag()
|
||||
{
|
||||
$this->assertEquals(
|
||||
0,
|
||||
sizeof(self::$publicLinkDB->filterTags('null', false))
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return links for a given day
|
||||
*/
|
||||
public function testFilterDay()
|
||||
{
|
||||
$this->assertEquals(
|
||||
2,
|
||||
sizeof(self::$publicLinkDB->filterDay('20121206'))
|
||||
);
|
||||
|
||||
$this->assertEquals(
|
||||
3,
|
||||
sizeof(self::$privateLinkDB->filterDay('20121206'))
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* 404 - day not found
|
||||
*/
|
||||
public function testFilterUnknownDay()
|
||||
{
|
||||
$this->assertEquals(
|
||||
0,
|
||||
sizeof(self::$publicLinkDB->filterDay('19700101'))
|
||||
);
|
||||
|
||||
$this->assertEquals(
|
||||
0,
|
||||
sizeof(self::$privateLinkDB->filterDay('19700101'))
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Use an invalid date format
|
||||
*/
|
||||
public function testFilterInvalidDay()
|
||||
{
|
||||
$this->assertEquals(
|
||||
0,
|
||||
sizeof(self::$privateLinkDB->filterDay('Rainy day, dream away'))
|
||||
);
|
||||
|
||||
// TODO: check input format
|
||||
$this->assertEquals(
|
||||
6,
|
||||
sizeof(self::$privateLinkDB->filterDay('20'))
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve a link entry with its hash
|
||||
*/
|
||||
public function testFilterSmallHash()
|
||||
{
|
||||
$links = self::$privateLinkDB->filterSmallHash('IuWvgA');
|
||||
|
||||
$this->assertEquals(
|
||||
1,
|
||||
sizeof($links)
|
||||
);
|
||||
|
||||
$this->assertEquals(
|
||||
'MediaGoblin',
|
||||
$links['20130614_184135']['title']
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* No link for this hash
|
||||
*/
|
||||
public function testFilterUnknownSmallHash()
|
||||
{
|
||||
$this->assertEquals(
|
||||
0,
|
||||
sizeof(self::$privateLinkDB->filterSmallHash('Iblaah'))
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Full-text search - result from a link's URL
|
||||
*/
|
||||
public function testFilterFullTextURL()
|
||||
{
|
||||
$this->assertEquals(
|
||||
2,
|
||||
sizeof(self::$publicLinkDB->filterFullText('ars.userfriendly.org'))
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Full-text search - result from a link's title only
|
||||
*/
|
||||
public function testFilterFullTextTitle()
|
||||
{
|
||||
// use miscellaneous cases
|
||||
$this->assertEquals(
|
||||
2,
|
||||
sizeof(self::$publicLinkDB->filterFullText('userfriendly -'))
|
||||
);
|
||||
$this->assertEquals(
|
||||
2,
|
||||
sizeof(self::$publicLinkDB->filterFullText('UserFriendly -'))
|
||||
);
|
||||
$this->assertEquals(
|
||||
2,
|
||||
sizeof(self::$publicLinkDB->filterFullText('uSeRFrIendlY -'))
|
||||
);
|
||||
|
||||
// use miscellaneous case and offset
|
||||
$this->assertEquals(
|
||||
2,
|
||||
sizeof(self::$publicLinkDB->filterFullText('RFrIendL'))
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Full-text search - result from the link's description only
|
||||
*/
|
||||
public function testFilterFullTextDescription()
|
||||
{
|
||||
$this->assertEquals(
|
||||
1,
|
||||
sizeof(self::$publicLinkDB->filterFullText('media publishing'))
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Full-text search - result from the link's tags only
|
||||
*/
|
||||
public function testFilterFullTextTags()
|
||||
{
|
||||
$this->assertEquals(
|
||||
2,
|
||||
sizeof(self::$publicLinkDB->filterFullText('gnu'))
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Full-text search - result set from mixed sources
|
||||
*/
|
||||
public function testFilterFullTextMixed()
|
||||
{
|
||||
$this->assertEquals(
|
||||
2,
|
||||
sizeof(self::$publicLinkDB->filterFullText('free software'))
|
||||
);
|
||||
}
|
||||
}
|
||||
?>
|
78
tests/UtilsTest.php
Normal file
78
tests/UtilsTest.php
Normal file
|
@ -0,0 +1,78 @@
|
|||
<?php
|
||||
/**
|
||||
* Utilities' tests
|
||||
*/
|
||||
|
||||
require_once 'application/Utils.php';
|
||||
|
||||
/**
|
||||
* Unitary tests for Shaarli utilities
|
||||
*/
|
||||
class UtilsTest extends PHPUnit_Framework_TestCase
|
||||
{
|
||||
/**
|
||||
* Represent a link by its hash
|
||||
*/
|
||||
public function testSmallHash()
|
||||
{
|
||||
$this->assertEquals('CyAAJw', smallHash('http://test.io'));
|
||||
$this->assertEquals(6, strlen(smallHash('https://github.com')));
|
||||
}
|
||||
|
||||
/**
|
||||
* Look for a substring at the beginning of a string
|
||||
*/
|
||||
public function testStartsWithCaseInsensitive()
|
||||
{
|
||||
$this->assertTrue(startsWith('Lorem ipsum', 'lorem', false));
|
||||
$this->assertTrue(startsWith('Lorem ipsum', 'LoReM i', false));
|
||||
}
|
||||
|
||||
/**
|
||||
* Look for a substring at the beginning of a string (case-sensitive)
|
||||
*/
|
||||
public function testStartsWithCaseSensitive()
|
||||
{
|
||||
$this->assertTrue(startsWith('Lorem ipsum', 'Lorem', true));
|
||||
$this->assertFalse(startsWith('Lorem ipsum', 'lorem', true));
|
||||
$this->assertFalse(startsWith('Lorem ipsum', 'LoReM i', true));
|
||||
}
|
||||
|
||||
/**
|
||||
* Look for a substring at the beginning of a string (Unicode)
|
||||
*/
|
||||
public function testStartsWithSpecialChars()
|
||||
{
|
||||
$this->assertTrue(startsWith('å!ùµ', 'å!', false));
|
||||
$this->assertTrue(startsWith('µ$åù', 'µ$', true));
|
||||
}
|
||||
|
||||
/**
|
||||
* Look for a substring at the end of a string
|
||||
*/
|
||||
public function testEndsWithCaseInsensitive()
|
||||
{
|
||||
$this->assertTrue(endsWith('Lorem ipsum', 'ipsum', false));
|
||||
$this->assertTrue(endsWith('Lorem ipsum', 'm IpsUM', false));
|
||||
}
|
||||
|
||||
/**
|
||||
* Look for a substring at the end of a string (case-sensitive)
|
||||
*/
|
||||
public function testEndsWithCaseSensitive()
|
||||
{
|
||||
$this->assertTrue(endsWith('lorem Ipsum', 'Ipsum', true));
|
||||
$this->assertFalse(endsWith('lorem Ipsum', 'ipsum', true));
|
||||
$this->assertFalse(endsWith('lorem Ipsum', 'M IPsuM', true));
|
||||
}
|
||||
|
||||
/**
|
||||
* Look for a substring at the end of a string (Unicode)
|
||||
*/
|
||||
public function testEndsWithSpecialChars()
|
||||
{
|
||||
$this->assertTrue(endsWith('å!ùµ', 'ùµ', false));
|
||||
$this->assertTrue(endsWith('µ$åù', 'åù', true));
|
||||
}
|
||||
}
|
||||
?>
|
128
tests/utils/ReferenceLinkDB.php
Normal file
128
tests/utils/ReferenceLinkDB.php
Normal file
|
@ -0,0 +1,128 @@
|
|||
<?php
|
||||
/**
|
||||
* Populates a reference datastore to test LinkDB
|
||||
*/
|
||||
class ReferenceLinkDB
|
||||
{
|
||||
private $links = array();
|
||||
private $publicCount = 0;
|
||||
private $privateCount = 0;
|
||||
|
||||
/**
|
||||
* Populates the test DB with reference data
|
||||
*/
|
||||
function __construct()
|
||||
{
|
||||
$this->addLink(
|
||||
'Free as in Freedom 2.0',
|
||||
'https://static.fsf.org/nosvn/faif-2.0.pdf',
|
||||
'Richard Stallman and the Free Software Revolution',
|
||||
0,
|
||||
'20150310_114633',
|
||||
'free gnu software stallman'
|
||||
);
|
||||
|
||||
$this->addLink(
|
||||
'MediaGoblin',
|
||||
'http://mediagoblin.org/',
|
||||
'A free software media publishing platform',
|
||||
0,
|
||||
'20130614_184135',
|
||||
'gnu media web'
|
||||
);
|
||||
|
||||
$this->addLink(
|
||||
'w3c-markup-validator',
|
||||
'https://dvcs.w3.org/hg/markup-validator/summary',
|
||||
'Mercurial repository for the W3C Validator',
|
||||
1,
|
||||
'20141125_084734',
|
||||
'css html w3c web Mercurial'
|
||||
);
|
||||
|
||||
$this->addLink(
|
||||
'UserFriendly - Web Designer',
|
||||
'http://ars.userfriendly.org/cartoons/?id=20121206',
|
||||
'Naming conventions...',
|
||||
0,
|
||||
'20121206_142300',
|
||||
'dev cartoon web'
|
||||
);
|
||||
|
||||
$this->addLink(
|
||||
'UserFriendly - Samba',
|
||||
'http://ars.userfriendly.org/cartoons/?id=20010306',
|
||||
'Tropical printing',
|
||||
0,
|
||||
'20121206_172539',
|
||||
'samba cartoon web'
|
||||
);
|
||||
|
||||
$this->addLink(
|
||||
'Geek and Poke',
|
||||
'http://geek-and-poke.com/',
|
||||
'',
|
||||
1,
|
||||
'20121206_182539',
|
||||
'dev cartoon'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a new link
|
||||
*/
|
||||
protected function addLink($title, $url, $description, $private, $date, $tags)
|
||||
{
|
||||
$link = array(
|
||||
'title' => $title,
|
||||
'url' => $url,
|
||||
'description' => $description,
|
||||
'private' => $private,
|
||||
'linkdate' => $date,
|
||||
'tags' => $tags,
|
||||
);
|
||||
$this->links[$date] = $link;
|
||||
|
||||
if ($private) {
|
||||
$this->privateCount++;
|
||||
return;
|
||||
}
|
||||
$this->publicCount++;
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes data to the datastore
|
||||
*/
|
||||
public function write($filename, $prefix, $suffix)
|
||||
{
|
||||
file_put_contents(
|
||||
$filename,
|
||||
$prefix.base64_encode(gzdeflate(serialize($this->links))).$suffix
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number of links in the reference data
|
||||
*/
|
||||
public function countLinks()
|
||||
{
|
||||
return $this->publicCount + $this->privateCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number of public links in the reference data
|
||||
*/
|
||||
public function countPublicLinks()
|
||||
{
|
||||
return $this->publicCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number of private links in the reference data
|
||||
*/
|
||||
public function countPrivateLinks()
|
||||
{
|
||||
return $this->privateCount;
|
||||
}
|
||||
}
|
||||
?>
|
Loading…
Add table
Add a link
Reference in a new issue