]> git.immae.eu Git - github/shaarli/Shaarli.git/blobdiff - application/bookmark/BookmarkIO.php
Add strict types for bookmarks management
[github/shaarli/Shaarli.git] / application / bookmark / BookmarkIO.php
index 6bf7f3654ebfdd41f87b9468f00c135c2725e9da..f40fa476247ff2fc9fd75c1048c4b7a340516b61 100644 (file)
@@ -1,7 +1,11 @@
 <?php
 
+declare(strict_types=1);
+
 namespace Shaarli\Bookmark;
 
+use malkusch\lock\mutex\Mutex;
+use malkusch\lock\mutex\NoMutex;
 use Shaarli\Bookmark\Exception\DatastoreNotInitializedException;
 use Shaarli\Bookmark\Exception\EmptyDataStoreException;
 use Shaarli\Bookmark\Exception\NotWritableDataStoreException;
@@ -27,11 +31,14 @@ class BookmarkIO
      */
     protected $conf;
 
+
+    /** @var Mutex */
+    protected $mutex;
+
     /**
      * string Datastore PHP prefix
      */
     protected static $phpPrefix = '<?php /* ';
-
     /**
      * string Datastore PHP suffix
      */
@@ -42,16 +49,21 @@ class BookmarkIO
      *
      * @param ConfigManager $conf instance
      */
-    public function __construct($conf)
+    public function __construct(ConfigManager $conf, Mutex $mutex = null)
     {
+        if ($mutex === null) {
+            // This should only happen with legacy classes
+            $mutex = new NoMutex();
+        }
         $this->conf = $conf;
         $this->datastore = $conf->get('resource.datastore');
+        $this->mutex = $mutex;
     }
 
     /**
      * Reads database from disk to memory
      *
-     * @return BookmarkArray instance
+     * @return Bookmark[]
      *
      * @throws NotWritableDataStoreException    Data couldn't be loaded
      * @throws EmptyDataStoreException          Datastore file exists but does not contain any bookmark
@@ -67,11 +79,16 @@ class BookmarkIO
             throw new NotWritableDataStoreException($this->datastore);
         }
 
+        $content = null;
+        $this->mutex->synchronized(function () use (&$content) {
+            $content = file_get_contents($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)))));
+            substr($content, strlen(self::$phpPrefix), -strlen(self::$phpSuffix))
+        )));
 
         if (empty($links)) {
             if (filesize($this->datastore) > 100) {
@@ -86,7 +103,7 @@ class BookmarkIO
     /**
      * Saves the database from memory to disk
      *
-     * @param BookmarkArray $links instance.
+     * @param Bookmark[] $links
      *
      * @throws NotWritableDataStoreException the datastore is not writable
      */
@@ -100,9 +117,13 @@ class BookmarkIO
             throw new NotWritableDataStoreException(dirname($this->datastore));
         }
 
-        file_put_contents(
-            $this->datastore,
-            self::$phpPrefix.base64_encode(gzdeflate(serialize($links))).self::$phpSuffix
-        );
+        $data = self::$phpPrefix.base64_encode(gzdeflate(serialize($links))).self::$phpSuffix;
+
+        $this->mutex->synchronized(function () use ($data) {
+            file_put_contents(
+                $this->datastore,
+                $data
+            );
+        });
     }
 }