3 namespace Shaarli\Bookmark
;
5 use malkusch\lock\mutex\Mutex
;
6 use malkusch\lock\mutex\NoMutex
;
7 use Shaarli\Bookmark\Exception\DatastoreNotInitializedException
;
8 use Shaarli\Bookmark\Exception\EmptyDataStoreException
;
9 use Shaarli\Bookmark\Exception\NotWritableDataStoreException
;
10 use Shaarli\Config\ConfigManager
;
15 * This class performs read/write operation to the file data store.
16 * Used by BookmarkFileService.
18 * @package Shaarli\Bookmark
23 * @var string Datastore file path
28 * @var ConfigManager instance
37 * string Datastore PHP prefix
39 protected static $phpPrefix = '<?php /* ';
41 * string Datastore PHP suffix
43 protected static $phpSuffix = ' */ ?>';
46 * LinksIO constructor.
48 * @param ConfigManager $conf instance
50 public function __construct(ConfigManager
$conf, Mutex
$mutex = null)
52 if ($mutex === null) {
53 // This should only happen with legacy classes
54 $mutex = new NoMutex();
57 $this->datastore
= $conf->get('resource.datastore');
58 $this->mutex
= $mutex;
62 * Reads database from disk to memory
64 * @return BookmarkArray instance
66 * @throws NotWritableDataStoreException Data couldn't be loaded
67 * @throws EmptyDataStoreException Datastore file exists but does not contain any bookmark
68 * @throws DatastoreNotInitializedException File does not exists
70 public function read()
72 if (! file_exists($this->datastore
)) {
73 throw new DatastoreNotInitializedException();
76 if (!is_writable($this->datastore
)) {
77 throw new NotWritableDataStoreException($this->datastore
);
81 $this->mutex
->synchronized(function () use (&$content) {
82 $content = file_get_contents($this->datastore
);
85 // Note that gzinflate is faster than gzuncompress.
86 // See: http://www.php.net/manual/en/function.gzdeflate.php#96439
87 $links = unserialize(gzinflate(base64_decode(
88 substr($content, strlen(self
::$phpPrefix), -strlen(self
::$phpSuffix))
92 if (filesize($this->datastore
) > 100) {
93 throw new NotWritableDataStoreException($this->datastore
);
95 throw new EmptyDataStoreException();
102 * Saves the database from memory to disk
104 * @param BookmarkArray $links instance.
106 * @throws NotWritableDataStoreException the datastore is not writable
108 public function write($links)
110 if (is_file($this->datastore
) && !is_writeable($this->datastore
)) {
111 // The datastore exists but is not writeable
112 throw new NotWritableDataStoreException($this->datastore
);
113 } else if (!is_file($this->datastore
) && !is_writeable(dirname($this->datastore
))) {
114 // The datastore does not exist and its parent directory is not writeable
115 throw new NotWritableDataStoreException(dirname($this->datastore
));
118 $data = self
::$phpPrefix.base64_encode(gzdeflate(serialize($links))).self
::$phpSuffix;
120 $this->mutex
->synchronized(function () use ($data) {