├── .gitignore ├── LICENSE.md ├── README.md └── gitplugins ├── GitPluginsPlugin.php ├── controllers └── GitPlugins_GetController.php ├── resources └── icon.svg ├── services └── GitPlugins_GetService.php ├── templates └── GitPluginsWidget.html └── widgets └── GitPlugins_GitWidget.php /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2016 Anata Creative 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # gitPlugins 2 | 3 | Get your plugins from Github straight into your Craft CMS. 4 | 5 | 6 | ## Installation 7 | 8 | 1. Download and extract the contents of the zip. Put the `gitplugins` folder to your Craft plugin folder. 9 | 2. Enable the gitPlugins plugin in Craft (Settings > Plugins). 10 | 3. Add the widget to your dashboard (Dashboard > New widget > Download Github Plugins). 11 | 12 | 13 | ## Usage 14 | 1. Get the base-url (for example: https://github.com/AnataCreative/gitPlugins) or zip-url (for example: https://github.com/AnataCreative/gitPlugins/archive/master.zip) for your plugin on Github. 15 | 2. Paste it in the input-field and click get. 16 | 3. The plugin will be downloaded and put into your plugins-folder. 17 | 4. Go to the plugins page (Settings > Plugins) and install your downloaded plugin. 18 | 5. Be awesome! :fire: 19 | 20 | 21 | ## Credits 22 | This plugin has started from the plugin uploader (https://github.com/yatryan/craft-plugin-uploader), and still has some parts of it in it. So big thanks to Taylor Ryan for that! 23 | 24 | 25 | ## Contribution 26 | Want to contribute or fix a bug? Awesome! :heart_eyes_cat:
27 | Just make a pull request to the develop branch and provide some explanation. 28 | 29 | If you are fixing a bug or adding an enhancement, please assign the issue to yourself, so people will know you're working on it. 30 | 31 | 32 | ## Roadmap 33 | Look for the issues with the tag 'enhancement'. Help is always welcome! :blush: 34 | -------------------------------------------------------------------------------- /gitplugins/GitPluginsPlugin.php: -------------------------------------------------------------------------------- 1 | _name); 21 | } 22 | 23 | public function getUrl() 24 | { 25 | return $this->_url; 26 | } 27 | 28 | public function getVersion() 29 | { 30 | return $this->_version; 31 | } 32 | 33 | public function getDeveloper() 34 | { 35 | return $this->_developer; 36 | } 37 | 38 | public function getDeveloperUrl() 39 | { 40 | return $this->_developerUrl; 41 | } 42 | 43 | public function getDescription() 44 | { 45 | return $this->_description; 46 | } 47 | 48 | public function getDocumentationUrl() 49 | { 50 | return $this->_documentationUrl; 51 | } 52 | 53 | public function getSchemaVersion() 54 | { 55 | return $this->_schemaVersion; 56 | } 57 | 58 | public function getReleaseFeedUrl() 59 | { 60 | return $this->_releaseFeedUrl; 61 | } 62 | 63 | public function getCraftRequiredVersion() 64 | { 65 | return $this->_minVersion; 66 | } 67 | 68 | public function onBeforeInstall() 69 | { 70 | if (!file_exists('../craft/storage/uploads/gitPlugins')) { 71 | mkdir('../craft/storage/uploads/gitPlugins', 0777, true); 72 | } 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /gitplugins/controllers/GitPlugins_GetController.php: -------------------------------------------------------------------------------- 1 | request->getPost('url'); 9 | 10 | $error = craft()->gitPlugins_get->getPlugin($url); 11 | 12 | if ($error) { 13 | craft()->userSession->setNotice(Craft::t($error)); 14 | } else { 15 | craft()->userSession->setNotice(Craft::t('Plugin downloaded')); 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /gitplugins/resources/icon.svg: -------------------------------------------------------------------------------- 1 | Github 2 | -------------------------------------------------------------------------------- /gitplugins/services/GitPlugins_GetService.php: -------------------------------------------------------------------------------- 1 | checkUrl($url); 20 | 21 | // Return 22 | return $error; 23 | } 24 | 25 | 26 | 27 | /** 28 | * @param string $url 29 | */ 30 | public function checkUrl($url) 31 | { 32 | // Is Github url? 33 | if (strpos($url, 'github') === false) { 34 | $error = 'Please enter a Github URL'; 35 | return $error; 36 | } 37 | 38 | // Determin Download Url 39 | if (strpos($url, '.zip')) { 40 | // Set 41 | $downloadUrl = $url; 42 | } else { 43 | // Set 44 | $downloadUrl = $url; 45 | 46 | if (substr($url, -1) !== '/') { 47 | $downloadUrl = $downloadUrl.'/'; 48 | } 49 | 50 | $downloadUrl = $downloadUrl.'archive/master.zip'; 51 | } 52 | 53 | // Get filename 54 | $http_response_header = get_headers($url); 55 | $realfilename = $this->get_real_filename($http_response_header, $url); 56 | 57 | // Determin Ziptarget and folderTarget 58 | if (strpos($realfilename, '.zip')) { 59 | $zipTarget = UPLOAD_FOLDER.'/'.$realfilename; 60 | } else { 61 | $zipTarget = UPLOAD_FOLDER.'/'.$realfilename.'-master.zip'; 62 | } 63 | 64 | $folderTarget = str_replace('.zip', '', $zipTarget); 65 | 66 | // Download 67 | $error = $this->download($zipTarget, $folderTarget, $downloadUrl); 68 | 69 | // return 70 | return $error; 71 | } 72 | 73 | 74 | 75 | /** 76 | * @param string $zipTarget 77 | * @param string $folderTarget 78 | * @param string $downloadUrl 79 | */ 80 | public function download($zipTarget, $folderTarget, $downloadUrl) 81 | { 82 | $file = @file_get_contents($downloadUrl); 83 | 84 | if ($file) { 85 | if (!is_dir(UPLOAD_FOLDER)) { 86 | $error = "Upload folder doesn't exist"; 87 | } else if (!is_writable(UPLOAD_FOLDER)) { 88 | $error = "Can't write plugin to the upload folder"; 89 | } else { 90 | file_put_contents($zipTarget, $file); 91 | 92 | $error = $this->extract($zipTarget, $folderTarget); 93 | } 94 | } else { 95 | $error = "Can't download plugin"; 96 | } 97 | 98 | return $error; 99 | } 100 | 101 | 102 | /** 103 | * @param string $zipTarget 104 | * @param string $folderTarget 105 | */ 106 | public function extract($zipTarget, $folderTarget) 107 | { 108 | $date = new DateTime(); 109 | $now = $date->getTimestamp(); 110 | $zip = new \ZipArchive(); 111 | $res = $zip->open($zipTarget); 112 | 113 | if ($res === TRUE) { 114 | $zip->extractTo(UPLOAD_FOLDER); 115 | $zip->close(); 116 | 117 | $error = $this->move($folderTarget, $zipTarget); 118 | } else { 119 | $error = "Can't extract zip"; 120 | } 121 | 122 | return $error; 123 | } 124 | 125 | 126 | /** 127 | * @param string $uploadFolder 128 | * @param string $uploadZipFile 129 | */ 130 | public function move($uploadFolder, $uploadZipFile) 131 | { 132 | $pluginExtractFile = ''; 133 | $pluginExtractFolder = ''; 134 | 135 | // Find the folder that the Plugin.php file is in. That is the root of the plugin. 136 | foreach (glob($uploadFolder."/*Plugin.php") as $filename) { 137 | $pluginExtractFile = $filename; 138 | $pluginExtractFolder = dirname($filename); 139 | } 140 | 141 | if ($pluginExtractFile === '') { 142 | foreach (glob($uploadFolder."/**/*Plugin.php") as $filename) { 143 | $pluginExtractFile = $filename; 144 | $pluginExtractFolder = dirname($filename); 145 | } 146 | } 147 | 148 | // Open the file 149 | $fp = @fopen($pluginExtractFile, 'r'); 150 | if ($fp) { 151 | $array = explode("\n", fread($fp, filesize($pluginExtractFile))); 152 | 153 | $pluginName = ''; 154 | 155 | // Get name of plugin 156 | foreach ($array as $line) { 157 | if (strpos($line, 'class') !== false && strpos($line, 'extends') !== false) { 158 | $split = explode(" ", $line); 159 | $pluginName = substr($split[1], 0, -6); 160 | break; 161 | } 162 | } 163 | 164 | // Copy to craft/plugins folder. 165 | $pluginInstallFolder = CRAFT_PLUGIN_FOLDER.'/'.strtolower($pluginName); 166 | 167 | if (!file_exists($pluginInstallFolder)) { 168 | // Copy folder to craft/plugins 169 | $this->recurse_copy($pluginExtractFolder, $pluginInstallFolder); 170 | 171 | $error = false; 172 | } 173 | else { 174 | $error = 'The plugin "'.$pluginName.'" is already uploaded.'; 175 | } 176 | } else { 177 | $error = 'The uploaded file is not a valid plugin.'; 178 | } 179 | 180 | // Remove zipfile and folder from uploads 181 | $this->rrmdir($uploadFolder); 182 | unlink($uploadZipFile); 183 | 184 | return $error; 185 | } 186 | 187 | 188 | /** 189 | * @param string $dir 190 | */ 191 | private function rrmdir($dir) 192 | { 193 | foreach (glob($dir.'/{,.}[!.,!..]*', GLOB_MARK|GLOB_BRACE) as $file) { 194 | if (is_dir($file)) { 195 | $this->rrmdir($file); 196 | } else { 197 | unlink($file); 198 | } 199 | } 200 | rmdir($dir); 201 | } 202 | 203 | 204 | /** 205 | * @param string $src 206 | * @param string $dst 207 | */ 208 | private function recurse_copy($src, $dst) 209 | { 210 | $dir = opendir($src); 211 | @mkdir($dst); 212 | 213 | while(false !== ( $file = readdir($dir)) ) { 214 | if (( $file != '.' ) && ( $file != '..' )) { 215 | if ( is_dir($src . '/' . $file) ) { 216 | $this->recurse_copy($src . '/' . $file,$dst . '/' . $file); 217 | } else { 218 | copy($src . '/' . $file,$dst . '/' . $file); 219 | } 220 | } 221 | } 222 | 223 | closedir($dir); 224 | } 225 | 226 | 227 | /** 228 | * @param string $to 229 | */ 230 | protected function move_uploaded_file($from, $to) 231 | { 232 | return move_uploaded_file($from, $to); 233 | } 234 | 235 | 236 | /** 237 | * @param string $headers 238 | * @param string $url 239 | */ 240 | protected function get_real_filename($headers, $url) 241 | { 242 | foreach($headers as $header) 243 | { 244 | if (strpos(strtolower($header),'content-disposition') !== false) 245 | { 246 | $tmp_name = explode('=', $header); 247 | if ($tmp_name[1]) { 248 | return trim($tmp_name[1],'";\''); 249 | } 250 | } 251 | } 252 | 253 | $stripped_url = preg_replace('/\\?.*/', '', $url); 254 | return basename($stripped_url); 255 | } 256 | } 257 | -------------------------------------------------------------------------------- /gitplugins/templates/GitPluginsWidget.html: -------------------------------------------------------------------------------- 1 | {% if not craft.users or craft.users.can('accessPlugin-gitplugin') %} 2 | 3 | {% import "_includes/forms" as forms %} 4 | 5 | 30 | 31 |
32 | 33 | {{ getCsrfInput() }} 34 | 35 | 36 | 37 | 38 | 39 |
40 |
41 | 42 |
43 |
44 | 47 |
48 |
49 |
50 | {% else %} 51 | You don't have permission to access this plugin. 52 | {% endif %} 53 | -------------------------------------------------------------------------------- /gitplugins/widgets/GitPlugins_GitWidget.php: -------------------------------------------------------------------------------- 1 | templates->render('gitplugins/GitPluginsWidget'); 13 | } 14 | } 15 | --------------------------------------------------------------------------------