{"action":"created","comment":{"url":"https://api.github.com/repos/anodyne/nova/pulls/comments/213288920","pull_request_review_id":149889663,"id":213288920,"node_id":"MDI0OlB1bGxSZXF1ZXN0UmV2aWV3Q29tbWVudDIxMzI4ODkyMA==","diff_hunk":"@@ -0,0 +1,7 @@\n+<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');\n+\n+require_once MODPATH.'core/helpers/Nova_extension_helper.php';\n+\n+class Extension_container extends Nova_extension_container { }\n+\n+class Extension_initialization_context extends Nova_extension_initialization_context { }","path":"application/helpers/extension_helper.php","position":7,"original_position":7,"commit_id":"ea464426040412624eaca272800a1ea17bb36b64","original_commit_id":"ea464426040412624eaca272800a1ea17bb36b64","user":{"login":"agentphoenix","id":14422,"node_id":"MDQ6VXNlcjE0NDIy","avatar_url":"https://avatars3.githubusercontent.com/u/14422?v=4","gravatar_id":"","url":"https://api.github.com/users/agentphoenix","html_url":"https://github.com/agentphoenix","followers_url":"https://api.github.com/users/agentphoenix/followers","following_url":"https://api.github.com/users/agentphoenix/following{/other_user}","gists_url":"https://api.github.com/users/agentphoenix/gists{/gist_id}","starred_url":"https://api.github.com/users/agentphoenix/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/agentphoenix/subscriptions","organizations_url":"https://api.github.com/users/agentphoenix/orgs","repos_url":"https://api.github.com/users/agentphoenix/repos","events_url":"https://api.github.com/users/agentphoenix/events{/privacy}","received_events_url":"https://api.github.com/users/agentphoenix/received_events","type":"User","site_admin":false},"body":"No spaces between braces.","created_at":"2018-08-28T12:16:28Z","updated_at":"2018-08-28T12:31:57Z","html_url":"https://github.com/anodyne/nova/pull/284#discussion_r213288920","pull_request_url":"https://api.github.com/repos/anodyne/nova/pulls/284","author_association":"MEMBER","_links":{"self":{"href":"https://api.github.com/repos/anodyne/nova/pulls/comments/213288920"},"html":{"href":"https://github.com/anodyne/nova/pull/284#discussion_r213288920"},"pull_request":{"href":"https://api.github.com/repos/anodyne/nova/pulls/284"}},"in_reply_to_id":213288783},"pull_request":{"url":"https://api.github.com/repos/anodyne/nova/pulls/284","id":211218575,"node_id":"MDExOlB1bGxSZXF1ZXN0MjExMjE4NTc1","html_url":"https://github.com/anodyne/nova/pull/284","diff_url":"https://github.com/anodyne/nova/pull/284.diff","patch_url":"https://github.com/anodyne/nova/pull/284.patch","issue_url":"https://api.github.com/repos/anodyne/nova/issues/284","number":284,"state":"open","locked":false,"title":"Basic Extension and Event Support","user":{"login":"jonmatterson","id":2497540,"node_id":"MDQ6VXNlcjI0OTc1NDA=","avatar_url":"https://avatars3.githubusercontent.com/u/2497540?v=4","gravatar_id":"","url":"https://api.github.com/users/jonmatterson","html_url":"https://github.com/jonmatterson","followers_url":"https://api.github.com/users/jonmatterson/followers","following_url":"https://api.github.com/users/jonmatterson/following{/other_user}","gists_url":"https://api.github.com/users/jonmatterson/gists{/gist_id}","starred_url":"https://api.github.com/users/jonmatterson/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jonmatterson/subscriptions","organizations_url":"https://api.github.com/users/jonmatterson/orgs","repos_url":"https://api.github.com/users/jonmatterson/repos","events_url":"https://api.github.com/users/jonmatterson/events{/privacy}","received_events_url":"https://api.github.com/users/jonmatterson/received_events","type":"User","site_admin":false},"body":"This pull request adds support for two new libraries:\r\n\r\n* Events: A library that supports listeners that triggers events and provides callbacks that can listen for an event or a namespace of events.\r\n* Extensions: A library that looks at a config file to load in a set of extensions, each of which are loaded by executing the extension's `init.php` file.\r\n\r\nTogether, these two libraries make it possible to write extensions installed with only the following three steps:\r\n\r\n1. Copy the extension's source files into `application/extensions/EXTENSION_NAME`\r\n2. Add EXTENSION_NAME to `application/config/extensions.php`\r\n3. Update the database as necessary\r\n\r\nIn the future, it might be nice to remove step (3), but this pull request is just the foundation of it.\r\n\r\nOnce this occurs, extensions can run that simply hook into the event library, with events supported in this PR to allow for changing data before CRUD operations are performed, as well as to mutate view data before a view is loaded and to modify the output of the view before it's passed back from `Location::view()`. It is likely we will want to add a few more of these events before we release 2.6, likely with events around other `Location` methods (and other places?).\r\n\r\nI've included some comments to explain what's going on, but better than that, here are some simple examples...\r\n\r\n## Extension Example Code\r\n\r\nThis example adds two extensions, `jquery` for a little `generator` helper that's exposed via access to the extension container and `bfms_character` which modifies the character page, join form, and edit form to add a new field and display content driven from an external API.\r\n\r\n#### `application/config/extensions.php`\r\n\r\n```php\r\n<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');\r\n\r\nrequire_once MODPATH.'core/config/nova_extensions.php';\r\n\r\n$config['extensions']['enabled'][] = 'jquery';\r\n$config['extensions']['enabled'][] = 'bfms_character';\r\n```\r\n\r\n#### `application/extensions/jquery/init.php`\r\n\r\n```php\r\n<?php \r\nrequire_once dirname(__FILE__).'/libraries/jquery_generator.php';\r\n\r\n$this->attach('generator', new jquery_generator());\r\n```\r\n\r\n#### `application/extensions/jquery/libraries/jquery_generator.php`\r\n\r\n```php\r\n<?php \r\nclass jquery_generator\r\n{\r\n  public function select($selector)\r\n  {\r\n    return new jquery_generator_chain($selector);\r\n  }\r\n}\r\n\r\nclass jquery_generator_chain\r\n{\r\n  public $selector;\r\n  public $chain = [];\r\n  \r\n  public function __construct($selector)\r\n  {\r\n    $this->selector = $selector;\r\n  }\r\n  \r\n  public function __call($method, $args = [])\r\n  {\r\n    if(in_array($method, ['first','last','before','after','append','prepend','html','text'])){\r\n      $this->chain[] = [\r\n        'type' => 'method',\r\n        'name' => $method, \r\n        'args' => $args\r\n      ];\r\n    }else{\r\n      show_error('Unsupported jquery_generator_chain method: '.$method);\r\n    }\r\n    return $this;\r\n  }\r\n  \r\n  public function __toString()\r\n  {\r\n    return '<script type=\"text/javascript\">'.implode('.', array_merge([\r\n      '$('.json_encode($this->selector).')'\r\n    ], array_map(function($entry){\r\n      switch($entry['type']){\r\n        case 'method':\r\n          return $entry['name'].'('.implode(',', array_map(function($arg){\r\n            return json_encode($arg);\r\n          }, $entry['args'])).')';\r\n      }\r\n    }, $this->chain))).'</script>';\r\n  }\r\n}\r\n```\r\n\r\n#### `application/extensions/bfms_character/init.php`\r\n\r\n```php\r\n<?php\r\n\r\nrequire_once dirname(__FILE__).'/helpers/bfms_character_api_helper.php';\r\n\r\n$this->require_extension('jquery');\r\n\r\n$this->event->listen(['db', 'insert', 'prepare', 'characters', 'main', 'join'], function($event){\r\n  if(empty($event['data']['bfms_character_url']) && $this->input->post('bfms_character_url', true))\r\n    $event['data']['bfms_character_url'] = $this->input->post('bfms_character_url', true);\r\n});\r\n\r\n$this->event->listen(['location', 'view', 'data', 'main', 'main_join_2'], function($event){\r\n  $event['data']['label']['bfms'] = 'Bravo Fleet Management System';\r\n  $event['data']['label']['bfms_instructions'] = 'If you provide the URL to your character within BFMS, the data from BFMS will be displayed so that you do not have to duplicate it.';\r\n  $event['data']['label']['bfms_character_url'] = 'Character URL';\r\n  $event['data']['inputs']['bfms_character_url'] = array(\r\n    'name' => 'bfms_character_url',\r\n    'id' => 'bfms_character_url'\r\n  );\r\n});\r\n\r\n$this->event->listen(['location', 'view', 'output', 'main', 'main_join_2'], function($event){\r\n  $event['output'] .= $this->extension['jquery']['generator']\r\n                  ->select('#three')\r\n                  ->prepend($this->extension['bfms_character']->view('characters_bio', $this->skin, 'admin', $event['data']));\r\n});\r\n\r\n$this->event->listen(['location', 'view', 'data', 'admin', 'characters_create'], function($event){\r\n  $event['data']['label']['bfms'] = 'Bravo Fleet Management System';\r\n  $event['data']['label']['bfms_instructions'] = 'If you provide the URL to your character within BFMS, the data from BFMS will be displayed so that you do not have to duplicate it.';\r\n  $event['data']['label']['bfms_character_url'] = 'Character URL';\r\n  $event['data']['inputs']['bfms_character_url'] = array(\r\n    'name' => 'bfms_character_url',\r\n    'id' => 'bfms_character_url'\r\n  );\r\n});\r\n\r\n$this->event->listen(['location', 'view', 'output', 'admin', 'characters_create'], function($event){\r\n  $event['output'] .= $this->extension['jquery']['generator']\r\n                  ->select('#two')\r\n                  ->prepend($this->extension['bfms_character']->view('characters_bio', $this->skin, 'admin', $event['data']));\r\n});\r\n\r\n$this->event->listen(['location', 'view', 'data', 'admin', 'characters_bio'], function($event){\r\n  $id = $this->uri->segment(3);\r\n  $char = $this->char->get_character($id);\r\n  $event['data']['label']['bfms'] = 'Bravo Fleet Management System';\r\n  $event['data']['label']['bfms_instructions'] = 'If you provide the URL to your character within BFMS, the data from BFMS will be displayed so that you do not have to duplicate it.';\r\n  $event['data']['label']['bfms_character_url'] = 'Character URL';\r\n  $event['data']['inputs']['bfms_character_url'] = array(\r\n    'name' => 'bfms_character_url',\r\n    'id' => 'bfms_character_url',\r\n    'value' => $char->bfms_character_url\r\n  );\r\n});\r\n\r\n$this->event->listen(['location', 'view', 'output', 'admin', 'characters_bio'], function($event){\r\n  $event['output'] .= $this->extension['jquery']['generator']\r\n                  ->select('#two')\r\n                  ->prepend($this->extension['bfms_character']->view('characters_bio', $this->skin, 'admin', $event['data']));\r\n});\r\n\r\n$this->event->listen(['location', 'view', 'data', 'main', 'personnel_character'], function($event){\r\n  $id = $this->uri->segment(3);\r\n  $char = $this->char->get_character($id);\r\n  $content = bfms_character__api__get_character($char);\r\n  $event['data']['bfms_character'] = json_decode($content, true);\r\n});\r\n\r\n$this->event->listen(['location', 'view', 'output', 'main', 'personnel_character'], function($event){\r\n  $event['output'] .= $this->extension['jquery']['generator']\r\n                  ->select('#tabs')\r\n                  ->append($this->extension['bfms_character']->view('personnel_character', $this->skin, 'main', $event['data']));\r\n});\r\n```\r\n\r\n#### `application/extensions/bfms_character/helpers/bfms_character_api_helper.php`\r\n\r\n```php\r\n<?php \r\n\r\nif(!function_exists('bfms_character__api__get_character'))\r\n{\r\n  function bfms_character__api__get_character($char)\r\n  {\r\n    $apiUrl = preg_replace('/character\\/(\\d+)/i', 'wp-json/wp/v2/character/$1', $char->bfms_character_url);\r\n    $ch = curl_init();\r\n    curl_setopt_array($ch, array(\r\n      CURLOPT_RETURNTRANSFER => true,\r\n      CURLOPT_HEADER         => false,\r\n      CURLOPT_USERAGENT      => \"nova\",\r\n    ));\r\n    curl_setopt($ch, CURLOPT_URL, $apiUrl);\r\n    $content = curl_exec($ch);\r\n    curl_close($ch);\r\n    return $content;\r\n  }\r\n}\r\n```\r\n\r\n#### `application/extensions/bfms_character/views/admin/pages/characters_bio.php`\r\n\r\n```php\r\n<?php echo text_output($label['bfms'], 'h3', 'page-subhead'); ?>\r\n\r\n<div class=\"indent-left\" id=\"bfms_character_fields\">\r\n \r\n <?php echo text_output($label['bfms_instructions'], 'p'); ?>\r\n \r\n <p>\r\n   <kbd><?php echo $label['bfms_character_url'] ?></kbd>\r\n   <?php echo form_input($inputs['bfms_character_url']) ?>\r\n </p>\r\n \r\n <script type=\"text/javascript\">\r\n $(\"#<?php echo $inputs['bfms_character_url']['id'] ?>\").change(function(){\r\n  var method;\r\n  if($(this).val().trim().length > 0){\r\n    method = 'hide';\r\n  }else{\r\n    method = 'show';\r\n  }\r\n  $('textarea#history').parent()[method]();\r\n  $('textarea#service_record').parent()[method]();\r\n }).change();\r\n </script>\r\n</div><br/>\r\n```\r\n\r\n#### `application/extensions/bfms_character/views/main/pages/personnel_character.php`\r\n\r\n```php\r\n<?php if($bfms_character): ?>\r\n  \r\n<div id=\"bfms_history\" class=\"ui-tabs-panel ui-widget-content ui-corner-bottom ui-tabs-hide\" style=\"padding-top:18px;\">\r\n  \r\n  <?php echo $bfms_character['bio']['history'];?>\r\n  \r\n</div>\r\n  \r\n<div id=\"bfms_service_record\" class=\"ui-tabs-panel ui-widget-content ui-corner-bottom ui-tabs-hide\">\r\n  \r\n  <table class=\"table100 zebra\">\r\n  <?php foreach($bfms_character['bio']['service_record'] as $item): ?>\r\n    \r\n    <tr>\r\n      <td><?php echo $item['year_start']; ?></td>\r\n      <td><?php echo $item['year_end']; ?></td>\r\n      <td style=\"text-align:center;line-height:1;\">\r\n        <?php if(!empty($item['rank_image_url'])): ?>\r\n        <img src=\"<?php echo $item['rank_image_url']; ?>\" style=\"margin-top:2px;\">\r\n        <br>\r\n        <small style=\"font-size:11px\"><?php echo $item['rank_name']; ?></small>\r\n        <?php else: ?>\r\n        <?php echo $item['rank_name']; ?>\r\n        <?php endif; ?>\r\n      </td>\r\n      <td><?php echo $item['position']; ?><br><em style=\"font-size:12px\"><?php echo $item['assignment']; ?></em></td>\r\n    </tr>\r\n    \r\n  <?php endforeach; ?>\r\n  </table>\r\n  \r\n</div>\r\n\r\n\r\n<script type=\"text/javascript\">\r\n$('#tabs > ul > li:contains(\"History\")').hide();\r\n$('#tabs > ul').append('<li><a href=\"#bfms_history\"><span>History</span></a></li>');\r\n$('#tabs > ul').append('<li><a href=\"#bfms_service_record\"><span>Service Record</span></a></li>');\r\n</script>\r\n  \r\n<?php endif; ?>\r\n```\r\n\r\n## Extension Example Outcome \r\n\r\nThe outcome of this is that without requiring the Nova user to make any changes to their Nova controllers or views, the extension is able to modify the tabs on the character page such as:\r\n\r\n<img width=\"1401\" alt=\"screen shot 2018-08-27 at 12 14 02 am\" src=\"https://user-images.githubusercontent.com/2497540/44683311-d37e7b80-a9fa-11e8-8906-e112ce0ca238.png\">\r\n\r\nAnd new fields in the edit and join screens (including saving the new fields) such as:\r\n\r\n<img width=\"1376\" alt=\"screen shot 2018-08-27 at 1 13 04 pm\" src=\"https://user-images.githubusercontent.com/2497540/44683353-fa3cb200-a9fa-11e8-96f9-fbe338b2d349.png\">\r\n\r\nSure, there's some trickery in how you write the views, inject content into the output string, etc., but that's kind of just a consequence of the lack of modularity. It's still a very powerful way to get around requiring the user to actually copy and paste code, update a skin, etc., to add a feature.","created_at":"2018-08-27T20:16:08Z","updated_at":"2018-08-28T12:31:56Z","closed_at":null,"merged_at":null,"merge_commit_sha":"14dd97d3acc28ed20e2f3bdbbbca2e016d1549b1","assignee":null,"assignees":[],"requested_reviewers":[],"requested_teams":[],"labels":[],"milestone":null,"commits_url":"https://api.github.com/repos/anodyne/nova/pulls/284/commits","review_comments_url":"https://api.github.com/repos/anodyne/nova/pulls/284/comments","review_comment_url":"https://api.github.com/repos/anodyne/nova/pulls/comments{/number}","comments_url":"https://api.github.com/repos/anodyne/nova/issues/284/comments","statuses_url":"https://api.github.com/repos/anodyne/nova/statuses/ea464426040412624eaca272800a1ea17bb36b64","head":{"label":"jonmatterson:2.6/extensibility","ref":"2.6/extensibility","sha":"ea464426040412624eaca272800a1ea17bb36b64","user":{"login":"jonmatterson","id":2497540,"node_id":"MDQ6VXNlcjI0OTc1NDA=","avatar_url":"https://avatars3.githubusercontent.com/u/2497540?v=4","gravatar_id":"","url":"https://api.github.com/users/jonmatterson","html_url":"https://github.com/jonmatterson","followers_url":"https://api.github.com/users/jonmatterson/followers","following_url":"https://api.github.com/users/jonmatterson/following{/other_user}","gists_url":"https://api.github.com/users/jonmatterson/gists{/gist_id}","starred_url":"https://api.github.com/users/jonmatterson/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jonmatterson/subscriptions","organizations_url":"https://api.github.com/users/jonmatterson/orgs","repos_url":"https://api.github.com/users/jonmatterson/repos","events_url":"https://api.github.com/users/jonmatterson/events{/privacy}","received_events_url":"https://api.github.com/users/jonmatterson/received_events","type":"User","site_admin":false},"repo":{"id":6107556,"node_id":"MDEwOlJlcG9zaXRvcnk2MTA3NTU2","name":"nova","full_name":"jonmatterson/nova","owner":{"login":"jonmatterson","id":2497540,"node_id":"MDQ6VXNlcjI0OTc1NDA=","avatar_url":"https://avatars3.githubusercontent.com/u/2497540?v=4","gravatar_id":"","url":"https://api.github.com/users/jonmatterson","html_url":"https://github.com/jonmatterson","followers_url":"https://api.github.com/users/jonmatterson/followers","following_url":"https://api.github.com/users/jonmatterson/following{/other_user}","gists_url":"https://api.github.com/users/jonmatterson/gists{/gist_id}","starred_url":"https://api.github.com/users/jonmatterson/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jonmatterson/subscriptions","organizations_url":"https://api.github.com/users/jonmatterson/orgs","repos_url":"https://api.github.com/users/jonmatterson/repos","events_url":"https://api.github.com/users/jonmatterson/events{/privacy}","received_events_url":"https://api.github.com/users/jonmatterson/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/jonmatterson/nova","description":"Next generation online RPG management software","fork":true,"url":"https://api.github.com/repos/jonmatterson/nova","forks_url":"https://api.github.com/repos/jonmatterson/nova/forks","keys_url":"https://api.github.com/repos/jonmatterson/nova/keys{/key_id}","collaborators_url":"https://api.github.com/repos/jonmatterson/nova/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/jonmatterson/nova/teams","hooks_url":"https://api.github.com/repos/jonmatterson/nova/hooks","issue_events_url":"https://api.github.com/repos/jonmatterson/nova/issues/events{/number}","events_url":"https://api.github.com/repos/jonmatterson/nova/events","assignees_url":"https://api.github.com/repos/jonmatterson/nova/assignees{/user}","branches_url":"https://api.github.com/repos/jonmatterson/nova/branches{/branch}","tags_url":"https://api.github.com/repos/jonmatterson/nova/tags","blobs_url":"https://api.github.com/repos/jonmatterson/nova/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/jonmatterson/nova/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/jonmatterson/nova/git/refs{/sha}","trees_url":"https://api.github.com/repos/jonmatterson/nova/git/trees{/sha}","statuses_url":"https://api.github.com/repos/jonmatterson/nova/statuses/{sha}","languages_url":"https://api.github.com/repos/jonmatterson/nova/languages","stargazers_url":"https://api.github.com/repos/jonmatterson/nova/stargazers","contributors_url":"https://api.github.com/repos/jonmatterson/nova/contributors","subscribers_url":"https://api.github.com/repos/jonmatterson/nova/subscribers","subscription_url":"https://api.github.com/repos/jonmatterson/nova/subscription","commits_url":"https://api.github.com/repos/jonmatterson/nova/commits{/sha}","git_commits_url":"https://api.github.com/repos/jonmatterson/nova/git/commits{/sha}","comments_url":"https://api.github.com/repos/jonmatterson/nova/comments{/number}","issue_comment_url":"https://api.github.com/repos/jonmatterson/nova/issues/comments{/number}","contents_url":"https://api.github.com/repos/jonmatterson/nova/contents/{+path}","compare_url":"https://api.github.com/repos/jonmatterson/nova/compare/{base}...{head}","merges_url":"https://api.github.com/repos/jonmatterson/nova/merges","archive_url":"https://api.github.com/repos/jonmatterson/nova/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/jonmatterson/nova/downloads","issues_url":"https://api.github.com/repos/jonmatterson/nova/issues{/number}","pulls_url":"https://api.github.com/repos/jonmatterson/nova/pulls{/number}","milestones_url":"https://api.github.com/repos/jonmatterson/nova/milestones{/number}","notifications_url":"https://api.github.com/repos/jonmatterson/nova/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/jonmatterson/nova/labels{/name}","releases_url":"https://api.github.com/repos/jonmatterson/nova/releases{/id}","deployments_url":"https://api.github.com/repos/jonmatterson/nova/deployments","created_at":"2012-10-06T22:57:17Z","updated_at":"2015-11-03T02:33:06Z","pushed_at":"2018-08-27T20:01:21Z","git_url":"git://github.com/jonmatterson/nova.git","ssh_url":"git@github.com:jonmatterson/nova.git","clone_url":"https://github.com/jonmatterson/nova.git","svn_url":"https://github.com/jonmatterson/nova","homepage":"http://www.anodyne-productions.com/nova","size":26826,"stargazers_count":0,"watchers_count":0,"language":"PHP","has_issues":false,"has_projects":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":1,"mirror_url":null,"archived":false,"open_issues_count":0,"license":null,"forks":1,"open_issues":0,"watchers":0,"default_branch":"2.4/master"}},"base":{"label":"anodyne:2.6/develop","ref":"2.6/develop","sha":"37d9d08654f5f5d8f7eacc2f6da1a623992b7fea","user":{"login":"anodyne","id":132190,"node_id":"MDEyOk9yZ2FuaXphdGlvbjEzMjE5MA==","avatar_url":"https://avatars1.githubusercontent.com/u/132190?v=4","gravatar_id":"","url":"https://api.github.com/users/anodyne","html_url":"https://github.com/anodyne","followers_url":"https://api.github.com/users/anodyne/followers","following_url":"https://api.github.com/users/anodyne/following{/other_user}","gists_url":"https://api.github.com/users/anodyne/gists{/gist_id}","starred_url":"https://api.github.com/users/anodyne/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/anodyne/subscriptions","organizations_url":"https://api.github.com/users/anodyne/orgs","repos_url":"https://api.github.com/users/anodyne/repos","events_url":"https://api.github.com/users/anodyne/events{/privacy}","received_events_url":"https://api.github.com/users/anodyne/received_events","type":"Organization","site_admin":false},"repo":{"id":333696,"node_id":"MDEwOlJlcG9zaXRvcnkzMzM2OTY=","name":"nova","full_name":"anodyne/nova","owner":{"login":"anodyne","id":132190,"node_id":"MDEyOk9yZ2FuaXphdGlvbjEzMjE5MA==","avatar_url":"https://avatars1.githubusercontent.com/u/132190?v=4","gravatar_id":"","url":"https://api.github.com/users/anodyne","html_url":"https://github.com/anodyne","followers_url":"https://api.github.com/users/anodyne/followers","following_url":"https://api.github.com/users/anodyne/following{/other_user}","gists_url":"https://api.github.com/users/anodyne/gists{/gist_id}","starred_url":"https://api.github.com/users/anodyne/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/anodyne/subscriptions","organizations_url":"https://api.github.com/users/anodyne/orgs","repos_url":"https://api.github.com/users/anodyne/repos","events_url":"https://api.github.com/users/anodyne/events{/privacy}","received_events_url":"https://api.github.com/users/anodyne/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/anodyne/nova","description":"Premier online RPG management software","fork":false,"url":"https://api.github.com/repos/anodyne/nova","forks_url":"https://api.github.com/repos/anodyne/nova/forks","keys_url":"https://api.github.com/repos/anodyne/nova/keys{/key_id}","collaborators_url":"https://api.github.com/repos/anodyne/nova/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/anodyne/nova/teams","hooks_url":"https://api.github.com/repos/anodyne/nova/hooks","issue_events_url":"https://api.github.com/repos/anodyne/nova/issues/events{/number}","events_url":"https://api.github.com/repos/anodyne/nova/events","assignees_url":"https://api.github.com/repos/anodyne/nova/assignees{/user}","branches_url":"https://api.github.com/repos/anodyne/nova/branches{/branch}","tags_url":"https://api.github.com/repos/anodyne/nova/tags","blobs_url":"https://api.github.com/repos/anodyne/nova/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/anodyne/nova/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/anodyne/nova/git/refs{/sha}","trees_url":"https://api.github.com/repos/anodyne/nova/git/trees{/sha}","statuses_url":"https://api.github.com/repos/anodyne/nova/statuses/{sha}","languages_url":"https://api.github.com/repos/anodyne/nova/languages","stargazers_url":"https://api.github.com/repos/anodyne/nova/stargazers","contributors_url":"https://api.github.com/repos/anodyne/nova/contributors","subscribers_url":"https://api.github.com/repos/anodyne/nova/subscribers","subscription_url":"https://api.github.com/repos/anodyne/nova/subscription","commits_url":"https://api.github.com/repos/anodyne/nova/commits{/sha}","git_commits_url":"https://api.github.com/repos/anodyne/nova/git/commits{/sha}","comments_url":"https://api.github.com/repos/anodyne/nova/comments{/number}","issue_comment_url":"https://api.github.com/repos/anodyne/nova/issues/comments{/number}","contents_url":"https://api.github.com/repos/anodyne/nova/contents/{+path}","compare_url":"https://api.github.com/repos/anodyne/nova/compare/{base}...{head}","merges_url":"https://api.github.com/repos/anodyne/nova/merges","archive_url":"https://api.github.com/repos/anodyne/nova/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/anodyne/nova/downloads","issues_url":"https://api.github.com/repos/anodyne/nova/issues{/number}","pulls_url":"https://api.github.com/repos/anodyne/nova/pulls{/number}","milestones_url":"https://api.github.com/repos/anodyne/nova/milestones{/number}","notifications_url":"https://api.github.com/repos/anodyne/nova/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/anodyne/nova/labels{/name}","releases_url":"https://api.github.com/repos/anodyne/nova/releases{/id}","deployments_url":"https://api.github.com/repos/anodyne/nova/deployments","created_at":"2009-10-11T04:31:21Z","updated_at":"2018-06-06T02:47:38Z","pushed_at":"2018-08-27T20:16:09Z","git_url":"git://github.com/anodyne/nova.git","ssh_url":"git@github.com:anodyne/nova.git","clone_url":"https://github.com/anodyne/nova.git","svn_url":"https://github.com/anodyne/nova","homepage":"http://anodyne-productions.com/nova","size":28195,"stargazers_count":19,"watchers_count":19,"language":"PHP","has_issues":true,"has_projects":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":7,"mirror_url":null,"archived":false,"open_issues_count":13,"license":null,"forks":7,"open_issues":13,"watchers":19,"default_branch":"2.5/master"}},"_links":{"self":{"href":"https://api.github.com/repos/anodyne/nova/pulls/284"},"html":{"href":"https://github.com/anodyne/nova/pull/284"},"issue":{"href":"https://api.github.com/repos/anodyne/nova/issues/284"},"comments":{"href":"https://api.github.com/repos/anodyne/nova/issues/284/comments"},"review_comments":{"href":"https://api.github.com/repos/anodyne/nova/pulls/284/comments"},"review_comment":{"href":"https://api.github.com/repos/anodyne/nova/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/anodyne/nova/pulls/284/commits"},"statuses":{"href":"https://api.github.com/repos/anodyne/nova/statuses/ea464426040412624eaca272800a1ea17bb36b64"}},"author_association":"CONTRIBUTOR"}}
{"actor":{"display_login":"agentphoenix"}}