2019-05-25 15:46:47 +02:00
|
|
|
<?php
|
|
|
|
|
|
|
|
namespace Shaarli\Bookmark;
|
|
|
|
|
2020-08-01 11:10:57 +02:00
|
|
|
use Shaarli\Bookmark\Exception\DatastoreNotInitializedException;
|
2019-05-25 15:46:47 +02:00
|
|
|
use Shaarli\Bookmark\Exception\EmptyDataStoreException;
|
|
|
|
use Shaarli\Bookmark\Exception\NotWritableDataStoreException;
|
|
|
|
use Shaarli\Config\ConfigManager;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Class BookmarkIO
|
|
|
|
*
|
|
|
|
* This class performs read/write operation to the file data store.
|
|
|
|
* Used by BookmarkFileService.
|
|
|
|
*
|
|
|
|
* @package Shaarli\Bookmark
|
|
|
|
*/
|
|
|
|
class BookmarkIO
|
|
|
|
{
|
|
|
|
/**
|
|
|
|
* @var string Datastore file path
|
|
|
|
*/
|
|
|
|
protected $datastore;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @var ConfigManager instance
|
|
|
|
*/
|
|
|
|
protected $conf;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* string Datastore PHP prefix
|
|
|
|
*/
|
|
|
|
protected static $phpPrefix = '<?php /* ';
|
|
|
|
|
|
|
|
/**
|
|
|
|
* string Datastore PHP suffix
|
|
|
|
*/
|
|
|
|
protected static $phpSuffix = ' */ ?>';
|
|
|
|
|
|
|
|
/**
|
|
|
|
* LinksIO constructor.
|
|
|
|
*
|
|
|
|
* @param ConfigManager $conf instance
|
|
|
|
*/
|
|
|
|
public function __construct($conf)
|
|
|
|
{
|
|
|
|
$this->conf = $conf;
|
|
|
|
$this->datastore = $conf->get('resource.datastore');
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Reads database from disk to memory
|
|
|
|
*
|
|
|
|
* @return BookmarkArray instance
|
|
|
|
*
|
2020-08-01 11:10:57 +02:00
|
|
|
* @throws NotWritableDataStoreException Data couldn't be loaded
|
|
|
|
* @throws EmptyDataStoreException Datastore file exists but does not contain any bookmark
|
|
|
|
* @throws DatastoreNotInitializedException File does not exists
|
2019-05-25 15:46:47 +02:00
|
|
|
*/
|
|
|
|
public function read()
|
|
|
|
{
|
|
|
|
if (! file_exists($this->datastore)) {
|
2020-08-01 11:10:57 +02:00
|
|
|
throw new DatastoreNotInitializedException();
|
2019-05-25 15:46:47 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
if (!is_writable($this->datastore)) {
|
|
|
|
throw new NotWritableDataStoreException($this->datastore);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Note that gzinflate is faster than gzuncompress.
|
|
|
|
// See: http://www.php.net/manual/en/function.gzdeflate.php#96439
|
|
|
|
$links = unserialize(gzinflate(base64_decode(
|
|
|
|
substr(file_get_contents($this->datastore),
|
|
|
|
strlen(self::$phpPrefix), -strlen(self::$phpSuffix)))));
|
|
|
|
|
|
|
|
if (empty($links)) {
|
|
|
|
if (filesize($this->datastore) > 100) {
|
|
|
|
throw new NotWritableDataStoreException($this->datastore);
|
|
|
|
}
|
|
|
|
throw new EmptyDataStoreException();
|
|
|
|
}
|
|
|
|
|
|
|
|
return $links;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Saves the database from memory to disk
|
|
|
|
*
|
|
|
|
* @param BookmarkArray $links instance.
|
|
|
|
*
|
|
|
|
* @throws NotWritableDataStoreException the datastore is not writable
|
|
|
|
*/
|
|
|
|
public function write($links)
|
|
|
|
{
|
|
|
|
if (is_file($this->datastore) && !is_writeable($this->datastore)) {
|
|
|
|
// The datastore exists but is not writeable
|
|
|
|
throw new NotWritableDataStoreException($this->datastore);
|
|
|
|
} else if (!is_file($this->datastore) && !is_writeable(dirname($this->datastore))) {
|
|
|
|
// The datastore does not exist and its parent directory is not writeable
|
|
|
|
throw new NotWritableDataStoreException(dirname($this->datastore));
|
|
|
|
}
|
|
|
|
|
|
|
|
file_put_contents(
|
|
|
|
$this->datastore,
|
|
|
|
self::$phpPrefix.base64_encode(gzdeflate(serialize($links))).self::$phpSuffix
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|