{"action":"created","comment":{"url":"https://api.github.com/repos/cakephp/cakephp/pulls/comments/72722143","id":72722143,"diff_hunk":"@@ -0,0 +1,212 @@\n+<?php\n+/**\n+ * CakePHP(tm) : Rapid Development Framework (http://cakephp.org)\n+ * Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)\n+ *\n+ * Licensed under The MIT License\n+ * For full copyright and license information, please see the LICENSE.txt\n+ * Redistributions of files must retain the above copyright notice.\n+ *\n+ * @copyright     Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)\n+ * @link          http://cakephp.org CakePHP(tm) Project\n+ * @since         3.3.0\n+ * @license       http://www.opensource.org/licenses/mit-license.php MIT License\n+ */\n+namespace Cake\\ORM;\n+\n+use ArrayObject;\n+use RuntimeException;\n+\n+/**\n+ * OOP style Save Option Builder.\n+ *\n+ * This allows you to build options to save entities in a OOP style and helps\n+ * you to avoid mistakes by validating the options as you build them.\n+ *\n+ * @see \\Cake\\Datasource\\RulesChecker\n+ */\n+class SaveOptionsBuilder extends ArrayObject\n+{\n+\n+    use AssociationsNormalizerTrait;\n+\n+    /**\n+     * Options\n+     *\n+     * @var array\n+     */\n+    protected $_options = [];\n+\n+    /**\n+     * Table object.\n+     *\n+     * @var \\Cake\\ORM\\Table;\n+     */\n+    protected $_table;\n+\n+    /**\n+     * Constructor.\n+     *\n+     * @param \\Cake\\ORM\\Table $table A table instance.\n+     * @param array $options Options to parse when instantiating.\n+     */\n+    public function __construct(Table $table, array $options = [])\n+    {\n+        $this->_table = $table;\n+        $this->parseArrayOptions($options);\n+    }\n+\n+    /**\n+     * Takes an options array and populates the option object with the data.\n+     *\n+     * This can be used to turn an options array into the object.\n+     *\n+     * @throws \\InvalidArgumentException If a given option key does not exist.\n+     * @param array $array Options array.\n+     * @return \\Cake\\ORM\\SaveOptionsBuilder\n+     */\n+    public function parseArrayOptions($array)\n+    {\n+        foreach ($array as $key => $value) {\n+            $this->{$key}($value);\n+        }\n+        return $this;\n+    }\n+\n+    /**\n+     * Set associated options.\n+     *\n+     * @param string|array $associated String or array of associations.\n+     * @return \\Cake\\ORM\\SaveOptionsBuilder\n+     */\n+    public function associated($associated)\n+    {\n+        $associated = $this->_normalizeAssociations($associated);\n+        $this->_associated($this->_table, $associated);\n+        $this->_options['associated'] = $associated;\n+\n+        return $this;\n+    }\n+\n+    /**\n+     * Checks that the associations exists recursively.\n+     *\n+     * @param \\Cake\\ORM\\Table $table Table object.\n+     * @param array $associations An associations array.\n+     * @return void\n+     */\n+    protected function _associated(Table $table, array $associations)\n+    {\n+        foreach ($associations as $key => $associated) {\n+            if (is_int($key)) {\n+                $this->_checkAssociation($table, $associated);\n+                continue;\n+            }\n+            $this->_checkAssociation($table, $key);\n+            if (isset($associated['associated'])) {\n+                $this->_associated($table->association($key)->target(), $associated['associated']);\n+                continue;\n+            }\n+        }\n+    }\n+\n+    /**\n+     * Checks if an association exists.\n+     *\n+     * @throws \\RuntimeException If no such association exists for the given table.\n+     * @param \\Cake\\ORM\\Table $table Table object.\n+     * @param string $association Association name.\n+     * @return void\n+     */\n+    protected function _checkAssociation(Table $table, $association)\n+    {\n+        if (!$table->associations()->has($association)) {\n+            throw new RuntimeException(sprintf('Table `%s` is not associated with `%s`', get_class($table), $association));\n+        }\n+    }\n+\n+    /**\n+     * Set the guard option.\n+     *\n+     * @param bool $guard Guard the properties or not.\n+     * @return \\Cake\\ORM\\SaveOptionsBuilder\n+     */\n+    public function guard($guard)\n+    {\n+        $this->_options['guard'] = (bool)$guard;\n+        return $this;\n+    }\n+\n+    /**\n+     * Set the validation rule set to use.\n+     *\n+     * @param string $validate Name of the validation rule set to use.\n+     * @return \\Cake\\ORM\\SaveOptionsBuilder\n+     */\n+    public function validate($validate)\n+    {\n+        $this->_table->validator($validate);","path":"src/ORM/SaveOptionsBuilder.php","position":148,"original_position":148,"commit_id":"f4903c69aa98cbaffb7342bb981d08fb7b2049b9","original_commit_id":"f4903c69aa98cbaffb7342bb981d08fb7b2049b9","user":{"login":"markstory","id":24086,"avatar_url":"https://avatars.githubusercontent.com/u/24086?v=3","gravatar_id":"","url":"https://api.github.com/users/markstory","html_url":"https://github.com/markstory","followers_url":"https://api.github.com/users/markstory/followers","following_url":"https://api.github.com/users/markstory/following{/other_user}","gists_url":"https://api.github.com/users/markstory/gists{/gist_id}","starred_url":"https://api.github.com/users/markstory/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/markstory/subscriptions","organizations_url":"https://api.github.com/users/markstory/orgs","repos_url":"https://api.github.com/users/markstory/repos","events_url":"https://api.github.com/users/markstory/events{/privacy}","received_events_url":"https://api.github.com/users/markstory/received_events","type":"User","site_admin":false},"body":"Yes. This will mutate the table by building a validator and triggering the `Model.buildValidator` event if the validator hasn't already been built.","created_at":"2016-07-28T23:37:41Z","updated_at":"2016-07-28T23:37:41Z","html_url":"https://github.com/cakephp/cakephp/pull/9143#discussion_r72722143","pull_request_url":"https://api.github.com/repos/cakephp/cakephp/pulls/9143","_links":{"self":{"href":"https://api.github.com/repos/cakephp/cakephp/pulls/comments/72722143"},"html":{"href":"https://github.com/cakephp/cakephp/pull/9143#discussion_r72722143"},"pull_request":{"href":"https://api.github.com/repos/cakephp/cakephp/pulls/9143"}}},"pull_request":{"url":"https://api.github.com/repos/cakephp/cakephp/pulls/9143","id":78132042,"html_url":"https://github.com/cakephp/cakephp/pull/9143","diff_url":"https://github.com/cakephp/cakephp/pull/9143.diff","patch_url":"https://github.com/cakephp/cakephp/pull/9143.patch","issue_url":"https://api.github.com/repos/cakephp/cakephp/issues/9143","number":9143,"state":"open","locked":false,"title":"Adding an option builder for the save options","user":{"login":"burzum","id":162789,"avatar_url":"https://avatars.githubusercontent.com/u/162789?v=3","gravatar_id":"","url":"https://api.github.com/users/burzum","html_url":"https://github.com/burzum","followers_url":"https://api.github.com/users/burzum/followers","following_url":"https://api.github.com/users/burzum/following{/other_user}","gists_url":"https://api.github.com/users/burzum/gists{/gist_id}","starred_url":"https://api.github.com/users/burzum/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/burzum/subscriptions","organizations_url":"https://api.github.com/users/burzum/orgs","repos_url":"https://api.github.com/users/burzum/repos","events_url":"https://api.github.com/users/burzum/events{/privacy}","received_events_url":"https://api.github.com/users/burzum/received_events","type":"User","site_admin":false},"body":"The option builder allows building the options through a chainable interface and does checks on some of the options to prevent mistakes like types in the associations. This helps the developer and ensures everything that is supposed to be saved gets really set up and saved right.","created_at":"2016-07-20T11:40:25Z","updated_at":"2016-07-28T23:37:41Z","closed_at":null,"merged_at":null,"merge_commit_sha":"b7e4f249cfc86f0dce86b22db362e2eae62b7665","assignee":{"login":"burzum","id":162789,"avatar_url":"https://avatars.githubusercontent.com/u/162789?v=3","gravatar_id":"","url":"https://api.github.com/users/burzum","html_url":"https://github.com/burzum","followers_url":"https://api.github.com/users/burzum/followers","following_url":"https://api.github.com/users/burzum/following{/other_user}","gists_url":"https://api.github.com/users/burzum/gists{/gist_id}","starred_url":"https://api.github.com/users/burzum/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/burzum/subscriptions","organizations_url":"https://api.github.com/users/burzum/orgs","repos_url":"https://api.github.com/users/burzum/repos","events_url":"https://api.github.com/users/burzum/events{/privacy}","received_events_url":"https://api.github.com/users/burzum/received_events","type":"User","site_admin":false},"assignees":[{"login":"burzum","id":162789,"avatar_url":"https://avatars.githubusercontent.com/u/162789?v=3","gravatar_id":"","url":"https://api.github.com/users/burzum","html_url":"https://github.com/burzum","followers_url":"https://api.github.com/users/burzum/followers","following_url":"https://api.github.com/users/burzum/following{/other_user}","gists_url":"https://api.github.com/users/burzum/gists{/gist_id}","starred_url":"https://api.github.com/users/burzum/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/burzum/subscriptions","organizations_url":"https://api.github.com/users/burzum/orgs","repos_url":"https://api.github.com/users/burzum/repos","events_url":"https://api.github.com/users/burzum/events{/privacy}","received_events_url":"https://api.github.com/users/burzum/received_events","type":"User","site_admin":false}],"milestone":null,"commits_url":"https://api.github.com/repos/cakephp/cakephp/pulls/9143/commits","review_comments_url":"https://api.github.com/repos/cakephp/cakephp/pulls/9143/comments","review_comment_url":"https://api.github.com/repos/cakephp/cakephp/pulls/comments{/number}","comments_url":"https://api.github.com/repos/cakephp/cakephp/issues/9143/comments","statuses_url":"https://api.github.com/repos/cakephp/cakephp/statuses/f4903c69aa98cbaffb7342bb981d08fb7b2049b9","head":{"label":"burzum:feature/entity-option-builder","ref":"feature/entity-option-builder","sha":"f4903c69aa98cbaffb7342bb981d08fb7b2049b9","user":{"login":"burzum","id":162789,"avatar_url":"https://avatars.githubusercontent.com/u/162789?v=3","gravatar_id":"","url":"https://api.github.com/users/burzum","html_url":"https://github.com/burzum","followers_url":"https://api.github.com/users/burzum/followers","following_url":"https://api.github.com/users/burzum/following{/other_user}","gists_url":"https://api.github.com/users/burzum/gists{/gist_id}","starred_url":"https://api.github.com/users/burzum/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/burzum/subscriptions","organizations_url":"https://api.github.com/users/burzum/orgs","repos_url":"https://api.github.com/users/burzum/repos","events_url":"https://api.github.com/users/burzum/events{/privacy}","received_events_url":"https://api.github.com/users/burzum/received_events","type":"User","site_admin":false},"repo":{"id":905891,"name":"cakephp","full_name":"burzum/cakephp","owner":{"login":"burzum","id":162789,"avatar_url":"https://avatars.githubusercontent.com/u/162789?v=3","gravatar_id":"","url":"https://api.github.com/users/burzum","html_url":"https://github.com/burzum","followers_url":"https://api.github.com/users/burzum/followers","following_url":"https://api.github.com/users/burzum/following{/other_user}","gists_url":"https://api.github.com/users/burzum/gists{/gist_id}","starred_url":"https://api.github.com/users/burzum/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/burzum/subscriptions","organizations_url":"https://api.github.com/users/burzum/orgs","repos_url":"https://api.github.com/users/burzum/repos","events_url":"https://api.github.com/users/burzum/events{/privacy}","received_events_url":"https://api.github.com/users/burzum/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/burzum/cakephp","description":"CakePHP: The Rapid Development Framework for PHP - Official Repository","fork":true,"url":"https://api.github.com/repos/burzum/cakephp","forks_url":"https://api.github.com/repos/burzum/cakephp/forks","keys_url":"https://api.github.com/repos/burzum/cakephp/keys{/key_id}","collaborators_url":"https://api.github.com/repos/burzum/cakephp/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/burzum/cakephp/teams","hooks_url":"https://api.github.com/repos/burzum/cakephp/hooks","issue_events_url":"https://api.github.com/repos/burzum/cakephp/issues/events{/number}","events_url":"https://api.github.com/repos/burzum/cakephp/events","assignees_url":"https://api.github.com/repos/burzum/cakephp/assignees{/user}","branches_url":"https://api.github.com/repos/burzum/cakephp/branches{/branch}","tags_url":"https://api.github.com/repos/burzum/cakephp/tags","blobs_url":"https://api.github.com/repos/burzum/cakephp/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/burzum/cakephp/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/burzum/cakephp/git/refs{/sha}","trees_url":"https://api.github.com/repos/burzum/cakephp/git/trees{/sha}","statuses_url":"https://api.github.com/repos/burzum/cakephp/statuses/{sha}","languages_url":"https://api.github.com/repos/burzum/cakephp/languages","stargazers_url":"https://api.github.com/repos/burzum/cakephp/stargazers","contributors_url":"https://api.github.com/repos/burzum/cakephp/contributors","subscribers_url":"https://api.github.com/repos/burzum/cakephp/subscribers","subscription_url":"https://api.github.com/repos/burzum/cakephp/subscription","commits_url":"https://api.github.com/repos/burzum/cakephp/commits{/sha}","git_commits_url":"https://api.github.com/repos/burzum/cakephp/git/commits{/sha}","comments_url":"https://api.github.com/repos/burzum/cakephp/comments{/number}","issue_comment_url":"https://api.github.com/repos/burzum/cakephp/issues/comments{/number}","contents_url":"https://api.github.com/repos/burzum/cakephp/contents/{+path}","compare_url":"https://api.github.com/repos/burzum/cakephp/compare/{base}...{head}","merges_url":"https://api.github.com/repos/burzum/cakephp/merges","archive_url":"https://api.github.com/repos/burzum/cakephp/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/burzum/cakephp/downloads","issues_url":"https://api.github.com/repos/burzum/cakephp/issues{/number}","pulls_url":"https://api.github.com/repos/burzum/cakephp/pulls{/number}","milestones_url":"https://api.github.com/repos/burzum/cakephp/milestones{/number}","notifications_url":"https://api.github.com/repos/burzum/cakephp/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/burzum/cakephp/labels{/name}","releases_url":"https://api.github.com/repos/burzum/cakephp/releases{/id}","deployments_url":"https://api.github.com/repos/burzum/cakephp/deployments","created_at":"2010-09-12T22:15:50Z","updated_at":"2014-01-16T22:37:48Z","pushed_at":"2016-07-26T11:23:16Z","git_url":"git://github.com/burzum/cakephp.git","ssh_url":"git@github.com:burzum/cakephp.git","clone_url":"https://github.com/burzum/cakephp.git","svn_url":"https://github.com/burzum/cakephp","homepage":"http://cakephp.org","size":60950,"stargazers_count":1,"watchers_count":1,"language":"PHP","has_issues":false,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":0,"mirror_url":null,"open_issues_count":0,"forks":0,"open_issues":0,"watchers":1,"default_branch":"master"}},"base":{"label":"cakephp:master","ref":"master","sha":"2fd23dfd9155346929afc2ddb00611d6f9762d57","user":{"login":"cakephp","id":23666,"avatar_url":"https://avatars.githubusercontent.com/u/23666?v=3","gravatar_id":"","url":"https://api.github.com/users/cakephp","html_url":"https://github.com/cakephp","followers_url":"https://api.github.com/users/cakephp/followers","following_url":"https://api.github.com/users/cakephp/following{/other_user}","gists_url":"https://api.github.com/users/cakephp/gists{/gist_id}","starred_url":"https://api.github.com/users/cakephp/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/cakephp/subscriptions","organizations_url":"https://api.github.com/users/cakephp/orgs","repos_url":"https://api.github.com/users/cakephp/repos","events_url":"https://api.github.com/users/cakephp/events{/privacy}","received_events_url":"https://api.github.com/users/cakephp/received_events","type":"Organization","site_admin":false},"repo":{"id":656494,"name":"cakephp","full_name":"cakephp/cakephp","owner":{"login":"cakephp","id":23666,"avatar_url":"https://avatars.githubusercontent.com/u/23666?v=3","gravatar_id":"","url":"https://api.github.com/users/cakephp","html_url":"https://github.com/cakephp","followers_url":"https://api.github.com/users/cakephp/followers","following_url":"https://api.github.com/users/cakephp/following{/other_user}","gists_url":"https://api.github.com/users/cakephp/gists{/gist_id}","starred_url":"https://api.github.com/users/cakephp/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/cakephp/subscriptions","organizations_url":"https://api.github.com/users/cakephp/orgs","repos_url":"https://api.github.com/users/cakephp/repos","events_url":"https://api.github.com/users/cakephp/events{/privacy}","received_events_url":"https://api.github.com/users/cakephp/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/cakephp/cakephp","description":"CakePHP: The Rapid Development Framework for PHP - Official Repository","fork":false,"url":"https://api.github.com/repos/cakephp/cakephp","forks_url":"https://api.github.com/repos/cakephp/cakephp/forks","keys_url":"https://api.github.com/repos/cakephp/cakephp/keys{/key_id}","collaborators_url":"https://api.github.com/repos/cakephp/cakephp/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/cakephp/cakephp/teams","hooks_url":"https://api.github.com/repos/cakephp/cakephp/hooks","issue_events_url":"https://api.github.com/repos/cakephp/cakephp/issues/events{/number}","events_url":"https://api.github.com/repos/cakephp/cakephp/events","assignees_url":"https://api.github.com/repos/cakephp/cakephp/assignees{/user}","branches_url":"https://api.github.com/repos/cakephp/cakephp/branches{/branch}","tags_url":"https://api.github.com/repos/cakephp/cakephp/tags","blobs_url":"https://api.github.com/repos/cakephp/cakephp/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/cakephp/cakephp/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/cakephp/cakephp/git/refs{/sha}","trees_url":"https://api.github.com/repos/cakephp/cakephp/git/trees{/sha}","statuses_url":"https://api.github.com/repos/cakephp/cakephp/statuses/{sha}","languages_url":"https://api.github.com/repos/cakephp/cakephp/languages","stargazers_url":"https://api.github.com/repos/cakephp/cakephp/stargazers","contributors_url":"https://api.github.com/repos/cakephp/cakephp/contributors","subscribers_url":"https://api.github.com/repos/cakephp/cakephp/subscribers","subscription_url":"https://api.github.com/repos/cakephp/cakephp/subscription","commits_url":"https://api.github.com/repos/cakephp/cakephp/commits{/sha}","git_commits_url":"https://api.github.com/repos/cakephp/cakephp/git/commits{/sha}","comments_url":"https://api.github.com/repos/cakephp/cakephp/comments{/number}","issue_comment_url":"https://api.github.com/repos/cakephp/cakephp/issues/comments{/number}","contents_url":"https://api.github.com/repos/cakephp/cakephp/contents/{+path}","compare_url":"https://api.github.com/repos/cakephp/cakephp/compare/{base}...{head}","merges_url":"https://api.github.com/repos/cakephp/cakephp/merges","archive_url":"https://api.github.com/repos/cakephp/cakephp/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/cakephp/cakephp/downloads","issues_url":"https://api.github.com/repos/cakephp/cakephp/issues{/number}","pulls_url":"https://api.github.com/repos/cakephp/cakephp/pulls{/number}","milestones_url":"https://api.github.com/repos/cakephp/cakephp/milestones{/number}","notifications_url":"https://api.github.com/repos/cakephp/cakephp/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/cakephp/cakephp/labels{/name}","releases_url":"https://api.github.com/repos/cakephp/cakephp/releases{/id}","deployments_url":"https://api.github.com/repos/cakephp/cakephp/deployments","created_at":"2010-05-08T14:38:22Z","updated_at":"2016-07-28T20:39:09Z","pushed_at":"2016-07-28T23:20:30Z","git_url":"git://github.com/cakephp/cakephp.git","ssh_url":"git@github.com:cakephp/cakephp.git","clone_url":"https://github.com/cakephp/cakephp.git","svn_url":"https://github.com/cakephp/cakephp","homepage":"http://cakephp.org","size":128472,"stargazers_count":6624,"watchers_count":6624,"language":"PHP","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":true,"forks_count":3003,"mirror_url":null,"open_issues_count":195,"forks":3003,"open_issues":195,"watchers":6624,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/cakephp/cakephp/pulls/9143"},"html":{"href":"https://github.com/cakephp/cakephp/pull/9143"},"issue":{"href":"https://api.github.com/repos/cakephp/cakephp/issues/9143"},"comments":{"href":"https://api.github.com/repos/cakephp/cakephp/issues/9143/comments"},"review_comments":{"href":"https://api.github.com/repos/cakephp/cakephp/pulls/9143/comments"},"review_comment":{"href":"https://api.github.com/repos/cakephp/cakephp/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/cakephp/cakephp/pulls/9143/commits"},"statuses":{"href":"https://api.github.com/repos/cakephp/cakephp/statuses/f4903c69aa98cbaffb7342bb981d08fb7b2049b9"}}}}
{"actor":{"display_login":"markstory"}}