{"action":"created","comment":{"url":"https://api.github.com/repos/cakephp/migrations/pulls/comments/34947085","id":34947085,"diff_hunk":"@@ -161,10 +161,65 @@ public function templateData()\n     }\n \n     /**\n+     * Order tables based on foreign key dependencies so tables that are foreign keys\n+     * to other are created first\n+     *\n+     * @param array $tables Tables to order.\n+     * @return array Tables ordered.\n+     */\n+    public function orderTables($tables)\n+    {\n+        if (empty($tables)) {\n+            return $tables;\n+        }\n+\n+        $orderedTables = [];\n+        foreach ($tables as $table) {\n+            $tableSchema = $this->getCollection($this->connection)->describe($table);\n+            $tableConstraints = $tableSchema->constraints();\n+            if (isset($tableConstraints[0]) && $tableConstraints[0] === 'primary') {\n+                unset($tableConstraints[0]);\n+            }\n+\n+            if (!empty($tableConstraints)) {\n+                foreach ($tableConstraints as $tableConstraint) {\n+                    $constraint = $tableSchema->constraint($tableConstraint);\n+\n+                    if ($constraint['type'] !== 'foreign') {\n+                        continue;\n+                    }\n+\n+                    $refTable = $constraint['references'][0];\n+\n+                    $refIndex = array_search($refTable, $orderedTables);\n+                    $tableIndex = array_search($table, $orderedTables);\n+\n+                    if ($refIndex === false && $tableIndex === false) {\n+                        array_unshift($orderedTables, $refTable, $table);\n+                    } elseif ($refIndex === false) {\n+                        array_splice($orderedTables, $tableIndex, 0, $refTable);\n+                    } elseif ($tableIndex === false) {\n+                        array_splice($orderedTables, $refIndex+1, 0, $table);\n+                    } elseif ($refIndex > $tableIndex) {\n+                        unset($orderedTables[$refIndex]);\n+                        array_splice($orderedTables, $tableIndex, 0, $refTable);\n+                    }\n+                }\n+            }","path":"src/Shell/Task/MigrationSnapshotTask.php","position":57,"original_position":57,"commit_id":"401e2d9301e2c74f5cf4ee6becd947208adb453c","original_commit_id":"401e2d9301e2c74f5cf4ee6becd947208adb453c","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":"Could this sorting be done with a usort() callback? ","created_at":"2015-07-18T12:17:55Z","updated_at":"2015-07-18T12:17:55Z","html_url":"https://github.com/cakephp/migrations/pull/101#discussion_r34947085","pull_request_url":"https://api.github.com/repos/cakephp/migrations/pulls/101","_links":{"self":{"href":"https://api.github.com/repos/cakephp/migrations/pulls/comments/34947085"},"html":{"href":"https://github.com/cakephp/migrations/pull/101#discussion_r34947085"},"pull_request":{"href":"https://api.github.com/repos/cakephp/migrations/pulls/101"}}},"pull_request":{"url":"https://api.github.com/repos/cakephp/migrations/pulls/101","id":40274013,"html_url":"https://github.com/cakephp/migrations/pull/101","diff_url":"https://github.com/cakephp/migrations/pull/101.diff","patch_url":"https://github.com/cakephp/migrations/pull/101.patch","issue_url":"https://api.github.com/repos/cakephp/migrations/issues/101","number":101,"state":"open","locked":false,"title":"Tables need to be ordered to respect foreign keys constraints dependencies","user":{"login":"HavokInspiration","id":5243386,"avatar_url":"https://avatars.githubusercontent.com/u/5243386?v=3","gravatar_id":"","url":"https://api.github.com/users/HavokInspiration","html_url":"https://github.com/HavokInspiration","followers_url":"https://api.github.com/users/HavokInspiration/followers","following_url":"https://api.github.com/users/HavokInspiration/following{/other_user}","gists_url":"https://api.github.com/users/HavokInspiration/gists{/gist_id}","starred_url":"https://api.github.com/users/HavokInspiration/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/HavokInspiration/subscriptions","organizations_url":"https://api.github.com/users/HavokInspiration/orgs","repos_url":"https://api.github.com/users/HavokInspiration/repos","events_url":"https://api.github.com/users/HavokInspiration/events{/privacy}","received_events_url":"https://api.github.com/users/HavokInspiration/received_events","type":"User","site_admin":false},"body":"When tables are fetched from the database, they need to be ordered following foreign keys constraints dependencies to avoid table creation referencing tables that do not exist yet.\r\n\r\nWhen dropping tables, their order needs to be reversed to avoid constraints failure.\r\n\r\nI added a new ``ArticlesFixture`` to test the behaviour which has a constraint on ``CategoriesFixture``. Since it is alphabetically before and the ``categories`` table should be created before the ``articles`` table is, it allows to check the good ordering.\r\n\r\nI also fixed a docblock along the way\r\n\r\nRefs #100 ","created_at":"2015-07-17T21:38:25Z","updated_at":"2015-07-18T12:17:55Z","closed_at":null,"merged_at":null,"merge_commit_sha":"6826a22fff10dd0dd8b368304b7b6d4a7b3fd571","assignee":null,"milestone":{"url":"https://api.github.com/repos/cakephp/migrations/milestones/6","html_url":"https://github.com/cakephp/migrations/milestones/1.1.5","labels_url":"https://api.github.com/repos/cakephp/migrations/milestones/6/labels","id":1203353,"number":6,"title":"1.1.5","description":null,"creator":{"login":"HavokInspiration","id":5243386,"avatar_url":"https://avatars.githubusercontent.com/u/5243386?v=3","gravatar_id":"","url":"https://api.github.com/users/HavokInspiration","html_url":"https://github.com/HavokInspiration","followers_url":"https://api.github.com/users/HavokInspiration/followers","following_url":"https://api.github.com/users/HavokInspiration/following{/other_user}","gists_url":"https://api.github.com/users/HavokInspiration/gists{/gist_id}","starred_url":"https://api.github.com/users/HavokInspiration/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/HavokInspiration/subscriptions","organizations_url":"https://api.github.com/users/HavokInspiration/orgs","repos_url":"https://api.github.com/users/HavokInspiration/repos","events_url":"https://api.github.com/users/HavokInspiration/events{/privacy}","received_events_url":"https://api.github.com/users/HavokInspiration/received_events","type":"User","site_admin":false},"open_issues":8,"closed_issues":3,"state":"open","created_at":"2015-07-11T12:24:10Z","updated_at":"2015-07-17T22:15:07Z","due_on":null,"closed_at":null},"commits_url":"https://api.github.com/repos/cakephp/migrations/pulls/101/commits","review_comments_url":"https://api.github.com/repos/cakephp/migrations/pulls/101/comments","review_comment_url":"https://api.github.com/repos/cakephp/migrations/pulls/comments{/number}","comments_url":"https://api.github.com/repos/cakephp/migrations/issues/101/comments","statuses_url":"https://api.github.com/repos/cakephp/migrations/statuses/401e2d9301e2c74f5cf4ee6becd947208adb453c","head":{"label":"HavokInspiration:tables-order-fk","ref":"tables-order-fk","sha":"401e2d9301e2c74f5cf4ee6becd947208adb453c","user":{"login":"HavokInspiration","id":5243386,"avatar_url":"https://avatars.githubusercontent.com/u/5243386?v=3","gravatar_id":"","url":"https://api.github.com/users/HavokInspiration","html_url":"https://github.com/HavokInspiration","followers_url":"https://api.github.com/users/HavokInspiration/followers","following_url":"https://api.github.com/users/HavokInspiration/following{/other_user}","gists_url":"https://api.github.com/users/HavokInspiration/gists{/gist_id}","starred_url":"https://api.github.com/users/HavokInspiration/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/HavokInspiration/subscriptions","organizations_url":"https://api.github.com/users/HavokInspiration/orgs","repos_url":"https://api.github.com/users/HavokInspiration/repos","events_url":"https://api.github.com/users/HavokInspiration/events{/privacy}","received_events_url":"https://api.github.com/users/HavokInspiration/received_events","type":"User","site_admin":false},"repo":{"id":33321980,"name":"migrations","full_name":"HavokInspiration/migrations","owner":{"login":"HavokInspiration","id":5243386,"avatar_url":"https://avatars.githubusercontent.com/u/5243386?v=3","gravatar_id":"","url":"https://api.github.com/users/HavokInspiration","html_url":"https://github.com/HavokInspiration","followers_url":"https://api.github.com/users/HavokInspiration/followers","following_url":"https://api.github.com/users/HavokInspiration/following{/other_user}","gists_url":"https://api.github.com/users/HavokInspiration/gists{/gist_id}","starred_url":"https://api.github.com/users/HavokInspiration/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/HavokInspiration/subscriptions","organizations_url":"https://api.github.com/users/HavokInspiration/orgs","repos_url":"https://api.github.com/users/HavokInspiration/repos","events_url":"https://api.github.com/users/HavokInspiration/events{/privacy}","received_events_url":"https://api.github.com/users/HavokInspiration/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/HavokInspiration/migrations","description":"CakePHP 3.0 database migrations plugin","fork":true,"url":"https://api.github.com/repos/HavokInspiration/migrations","forks_url":"https://api.github.com/repos/HavokInspiration/migrations/forks","keys_url":"https://api.github.com/repos/HavokInspiration/migrations/keys{/key_id}","collaborators_url":"https://api.github.com/repos/HavokInspiration/migrations/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/HavokInspiration/migrations/teams","hooks_url":"https://api.github.com/repos/HavokInspiration/migrations/hooks","issue_events_url":"https://api.github.com/repos/HavokInspiration/migrations/issues/events{/number}","events_url":"https://api.github.com/repos/HavokInspiration/migrations/events","assignees_url":"https://api.github.com/repos/HavokInspiration/migrations/assignees{/user}","branches_url":"https://api.github.com/repos/HavokInspiration/migrations/branches{/branch}","tags_url":"https://api.github.com/repos/HavokInspiration/migrations/tags","blobs_url":"https://api.github.com/repos/HavokInspiration/migrations/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/HavokInspiration/migrations/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/HavokInspiration/migrations/git/refs{/sha}","trees_url":"https://api.github.com/repos/HavokInspiration/migrations/git/trees{/sha}","statuses_url":"https://api.github.com/repos/HavokInspiration/migrations/statuses/{sha}","languages_url":"https://api.github.com/repos/HavokInspiration/migrations/languages","stargazers_url":"https://api.github.com/repos/HavokInspiration/migrations/stargazers","contributors_url":"https://api.github.com/repos/HavokInspiration/migrations/contributors","subscribers_url":"https://api.github.com/repos/HavokInspiration/migrations/subscribers","subscription_url":"https://api.github.com/repos/HavokInspiration/migrations/subscription","commits_url":"https://api.github.com/repos/HavokInspiration/migrations/commits{/sha}","git_commits_url":"https://api.github.com/repos/HavokInspiration/migrations/git/commits{/sha}","comments_url":"https://api.github.com/repos/HavokInspiration/migrations/comments{/number}","issue_comment_url":"https://api.github.com/repos/HavokInspiration/migrations/issues/comments{/number}","contents_url":"https://api.github.com/repos/HavokInspiration/migrations/contents/{+path}","compare_url":"https://api.github.com/repos/HavokInspiration/migrations/compare/{base}...{head}","merges_url":"https://api.github.com/repos/HavokInspiration/migrations/merges","archive_url":"https://api.github.com/repos/HavokInspiration/migrations/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/HavokInspiration/migrations/downloads","issues_url":"https://api.github.com/repos/HavokInspiration/migrations/issues{/number}","pulls_url":"https://api.github.com/repos/HavokInspiration/migrations/pulls{/number}","milestones_url":"https://api.github.com/repos/HavokInspiration/migrations/milestones{/number}","notifications_url":"https://api.github.com/repos/HavokInspiration/migrations/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/HavokInspiration/migrations/labels{/name}","releases_url":"https://api.github.com/repos/HavokInspiration/migrations/releases{/id}","created_at":"2015-04-02T17:22:49Z","updated_at":"2015-04-02T17:22:49Z","pushed_at":"2015-07-17T22:14:23Z","git_url":"git://github.com/HavokInspiration/migrations.git","ssh_url":"git@github.com:HavokInspiration/migrations.git","clone_url":"https://github.com/HavokInspiration/migrations.git","svn_url":"https://github.com/HavokInspiration/migrations","homepage":null,"size":450,"stargazers_count":0,"watchers_count":0,"language":"PHP","has_issues":false,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":0,"mirror_url":null,"open_issues_count":0,"forks":0,"open_issues":0,"watchers":0,"default_branch":"master"}},"base":{"label":"cakephp:master","ref":"master","sha":"a53d92450bdf8ac87f8c3c9f10af4fd4466c60b4","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":23262129,"name":"migrations","full_name":"cakephp/migrations","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/migrations","description":"CakePHP 3.0 database migrations plugin","fork":false,"url":"https://api.github.com/repos/cakephp/migrations","forks_url":"https://api.github.com/repos/cakephp/migrations/forks","keys_url":"https://api.github.com/repos/cakephp/migrations/keys{/key_id}","collaborators_url":"https://api.github.com/repos/cakephp/migrations/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/cakephp/migrations/teams","hooks_url":"https://api.github.com/repos/cakephp/migrations/hooks","issue_events_url":"https://api.github.com/repos/cakephp/migrations/issues/events{/number}","events_url":"https://api.github.com/repos/cakephp/migrations/events","assignees_url":"https://api.github.com/repos/cakephp/migrations/assignees{/user}","branches_url":"https://api.github.com/repos/cakephp/migrations/branches{/branch}","tags_url":"https://api.github.com/repos/cakephp/migrations/tags","blobs_url":"https://api.github.com/repos/cakephp/migrations/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/cakephp/migrations/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/cakephp/migrations/git/refs{/sha}","trees_url":"https://api.github.com/repos/cakephp/migrations/git/trees{/sha}","statuses_url":"https://api.github.com/repos/cakephp/migrations/statuses/{sha}","languages_url":"https://api.github.com/repos/cakephp/migrations/languages","stargazers_url":"https://api.github.com/repos/cakephp/migrations/stargazers","contributors_url":"https://api.github.com/repos/cakephp/migrations/contributors","subscribers_url":"https://api.github.com/repos/cakephp/migrations/subscribers","subscription_url":"https://api.github.com/repos/cakephp/migrations/subscription","commits_url":"https://api.github.com/repos/cakephp/migrations/commits{/sha}","git_commits_url":"https://api.github.com/repos/cakephp/migrations/git/commits{/sha}","comments_url":"https://api.github.com/repos/cakephp/migrations/comments{/number}","issue_comment_url":"https://api.github.com/repos/cakephp/migrations/issues/comments{/number}","contents_url":"https://api.github.com/repos/cakephp/migrations/contents/{+path}","compare_url":"https://api.github.com/repos/cakephp/migrations/compare/{base}...{head}","merges_url":"https://api.github.com/repos/cakephp/migrations/merges","archive_url":"https://api.github.com/repos/cakephp/migrations/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/cakephp/migrations/downloads","issues_url":"https://api.github.com/repos/cakephp/migrations/issues{/number}","pulls_url":"https://api.github.com/repos/cakephp/migrations/pulls{/number}","milestones_url":"https://api.github.com/repos/cakephp/migrations/milestones{/number}","notifications_url":"https://api.github.com/repos/cakephp/migrations/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/cakephp/migrations/labels{/name}","releases_url":"https://api.github.com/repos/cakephp/migrations/releases{/id}","created_at":"2014-08-23T17:40:26Z","updated_at":"2015-06-24T06:02:29Z","pushed_at":"2015-07-17T22:14:23Z","git_url":"git://github.com/cakephp/migrations.git","ssh_url":"git@github.com:cakephp/migrations.git","clone_url":"https://github.com/cakephp/migrations.git","svn_url":"https://github.com/cakephp/migrations","homepage":null,"size":953,"stargazers_count":53,"watchers_count":53,"language":"PHP","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":23,"mirror_url":null,"open_issues_count":10,"forks":23,"open_issues":10,"watchers":53,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/cakephp/migrations/pulls/101"},"html":{"href":"https://github.com/cakephp/migrations/pull/101"},"issue":{"href":"https://api.github.com/repos/cakephp/migrations/issues/101"},"comments":{"href":"https://api.github.com/repos/cakephp/migrations/issues/101/comments"},"review_comments":{"href":"https://api.github.com/repos/cakephp/migrations/pulls/101/comments"},"review_comment":{"href":"https://api.github.com/repos/cakephp/migrations/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/cakephp/migrations/pulls/101/commits"},"statuses":{"href":"https://api.github.com/repos/cakephp/migrations/statuses/401e2d9301e2c74f5cf4ee6becd947208adb453c"}}}}