├── pix └── icon.png ├── db └── access.php ├── lang └── en │ └── repository_github.php ├── version.php └── lib.php /pix/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/marinaglancy/moodle-repository_github/master/pix/icon.png -------------------------------------------------------------------------------- /db/access.php: -------------------------------------------------------------------------------- 1 | . 16 | 17 | /** 18 | * Plugin capabilities. 19 | * 20 | * @package repository_github 21 | * @copyright 2012 Dan Poltawski 22 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 23 | */ 24 | 25 | defined('MOODLE_INTERNAL') || die(); 26 | 27 | $capabilities = array( 28 | 29 | 'repository/github:view' => array( 30 | 'captype' => 'read', 31 | 'contextlevel' => CONTEXT_MODULE, 32 | 'archetypes' => array( 33 | ) 34 | ) 35 | ); 36 | -------------------------------------------------------------------------------- /lang/en/repository_github.php: -------------------------------------------------------------------------------- 1 | . 16 | 17 | /** 18 | * Lang strings for github 19 | * 20 | * @package repository_github 21 | * @copyright 2012 Dan Poltawski 22 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 23 | */ 24 | 25 | $string['branches'] = 'Branches'; 26 | $string['configplugin'] = 'Configure GitHub repository'; 27 | $string['currentuser'] = 'github user: {$a}'; 28 | $string['github:view'] = 'View GitHub repository'; 29 | $string['pluginname'] = 'GitHub'; 30 | $string['repos'] = 'Repositories'; 31 | $string['tags'] = 'Tags'; 32 | $string['username'] = 'GitHub username:'; 33 | 34 | -------------------------------------------------------------------------------- /version.php: -------------------------------------------------------------------------------- 1 | . 16 | 17 | /** 18 | * Version information 19 | * 20 | * @package repository_github 21 | * @copyright 2012 Dan Poltawski 22 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 23 | */ 24 | 25 | defined('MOODLE_INTERNAL') || die(); 26 | 27 | $plugin->version = 2012071100; // The current plugin version (Date: YYYYMMDDXX). 28 | $plugin->requires = 2012062500; // Requires this Moodle version. 29 | $plugin->component = 'repository_github'; // Full name of the plugin (used for diagnostics). 30 | $plugin->release = '0.2'; 31 | $plugin->maturity = MATURITY_BETA; 32 | -------------------------------------------------------------------------------- /lib.php: -------------------------------------------------------------------------------- 1 | . 16 | 17 | /** 18 | * Simple repository plugin for downloading zipballs from github tags 19 | * 20 | * @package repository_github 21 | * @copyright 2012 Dan Poltawski 22 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 23 | */ 24 | require_once($CFG->dirroot . '/repository/lib.php'); 25 | 26 | /** 27 | * Simple repository plugin for downloading zipballs from github tags 28 | * 29 | * @package repository_github 30 | * @copyright 2012 Dan Poltawski 31 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 32 | */ 33 | class repository_github extends repository { 34 | /** user preference key for username */ 35 | const PREFNAME = 'repository_github_username'; 36 | /** Base of uri for github api requests */ 37 | const APIBASE = 'https://api.github.com'; 38 | /** @var string username for which we are browsing */ 39 | private $username = ''; 40 | 41 | /** 42 | * Check if we are 'logged in' (have a github 43 | * user prefence) 44 | * 45 | * @return bool true if logged in 46 | */ 47 | public function check_login() { 48 | // We've already set a github username. 49 | $username = get_user_preferences(self::PREFNAME, ''); 50 | if (!empty($username)) { 51 | if ($this->validate_user($username)) { 52 | return true; 53 | } 54 | } 55 | 56 | // A username has been submitted from form. 57 | $submitted = optional_param('github_username', '', PARAM_ALPHANUM); 58 | if (!empty($submitted)) { 59 | if ($this->validate_user($submitted)) { 60 | set_user_preference(self::PREFNAME, $submitted); 61 | return true; 62 | } 63 | } 64 | 65 | return false; 66 | } 67 | 68 | private function validate_user($username) { 69 | $c = new curl(); 70 | $json = $c->get(self::APIBASE.'/users/'.$username); 71 | if ($c->info['http_code'] !== 200 or empty($json)) { 72 | return false; 73 | } 74 | 75 | $this->username = $username; 76 | return true; 77 | } 78 | 79 | public function print_login() { 80 | $username = new stdClass(); 81 | $username->label = get_string('username', 'repository_github'); 82 | $username->type = 'text'; 83 | $username->name = 'github_username'; 84 | $username->value = ''; 85 | 86 | return array('login' => array($username)); 87 | } 88 | 89 | public function logout() { 90 | $this->username = ''; 91 | unset_user_preference(self::PREFNAME); 92 | return $this->print_login(); 93 | } 94 | 95 | /** 96 | * Print files listing. We display the users repositories 97 | * and then allow tag zipballs to be downloaded 98 | * 99 | * @param string $path the github repository name 100 | * @param string $page the page number of file list 101 | * @return array the list of files, including meta infomation 102 | */ 103 | public function get_listing($path='', $page = '') { 104 | $ret = array(); 105 | $ret['dynload'] = true; 106 | $ret['nosearch'] = true; 107 | $ret['logouttext'] = get_string('currentuser', 'repository_github', $this->username); 108 | $ret['path'] = array(array('name'=>get_string('repos', 'repository_github'), 'path'=>'')); 109 | 110 | if (empty($path)) { 111 | $ret['list'] = $this->list_repositories(); 112 | } else { 113 | 114 | $pieces = explode('/', $path); 115 | $ret['path'][] = array('name'=> $pieces[0], 'path'=> $pieces[0]); 116 | 117 | if (count($pieces) > 1) { 118 | 119 | if ($pieces[1] === 'tags') { 120 | $ret['path'][] = array('name'=> get_string('tags', 'repository_github'), 'path'=> 'tags'); 121 | $ret['list'] = $this->list_repository_tags($pieces[0]); 122 | } else if ($pieces[1] === 'branches') { 123 | $ret['path'][] = array('name'=> get_string('branches', 'repository_github'), 'path'=> 'branches'); 124 | $ret['list'] = $this->list_repository_branches($pieces[0]); 125 | } 126 | } else { 127 | $ret['list'] = $this->list_repository_metafolders($pieces[0]); 128 | } 129 | } 130 | 131 | return $ret; 132 | } 133 | 134 | private function list_repository_metafolders($repository) { 135 | global $OUTPUT; 136 | 137 | $files = array(); 138 | $files[] = array('title'=> 'Tags', 139 | 'path' => $repository.'/tags', 140 | 'thumbnail' => $OUTPUT->pix_url(file_folder_icon(90))->out(false), 141 | 'children' => array(), 142 | ); 143 | $files[] = array('title'=> 'Branches', 144 | 'path' => $repository.'/branches', 145 | 'thumbnail' => $OUTPUT->pix_url(file_folder_icon(90))->out(false), 146 | 'children' => array(), 147 | ); 148 | 149 | return $files; 150 | } 151 | 152 | private function list_repository_branches($reponame) { 153 | global $OUTPUT; 154 | 155 | $c = new curl(); 156 | $url = self::APIBASE.'/repos/'.$this->username.'/'.$reponame.'/branches'; 157 | $json = $c->get($url); 158 | 159 | if ($c->info['http_code'] !== 200 or empty($json)) { 160 | return array(); 161 | } 162 | $branches = json_decode($json); 163 | 164 | $files = array(); 165 | foreach ($branches as $branch) { 166 | $files[] = array('title'=> $reponame.'-'.$branch->name.'.zip', 167 | 'thumbnail' => $OUTPUT->pix_url(file_extension_icon('download.zip', 90))->out(false), 168 | 'source' => self::APIBASE.'/repos/'.$this->username.'/'.$reponame.'/zipball/'.$branch->name, 169 | 'shorttitle' => $branch->name, 170 | 'url' => $branch->commit->url, 171 | ); 172 | }; 173 | 174 | return $files; 175 | } 176 | 177 | /** 178 | * Returns a listing of zipballs to be downloaded 179 | * from a specified repository 180 | * 181 | * @param string $reponame the github repository 182 | * @return array listing of files for repository 183 | */ 184 | private function list_repository_tags($reponame) { 185 | global $OUTPUT; 186 | 187 | $c = new curl(); 188 | $url = self::APIBASE.'/repos/'.$this->username.'/'.$reponame.'/tags'; 189 | $json = $c->get($url); 190 | 191 | if ($c->info['http_code'] !== 200 or empty($json)) { 192 | return array(); 193 | } 194 | $tags = json_decode($json); 195 | 196 | $files = array(); 197 | foreach ($tags as $tag) { 198 | $files[] = array('title'=> $reponame.'-'.$tag->name.'.zip', 199 | 'thumbnail' => $OUTPUT->pix_url(file_extension_icon('download.zip', 90))->out(false), 200 | 'source' => $tag->zipball_url, 201 | 'shorttitle' => $tag->name, 202 | 'url' => $tag->commit->url, 203 | ); 204 | }; 205 | 206 | return $files; 207 | } 208 | 209 | /** 210 | * Returns a listing of repositories in 'repository' 211 | * folder form for browsing 212 | * 213 | * @return array listing of repositories as folders 214 | */ 215 | private function list_repositories() { 216 | global $OUTPUT; 217 | 218 | $c = new curl(); 219 | $url = self::APIBASE.'/users/'.$this->username.'/repos?sort=updated'; 220 | $json = $c->get($url); 221 | 222 | if ($c->info['http_code'] !== 200 or empty($json)) { 223 | // Unset user preference, because probably don't 224 | // want to go back here consistently. 225 | unset_user_preference(self::PREFNAME); 226 | return array(); 227 | } 228 | 229 | $repos = json_decode($json); 230 | 231 | $files = array(); 232 | foreach ($repos as $repo) { 233 | $files[] = array('title'=> $repo->name, 234 | 'date' => strtotime($repo->updated_at), 235 | 'path' => $repo->name, 236 | 'size' => $repo->size*1024, 237 | 'shorttitle' => $repo->name.': '.$repo->description, 238 | 'thumbnail' => $OUTPUT->pix_url(file_folder_icon(90))->out(false), 239 | 'children' => array(), 240 | ); 241 | }; 242 | 243 | return $files; 244 | } 245 | 246 | /** 247 | * Download a zipball from github 248 | * 249 | * @param string $url the url of file 250 | * @param string $filename save location 251 | * @return array with elements: 252 | * path: internal location of the file 253 | * url: URL to the source (from parameters) 254 | */ 255 | public function get_file($url, $filename = '') { 256 | $path = $this->prepare_file($filename); 257 | 258 | $fp = fopen($path, 'w'); 259 | $c = new curl(); 260 | $c->setopt(array('CURLOPT_FOLLOWLOCATION' => true, 'CURLOPT_MAXREDIRS' => 3)); 261 | $result = $c->download(array(array('url' => $url, 'file'=> $fp))); 262 | 263 | // Close file handler. 264 | fclose($fp); 265 | if (empty($result)) { 266 | unlink($path); 267 | return null; 268 | } 269 | return array('path'=>$path, 'url'=>$url); 270 | } 271 | 272 | public function supported_filetypes() { 273 | return array('application/zip'); 274 | } 275 | public function supported_returntypes() { 276 | return FILE_INTERNAL | FILE_EXTERNAL; 277 | } 278 | } 279 | --------------------------------------------------------------------------------