{"action":"created","comment":{"url":"https://api.github.com/repos/webmozart/key-value-store/pulls/comments/40651163","id":40651163,"diff_hunk":"@@ -0,0 +1,305 @@\n+<?php\n+\n+/*\n+ * This file is part of the webmozart/key-value-store package.\n+ *\n+ * (c) Bernhard Schussek <bschussek@gmail.com>\n+ *\n+ * For the full copyright and license information, please view the LICENSE\n+ * file that was distributed with this source code.\n+ */\n+\n+namespace Webmozart\\KeyValueStore;\n+\n+use Doctrine\\DBAL\\Connection;\n+use Doctrine\\DBAL\\Schema\\Schema;\n+use Exception;\n+use PDO;\n+use Webmozart\\Assert\\Assert;\n+use Webmozart\\KeyValueStore\\Api\\KeyValueStore;\n+use Webmozart\\KeyValueStore\\Api\\NoSuchKeyException;\n+use Webmozart\\KeyValueStore\\Api\\ReadException;\n+use Webmozart\\KeyValueStore\\Api\\WriteException;\n+use Webmozart\\KeyValueStore\\Util\\KeyUtil;\n+use Webmozart\\KeyValueStore\\Util\\Serializer;\n+\n+/**\n+ * A key-value store backed by Doctrine DBAL.\n+ *\n+ * @since  1.0\n+ *\n+ * @author Bernhard Schussek <bschussek@gmail.com>\n+ * @author Michiel Boeckaert <boeckaert@gmail.com>\n+ */\n+class DbalStore implements KeyValueStore\n+{\n+    private $connection;\n+    private $tableName;\n+\n+    /**\n+     * @param Connection $connection A doctrine connection instance\n+     * @param string     $tableName  The name of the database table\n+     */\n+    public function __construct(Connection $connection, $tableName = 'store')\n+    {\n+        Assert::stringNotEmpty($tableName, 'The table must be a string. Got: %s');\n+\n+        $this->connection = $connection;\n+        $this->tableName = $tableName;\n+    }\n+\n+    /**\n+     * {@inheritdoc}\n+     */\n+    public function set($key, $value)\n+    {\n+        KeyUtil::validate($key);\n+\n+        try {\n+            $existing = $this->exists($key);\n+        } catch (Exception $e) {\n+            throw WriteException::forException($e);\n+        }\n+\n+        if (false === $existing) {\n+            $this->doInsert($key, $value);\n+        } else {\n+            $this->doUpdate($key, $value);\n+        }\n+    }\n+\n+    /**\n+     * {@inheritdoc}\n+     */\n+    public function get($key, $default = null)\n+    {\n+        KeyUtil::validate($key);\n+\n+        $dbResult = $this->getDbRow($key);\n+\n+        if (null === $dbResult) {\n+            return $default;\n+        }\n+\n+        return Serializer::unserialize($dbResult['meta_value']);\n+    }\n+\n+    /**\n+     * {@inheritdoc}\n+     */\n+    public function getOrFail($key)\n+    {\n+        KeyUtil::validate($key);\n+\n+        $dbResult = $this->getDbRow($key);\n+\n+        if (null === $dbResult) {\n+            throw NoSuchKeyException::forKey($key);\n+        }\n+\n+        return Serializer::unserialize($dbResult['meta_value']);\n+    }\n+\n+    /**\n+     * {@inheritdoc}\n+     */\n+    public function getMultiple(array $keys, $default = null)\n+    {\n+        KeyUtil::validateMultiple($keys);\n+\n+        // Normalize indices of the array\n+        $keys = array_values($keys);\n+        $data = $this->doGetMultiple($keys);\n+\n+        $results = array();\n+        $resolved = array();\n+        foreach ($data as $row) {\n+            $results[$row['meta_key']] = Serializer::unserialize($row['meta_value']);\n+            $resolved[$row['meta_key']] = $row['meta_key'];\n+        }\n+\n+        $notResolvedArr = array_diff($keys, $resolved);\n+        foreach ($notResolvedArr as $notResolved) {\n+            $results[$notResolved] = $default;\n+        }\n+\n+        return $results;\n+    }\n+\n+    /**\n+     * {@inheritdoc}\n+     */\n+    public function getMultipleOrFail(array $keys)\n+    {\n+        KeyUtil::validateMultiple($keys);\n+\n+        // Normalize indices of the array\n+        $keys = array_values($keys);\n+\n+        $data = $this->doGetMultiple($keys);\n+\n+        $results = array();\n+        $resolved = array();\n+        foreach ($data as $row) {\n+            $results[$row['meta_key']] = Serializer::unserialize($row['meta_value']);\n+            $resolved[] = $row['meta_key'];\n+        }\n+\n+        $notResolvedArr = array_diff($keys, $resolved);\n+\n+        if (!empty($notResolvedArr)) {\n+            throw NoSuchKeyException::forKeys($notResolvedArr);\n+        }\n+\n+        return $results;\n+    }\n+\n+    /**\n+     * {@inheritdoc}\n+     */\n+    public function remove($key)\n+    {\n+        KeyUtil::validate($key);\n+\n+        try {\n+            $result = $this->connection->delete($this->tableName, array('meta_key' => $key));\n+        } catch (Exception $e) {\n+            throw WriteException::forException($e);\n+        }\n+\n+        return $result === 1;\n+    }\n+\n+    /**\n+     * {@inheritdoc}\n+     */\n+    public function exists($key)\n+    {\n+        KeyUtil::validate($key);\n+\n+        try {\n+            $result = $this->connection->fetchAssoc('SELECT * FROM '.$this->tableName.' WHERE meta_key = ?', array($key));\n+        } catch (Exception $e) {\n+            throw ReadException::forException($e);\n+        }\n+\n+        return $result ? true : false;\n+    }\n+\n+    /**\n+     * {@inheritdoc}\n+     */\n+    public function clear()\n+    {\n+        try {\n+            $stmt = $this->connection->query('DELETE FROM '.$this->tableName);\n+            $stmt->execute();\n+        } catch (Exception $e) {\n+            throw WriteException::forException($e);\n+        }\n+    }\n+\n+    /**\n+     * {@inheritdoc}\n+     */\n+    public function keys()\n+    {\n+        try {\n+            $stmt = $this->connection->query('SELECT meta_key FROM '.$this->tableName);\n+            $result = $stmt->fetchAll(PDO::FETCH_COLUMN);\n+        } catch (Exception $e) {\n+            throw ReadException::forException($e);\n+        }\n+\n+        return $result;\n+    }\n+\n+    private function doInsert($key, $value)\n+    {\n+        $serialized = Serializer::serialize($value);\n+\n+        try {\n+            $this->connection->insert($this->tableName, array(\n+                'meta_key' => $key,\n+                'meta_value' => $serialized,\n+            ));\n+        } catch (Exception $e) {\n+            throw WriteException::forException($e);\n+        }\n+    }\n+\n+    /**\n+     * The name for our DBAL database table.\n+     *\n+     * @return string\n+     */\n+    public function getTableName()\n+    {\n+        return $this->tableName;\n+    }\n+\n+    /**\n+     * Object Representation of the table used in this class.\n+     *\n+     * @return \\Doctrine\\DBAL\\Schema\\Table","path":"src/DbalStore.php","position":244,"original_position":244,"commit_id":"22d361d3df2c32632fd822ed8140f327b8c063b7","original_commit_id":"22d361d3df2c32632fd822ed8140f327b8c063b7","user":{"login":"webmozart","id":176399,"avatar_url":"https://avatars.githubusercontent.com/u/176399?v=3","gravatar_id":"","url":"https://api.github.com/users/webmozart","html_url":"https://github.com/webmozart","followers_url":"https://api.github.com/users/webmozart/followers","following_url":"https://api.github.com/users/webmozart/following{/other_user}","gists_url":"https://api.github.com/users/webmozart/gists{/gist_id}","starred_url":"https://api.github.com/users/webmozart/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/webmozart/subscriptions","organizations_url":"https://api.github.com/users/webmozart/orgs","repos_url":"https://api.github.com/users/webmozart/repos","events_url":"https://api.github.com/users/webmozart/events{/privacy}","received_events_url":"https://api.github.com/users/webmozart/received_events","type":"User","site_admin":false},"body":"You can shorten this to `@return Table` and add `use Doctrine\\DBAL\\Schema\\Table` at the top. :)","created_at":"2015-09-29T09:27:50Z","updated_at":"2015-09-29T09:27:50Z","html_url":"https://github.com/webmozart/key-value-store/pull/15#discussion_r40651163","pull_request_url":"https://api.github.com/repos/webmozart/key-value-store/pulls/15","_links":{"self":{"href":"https://api.github.com/repos/webmozart/key-value-store/pulls/comments/40651163"},"html":{"href":"https://github.com/webmozart/key-value-store/pull/15#discussion_r40651163"},"pull_request":{"href":"https://api.github.com/repos/webmozart/key-value-store/pulls/15"}}},"pull_request":{"url":"https://api.github.com/repos/webmozart/key-value-store/pulls/15","id":46222448,"html_url":"https://github.com/webmozart/key-value-store/pull/15","diff_url":"https://github.com/webmozart/key-value-store/pull/15.diff","patch_url":"https://github.com/webmozart/key-value-store/pull/15.patch","issue_url":"https://api.github.com/repos/webmozart/key-value-store/issues/15","number":15,"state":"open","locked":false,"title":"Doctrine DBAL store","user":{"login":"Miliooo","id":3365006,"avatar_url":"https://avatars.githubusercontent.com/u/3365006?v=3","gravatar_id":"","url":"https://api.github.com/users/Miliooo","html_url":"https://github.com/Miliooo","followers_url":"https://api.github.com/users/Miliooo/followers","following_url":"https://api.github.com/users/Miliooo/following{/other_user}","gists_url":"https://api.github.com/users/Miliooo/gists{/gist_id}","starred_url":"https://api.github.com/users/Miliooo/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Miliooo/subscriptions","organizations_url":"https://api.github.com/users/Miliooo/orgs","repos_url":"https://api.github.com/users/Miliooo/repos","events_url":"https://api.github.com/users/Miliooo/events{/privacy}","received_events_url":"https://api.github.com/users/Miliooo/received_events","type":"User","site_admin":false},"body":"I needed a key value store dbal implementation for my own project. \r\n\r\nThe only thing I found was https://github.com/doctrine/KeyValueStore/blob/master/lib/Doctrine/KeyValueStore/Storage/DBALStorage.php and this package.\r\n\r\nSo I decided to implement one that implements this projects interface.","created_at":"2015-09-28T23:54:36Z","updated_at":"2015-09-29T09:27:50Z","closed_at":null,"merged_at":null,"merge_commit_sha":"d5a14f84bb6b2c4987ce35214d7264ce2e7fa957","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/webmozart/key-value-store/pulls/15/commits","review_comments_url":"https://api.github.com/repos/webmozart/key-value-store/pulls/15/comments","review_comment_url":"https://api.github.com/repos/webmozart/key-value-store/pulls/comments{/number}","comments_url":"https://api.github.com/repos/webmozart/key-value-store/issues/15/comments","statuses_url":"https://api.github.com/repos/webmozart/key-value-store/statuses/22d361d3df2c32632fd822ed8140f327b8c063b7","head":{"label":"Miliooo:dbal","ref":"dbal","sha":"22d361d3df2c32632fd822ed8140f327b8c063b7","user":{"login":"Miliooo","id":3365006,"avatar_url":"https://avatars.githubusercontent.com/u/3365006?v=3","gravatar_id":"","url":"https://api.github.com/users/Miliooo","html_url":"https://github.com/Miliooo","followers_url":"https://api.github.com/users/Miliooo/followers","following_url":"https://api.github.com/users/Miliooo/following{/other_user}","gists_url":"https://api.github.com/users/Miliooo/gists{/gist_id}","starred_url":"https://api.github.com/users/Miliooo/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Miliooo/subscriptions","organizations_url":"https://api.github.com/users/Miliooo/orgs","repos_url":"https://api.github.com/users/Miliooo/repos","events_url":"https://api.github.com/users/Miliooo/events{/privacy}","received_events_url":"https://api.github.com/users/Miliooo/received_events","type":"User","site_admin":false},"repo":{"id":43315942,"name":"key-value-store","full_name":"Miliooo/key-value-store","owner":{"login":"Miliooo","id":3365006,"avatar_url":"https://avatars.githubusercontent.com/u/3365006?v=3","gravatar_id":"","url":"https://api.github.com/users/Miliooo","html_url":"https://github.com/Miliooo","followers_url":"https://api.github.com/users/Miliooo/followers","following_url":"https://api.github.com/users/Miliooo/following{/other_user}","gists_url":"https://api.github.com/users/Miliooo/gists{/gist_id}","starred_url":"https://api.github.com/users/Miliooo/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Miliooo/subscriptions","organizations_url":"https://api.github.com/users/Miliooo/orgs","repos_url":"https://api.github.com/users/Miliooo/repos","events_url":"https://api.github.com/users/Miliooo/events{/privacy}","received_events_url":"https://api.github.com/users/Miliooo/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/Miliooo/key-value-store","description":"A key-value store API with implementations for different backends.","fork":true,"url":"https://api.github.com/repos/Miliooo/key-value-store","forks_url":"https://api.github.com/repos/Miliooo/key-value-store/forks","keys_url":"https://api.github.com/repos/Miliooo/key-value-store/keys{/key_id}","collaborators_url":"https://api.github.com/repos/Miliooo/key-value-store/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/Miliooo/key-value-store/teams","hooks_url":"https://api.github.com/repos/Miliooo/key-value-store/hooks","issue_events_url":"https://api.github.com/repos/Miliooo/key-value-store/issues/events{/number}","events_url":"https://api.github.com/repos/Miliooo/key-value-store/events","assignees_url":"https://api.github.com/repos/Miliooo/key-value-store/assignees{/user}","branches_url":"https://api.github.com/repos/Miliooo/key-value-store/branches{/branch}","tags_url":"https://api.github.com/repos/Miliooo/key-value-store/tags","blobs_url":"https://api.github.com/repos/Miliooo/key-value-store/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/Miliooo/key-value-store/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/Miliooo/key-value-store/git/refs{/sha}","trees_url":"https://api.github.com/repos/Miliooo/key-value-store/git/trees{/sha}","statuses_url":"https://api.github.com/repos/Miliooo/key-value-store/statuses/{sha}","languages_url":"https://api.github.com/repos/Miliooo/key-value-store/languages","stargazers_url":"https://api.github.com/repos/Miliooo/key-value-store/stargazers","contributors_url":"https://api.github.com/repos/Miliooo/key-value-store/contributors","subscribers_url":"https://api.github.com/repos/Miliooo/key-value-store/subscribers","subscription_url":"https://api.github.com/repos/Miliooo/key-value-store/subscription","commits_url":"https://api.github.com/repos/Miliooo/key-value-store/commits{/sha}","git_commits_url":"https://api.github.com/repos/Miliooo/key-value-store/git/commits{/sha}","comments_url":"https://api.github.com/repos/Miliooo/key-value-store/comments{/number}","issue_comment_url":"https://api.github.com/repos/Miliooo/key-value-store/issues/comments{/number}","contents_url":"https://api.github.com/repos/Miliooo/key-value-store/contents/{+path}","compare_url":"https://api.github.com/repos/Miliooo/key-value-store/compare/{base}...{head}","merges_url":"https://api.github.com/repos/Miliooo/key-value-store/merges","archive_url":"https://api.github.com/repos/Miliooo/key-value-store/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/Miliooo/key-value-store/downloads","issues_url":"https://api.github.com/repos/Miliooo/key-value-store/issues{/number}","pulls_url":"https://api.github.com/repos/Miliooo/key-value-store/pulls{/number}","milestones_url":"https://api.github.com/repos/Miliooo/key-value-store/milestones{/number}","notifications_url":"https://api.github.com/repos/Miliooo/key-value-store/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/Miliooo/key-value-store/labels{/name}","releases_url":"https://api.github.com/repos/Miliooo/key-value-store/releases{/id}","created_at":"2015-09-28T17:32:58Z","updated_at":"2015-09-28T17:32:58Z","pushed_at":"2015-09-29T09:06:25Z","git_url":"git://github.com/Miliooo/key-value-store.git","ssh_url":"git@github.com:Miliooo/key-value-store.git","clone_url":"https://github.com/Miliooo/key-value-store.git","svn_url":"https://github.com/Miliooo/key-value-store","homepage":"","size":837,"stargazers_count":0,"watchers_count":0,"language":"PHP","has_issues":false,"has_downloads":true,"has_wiki":false,"has_pages":true,"forks_count":0,"mirror_url":null,"open_issues_count":0,"forks":0,"open_issues":0,"watchers":0,"default_branch":"master"}},"base":{"label":"webmozart:master","ref":"master","sha":"cf753578223d92022e6e3e2e6b8e3f6cea1f35ab","user":{"login":"webmozart","id":176399,"avatar_url":"https://avatars.githubusercontent.com/u/176399?v=3","gravatar_id":"","url":"https://api.github.com/users/webmozart","html_url":"https://github.com/webmozart","followers_url":"https://api.github.com/users/webmozart/followers","following_url":"https://api.github.com/users/webmozart/following{/other_user}","gists_url":"https://api.github.com/users/webmozart/gists{/gist_id}","starred_url":"https://api.github.com/users/webmozart/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/webmozart/subscriptions","organizations_url":"https://api.github.com/users/webmozart/orgs","repos_url":"https://api.github.com/users/webmozart/repos","events_url":"https://api.github.com/users/webmozart/events{/privacy}","received_events_url":"https://api.github.com/users/webmozart/received_events","type":"User","site_admin":false},"repo":{"id":28540334,"name":"key-value-store","full_name":"webmozart/key-value-store","owner":{"login":"webmozart","id":176399,"avatar_url":"https://avatars.githubusercontent.com/u/176399?v=3","gravatar_id":"","url":"https://api.github.com/users/webmozart","html_url":"https://github.com/webmozart","followers_url":"https://api.github.com/users/webmozart/followers","following_url":"https://api.github.com/users/webmozart/following{/other_user}","gists_url":"https://api.github.com/users/webmozart/gists{/gist_id}","starred_url":"https://api.github.com/users/webmozart/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/webmozart/subscriptions","organizations_url":"https://api.github.com/users/webmozart/orgs","repos_url":"https://api.github.com/users/webmozart/repos","events_url":"https://api.github.com/users/webmozart/events{/privacy}","received_events_url":"https://api.github.com/users/webmozart/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/webmozart/key-value-store","description":"A key-value store API with implementations for different backends.","fork":false,"url":"https://api.github.com/repos/webmozart/key-value-store","forks_url":"https://api.github.com/repos/webmozart/key-value-store/forks","keys_url":"https://api.github.com/repos/webmozart/key-value-store/keys{/key_id}","collaborators_url":"https://api.github.com/repos/webmozart/key-value-store/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/webmozart/key-value-store/teams","hooks_url":"https://api.github.com/repos/webmozart/key-value-store/hooks","issue_events_url":"https://api.github.com/repos/webmozart/key-value-store/issues/events{/number}","events_url":"https://api.github.com/repos/webmozart/key-value-store/events","assignees_url":"https://api.github.com/repos/webmozart/key-value-store/assignees{/user}","branches_url":"https://api.github.com/repos/webmozart/key-value-store/branches{/branch}","tags_url":"https://api.github.com/repos/webmozart/key-value-store/tags","blobs_url":"https://api.github.com/repos/webmozart/key-value-store/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/webmozart/key-value-store/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/webmozart/key-value-store/git/refs{/sha}","trees_url":"https://api.github.com/repos/webmozart/key-value-store/git/trees{/sha}","statuses_url":"https://api.github.com/repos/webmozart/key-value-store/statuses/{sha}","languages_url":"https://api.github.com/repos/webmozart/key-value-store/languages","stargazers_url":"https://api.github.com/repos/webmozart/key-value-store/stargazers","contributors_url":"https://api.github.com/repos/webmozart/key-value-store/contributors","subscribers_url":"https://api.github.com/repos/webmozart/key-value-store/subscribers","subscription_url":"https://api.github.com/repos/webmozart/key-value-store/subscription","commits_url":"https://api.github.com/repos/webmozart/key-value-store/commits{/sha}","git_commits_url":"https://api.github.com/repos/webmozart/key-value-store/git/commits{/sha}","comments_url":"https://api.github.com/repos/webmozart/key-value-store/comments{/number}","issue_comment_url":"https://api.github.com/repos/webmozart/key-value-store/issues/comments{/number}","contents_url":"https://api.github.com/repos/webmozart/key-value-store/contents/{+path}","compare_url":"https://api.github.com/repos/webmozart/key-value-store/compare/{base}...{head}","merges_url":"https://api.github.com/repos/webmozart/key-value-store/merges","archive_url":"https://api.github.com/repos/webmozart/key-value-store/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/webmozart/key-value-store/downloads","issues_url":"https://api.github.com/repos/webmozart/key-value-store/issues{/number}","pulls_url":"https://api.github.com/repos/webmozart/key-value-store/pulls{/number}","milestones_url":"https://api.github.com/repos/webmozart/key-value-store/milestones{/number}","notifications_url":"https://api.github.com/repos/webmozart/key-value-store/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/webmozart/key-value-store/labels{/name}","releases_url":"https://api.github.com/repos/webmozart/key-value-store/releases{/id}","created_at":"2014-12-27T15:54:10Z","updated_at":"2015-09-12T18:01:32Z","pushed_at":"2015-09-29T09:06:26Z","git_url":"git://github.com/webmozart/key-value-store.git","ssh_url":"git@github.com:webmozart/key-value-store.git","clone_url":"https://github.com/webmozart/key-value-store.git","svn_url":"https://github.com/webmozart/key-value-store","homepage":"","size":837,"stargazers_count":64,"watchers_count":64,"language":"PHP","has_issues":true,"has_downloads":true,"has_wiki":false,"has_pages":true,"forks_count":5,"mirror_url":null,"open_issues_count":2,"forks":5,"open_issues":2,"watchers":64,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/webmozart/key-value-store/pulls/15"},"html":{"href":"https://github.com/webmozart/key-value-store/pull/15"},"issue":{"href":"https://api.github.com/repos/webmozart/key-value-store/issues/15"},"comments":{"href":"https://api.github.com/repos/webmozart/key-value-store/issues/15/comments"},"review_comments":{"href":"https://api.github.com/repos/webmozart/key-value-store/pulls/15/comments"},"review_comment":{"href":"https://api.github.com/repos/webmozart/key-value-store/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/webmozart/key-value-store/pulls/15/commits"},"statuses":{"href":"https://api.github.com/repos/webmozart/key-value-store/statuses/22d361d3df2c32632fd822ed8140f327b8c063b7"}}}}