Skip to content

Commit a7bb8a7

Browse files
committed
2.4.0
- **Private Repository Unterstützung**: Zugriff auf private GitHub Repositories für konfigurierte User/Organisationen - **Repository Besitzer Konfiguration**: Neue Einstellung zur Definition privater Repository-Besitzer - **Alphabetische Sortierung**: Repositories werden alphabetisch sortiert angezeigt - **UI-Verbesserungen**: Neues 2-spaltiges Layout mit rechtsbündigem Installieren-Button ## Technische Details Diese Version erweitert zip_install um die Möglichkeit, auch private Repositories zu nutzen (erfordert GitHub Token mit repo-Scope) und verbessert die Benutzeroberfläche für bessere Übersichtlichkeit."
1 parent a4a5ac4 commit a7bb8a7

9 files changed

Lines changed: 159 additions & 41 deletions

File tree

README.md

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ Dieses AddOn ermöglicht die einfache Installation von AddOns oder Plugins durch
1818
* Installation direkt von GitHub-Repositories
1919
* Repository-Suche nach Benutzer/Organisation
2020
* Anzeige von Beschreibungen und Details der Repositories
21+
* **Unterstützung für private Repositories** bei konfigurierten Usern/Organisationen
22+
* Alphabetische Sortierung der Repository-Liste
2123

2224
## Installation
2325

@@ -66,11 +68,24 @@ Ein persönlicher Zugriffstoken kann unter **GitHub > Settings > Developer setti
6668
Der Token kann bequem über die **Einstellungen-Seite** des AddOns eingetragen werden.
6769

6870
**Vorteile eines Tokens:**
69-
* Erhöhtes Rate-Limit (5000 Anfragen/Stunde statt 60).
70-
* **Zugriff auf private Repositories**: Mit einem Token, der über den Scope `repo` verfügt, können auch private Repositories installiert werden.
71+
* Erhöhtes Rate-Limit (5000 Anfragen/Stunde statt 60)
72+
* **Zugriff auf private Repositories**: Mit einem Token, der über den Scope `repo` verfügt, können auch private Repositories installiert werden
7173

7274
Für öffentliche Repositories reicht in der Regel ein Token ohne spezielle Scopes (oder der Scope `public_repo`).
7375

76+
### Private Repositories konfigurieren
77+
78+
Um private Repositories in der Suche anzuzeigen, müssen diese in den **Einstellungen** unter "Private Repository Besitzer" eingetragen werden:
79+
80+
1. Trage deinen GitHub-Token in den Einstellungen ein (benötigt den Scope `repo`)
81+
2. Trage die gewünschten GitHub-Benutzernamen oder Organisationen komma-getrennt ein, z.B.: `KLXM, skerbis, meine-org`
82+
3. Bei der Suche nach diesen Usern/Orgas werden nun auch private Repositories angezeigt (mit einem "Privat"-Label gekennzeichnet)
83+
84+
**Wichtig:** Private Repositories werden nur angezeigt, wenn:
85+
- Der eingetragene Token von einem User stammt, der Zugriff auf diese Repos hat
86+
- Bei Organisationen: Der authentifizierte User muss Member der Organisation sein
87+
- Bei einzelnen Usern: Der Token muss vom gesuchten User selbst stammen
88+
7489
## Voraussetzungen
7590

7691
* REDAXO >= 5.18

assets/css/zip_install.css

Lines changed: 27 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -37,21 +37,22 @@
3737

3838
/* Layout */
3939
#zip_install_repos {
40-
margin-top: 20px;
40+
margin-top: 15px;
4141
}
4242

4343
/* Repository Cards */
4444
.zip-panel {
4545
background: var(--zip-bg-color);
4646
border: 1px solid var(--zip-border-color);
4747
box-shadow: var(--zip-card-shadow);
48-
border-radius: 4px;
49-
margin-bottom: 20px;
50-
transition: var(--zip-transition);
48+
border-radius: 3px;
49+
margin-bottom: 12px;
50+
transition: all 0.2s ease;
51+
overflow: hidden;
5152
}
5253

5354
.zip-panel:hover {
54-
box-shadow: 0 4px 8px var(--zip-shadow-color);
55+
box-shadow: 0 4px 12px var(--zip-shadow-color);
5556
}
5657

5758
.zip-panel-header {
@@ -60,38 +61,49 @@
6061
background: var(--zip-bg-color);
6162
}
6263

63-
.zip-panel-header-content {
64-
display: flex;
65-
justify-content: space-between;
66-
align-items: center;
64+
.zip-panel-header .row {
65+
margin: 0;
66+
}
67+
68+
.zip-panel-header .col-sm-9,
69+
.zip-panel-header .col-sm-3 {
70+
padding: 0 15px;
6771
}
6872

6973
.zip-panel-title {
70-
font-size: 14px;
74+
font-size: 15px;
7175
font-weight: 600;
7276
color: var(--zip-text-color);
7377
margin: 0;
78+
padding: 0;
79+
line-height: 32px; /* Align with button height */
7480
}
7581

7682
.zip-panel-title a {
7783
color: var(--zip-text-color);
7884
text-decoration: none;
79-
transition: var(--zip-transition);
85+
transition: color 0.2s ease;
8086
}
8187

8288
.zip-panel-title a:hover {
83-
opacity: 0.8;
89+
color: #3bb594;
90+
}
91+
92+
.zip-panel-title .label {
93+
vertical-align: middle;
94+
margin-left: 8px;
8495
}
8596

8697
.zip-panel-body {
87-
padding: 15px;
88-
background: var(--zip-bg-color);
98+
padding: 12px 15px;
99+
background: var(--zip-hover-bg);
89100
}
90101

91102
.zip-description {
92103
color: var(--zip-text-light);
93104
margin: 0;
94-
min-height: 40px;
105+
line-height: 1.5;
106+
font-size: 13px;
95107
}
96108

97109
/* Form Elements */

boot.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<?php
22

33
// Add CSS for better GitHub repo display
4-
if (rex::isBackend() && is_string(rex_get('page', 'string')) && rex_be_controller::getCurrentPage() === 'install/packages/zip_install') {
5-
rex_view::addCssFile($this->getAssetsUrl('css/zip_install.css'));
4+
if (rex::isBackend() && rex_be_controller::getCurrentPage() === 'install/zip_install/upload') {
5+
rex_view::addCssFile($this->getAssetsUrl('css/zip_install.css?v=' . $this->getVersion()));
66
}

lang/de_de.lang

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,12 +39,16 @@ zip_install_plugin_parent_missing = Das Plugin konnte nicht installiert werden,
3939

4040
zip_install_security_warning = Bitte beachten: Installieren Sie nur AddOns aus vertrauenswürdigen Quellen!
4141

42+
zip_install_private = Privat
43+
4244
zip_install_settings_github_token = GitHub Token
4345
zip_install_settings_github_token_info = Optional. Ein GitHub Token erhöht das stündliche API-Limit von 60 auf 5000 Anfragen.
4446
zip_install_settings_github_token_create = GitHub Token erstellen
4547
zip_install_settings_upload_max_size = Maximale Upload-Größe (MB)
4648
zip_install_settings_upload_max_size_info = Maximale Größe von ZIP-Dateien, die hochgeladen werden können. Standard: 50 MB.
4749
zip_install_settings_upload_max_size_invalid = Die Upload-Größe muss zwischen 1 und 500 MB liegen.
50+
zip_install_settings_private_repo_owners = Private Repository Besitzer
51+
zip_install_settings_private_repo_owners_info = Komma-getrennte Liste von GitHub Benutzernamen oder Organisationen, für die auch private Repositories angezeigt werden sollen (erfordert GitHub Token).
4852
zip_install_settings_saved = Einstellungen wurden erfolgreich gespeichert.
4953

5054
#permissions

lang/en_gb.lang

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,12 +39,16 @@ zip_install_plugin_parent_missing = The plugin could not be installed because th
3939

4040
zip_install_security_warning = Please note: Only install AddOns from trusted sources!
4141

42+
zip_install_private = Private
43+
4244
zip_install_settings_github_token = GitHub Token
4345
zip_install_settings_github_token_info = Optional. A GitHub token increases the hourly API limit from 60 to 5000 requests.
4446
zip_install_settings_github_token_create = Create GitHub Token
4547
zip_install_settings_upload_max_size = Maximum Upload Size (MB)
4648
zip_install_settings_upload_max_size_info = Maximum size of ZIP files that can be uploaded. Default: 50 MB.
4749
zip_install_settings_upload_max_size_invalid = The upload size must be between 1 and 500 MB.
50+
zip_install_settings_private_repo_owners = Private Repository Owners
51+
zip_install_settings_private_repo_owners_info = Comma-separated list of GitHub usernames or organizations for which private repositories should also be displayed (requires GitHub token).
4852
zip_install_settings_saved = Settings have been saved successfully.
4953

5054
#permissions

lib/zip_install.php

Lines changed: 66 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -231,6 +231,11 @@ public function getGitHubRepos(string $username): array
231231
// Get GitHub token from config if available
232232
$token = $this->addon->getConfig('github_token');
233233

234+
// Check if this user/org is configured for private repos
235+
$privateRepoOwners = $this->addon->getConfig('private_repo_owners', '');
236+
$privateOwnersList = array_map('trim', explode(',', $privateRepoOwners));
237+
$includePrivate = $token && in_array($username, $privateOwnersList, true);
238+
234239
$headers = [
235240
'User-Agent: REDAXOZipInstall/2.0',
236241
'Accept: application/vnd.github.v3+json'
@@ -250,17 +255,63 @@ public function getGitHubRepos(string $username): array
250255

251256
$context = stream_context_create($options);
252257

258+
// Check who the authenticated user is (if token is available)
259+
$authenticatedUsername = null;
260+
if ($includePrivate && $token) {
261+
$userInfoResponse = @file_get_contents('https://api.github.com/user', false, $context);
262+
if ($userInfoResponse !== false) {
263+
$userInfo = json_decode($userInfoResponse, true);
264+
if (isset($userInfo['login'])) {
265+
$authenticatedUsername = $userInfo['login'];
266+
}
267+
}
268+
}
269+
253270
while (count($allRepos) < 200) {
254-
$url = sprintf(
255-
'https://api.github.com/users/%s/repos?per_page=%d&page=%d',
256-
urlencode($username),
257-
$perPage,
258-
$page
259-
);
260-
261-
try {
271+
// For configured users/orgs with token, try different approaches
272+
if ($includePrivate) {
273+
// First, try organization endpoint - works for organizations
274+
$url = sprintf(
275+
'https://api.github.com/orgs/%s/repos?per_page=%d&page=%d&type=all',
276+
urlencode($username),
277+
$perPage,
278+
$page
279+
);
280+
262281
$response = @file_get_contents($url, false, $context);
263282

283+
// If /orgs/ fails, check if searched user is the authenticated user
284+
if ($response === false && $authenticatedUsername && strcasecmp($authenticatedUsername, $username) === 0) {
285+
// Use /user/repos for the authenticated user's own repos
286+
$url = sprintf(
287+
'https://api.github.com/user/repos?per_page=%d&page=%d&type=all',
288+
$perPage,
289+
$page
290+
);
291+
$response = @file_get_contents($url, false, $context);
292+
} elseif ($response === false) {
293+
// Fall back to public repos for other users
294+
$url = sprintf(
295+
'https://api.github.com/users/%s/repos?per_page=%d&page=%d',
296+
urlencode($username),
297+
$perPage,
298+
$page
299+
);
300+
$response = @file_get_contents($url, false, $context);
301+
}
302+
} else {
303+
// Standard public repos endpoint
304+
$url = sprintf(
305+
'https://api.github.com/users/%s/repos?per_page=%d&page=%d',
306+
urlencode($username),
307+
$perPage,
308+
$page
309+
);
310+
311+
$response = @file_get_contents($url, false, $context);
312+
}
313+
314+
try {
264315
// Check for rate limit headers
265316
if (isset($http_response_header)) {
266317
foreach ($http_response_header as $header) {
@@ -310,7 +361,8 @@ public function getGitHubRepos(string $username): array
310361
'download_url' => $downloadUrl,
311362
'default_branch' => $repo['default_branch'],
312363
'topics' => $repo['topics'] ?? [],
313-
'homepage' => $repo['homepage'] ?? null
364+
'homepage' => $repo['homepage'] ?? null,
365+
'private' => $repo['private'] ?? false
314366
];
315367
}
316368

@@ -322,6 +374,11 @@ public function getGitHubRepos(string $username): array
322374

323375
$page++;
324376
}
377+
378+
// Sort repositories by name (case-insensitive)
379+
usort($allRepos, function($a, $b) {
380+
return strcasecmp($a['name'], $b['name']);
381+
});
325382

326383
return $allRepos;
327384
}

package.yml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
package: zip_install
2-
version: '2.3.0'
2+
version: '2.4.0'
33
author: Friends Of REDAXO
44
supportpage: github.com/FriendsOfREDAXO/zip_install
55
live_mode: false
@@ -33,3 +33,4 @@ conflicts:
3333
default_config:
3434
upload_max_size: 50
3535
github_token: '' # Optional GitHub API Token für höheres Rate Limit
36+
private_repo_owners: '' # Komma-getrennte Liste von GitHub Usern/Orgas für private Repos

pages/install.zip_install.settings.php

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
if ($csrf->isValid()) {
1111
$githubToken = rex_post('github_token', 'string', '');
1212
$uploadMaxSize = rex_post('upload_max_size', 'int', 50);
13+
$privateRepoOwners = rex_post('private_repo_owners', 'string', '');
1314

1415
// Validate upload size
1516
if ($uploadMaxSize < 1 || $uploadMaxSize > 500) {
@@ -18,6 +19,7 @@
1819
// Save settings
1920
rex_config::set('zip_install', 'github_token', $githubToken);
2021
rex_config::set('zip_install', 'upload_max_size', $uploadMaxSize);
22+
rex_config::set('zip_install', 'private_repo_owners', $privateRepoOwners);
2123

2224
echo rex_view::success(rex_i18n::msg('zip_install_settings_saved'));
2325
}
@@ -29,6 +31,7 @@
2931
// Get current settings
3032
$githubToken = rex_config::get('zip_install', 'github_token', '');
3133
$uploadMaxSize = rex_config::get('zip_install', 'upload_max_size', 50);
34+
$privateRepoOwners = rex_config::get('zip_install', 'private_repo_owners', '');
3235

3336
// Get Rate Limit Info
3437
$rateLimitInfo = '';
@@ -72,6 +75,13 @@
7275
$n['field'] = '<input class="form-control" type="number" id="upload_max_size" name="upload_max_size" value="' . $uploadMaxSize . '" min="1" max="500" />';
7376
$n['note'] = rex_i18n::msg('zip_install_settings_upload_max_size_info');
7477
$formElements[] = $n;
78+
// Private Repo Owners field
79+
$n = [];
80+
$n['label'] = '<label for="private_repo_owners">' . rex_i18n::msg('zip_install_settings_private_repo_owners') . '</label>';
81+
$n['field'] = '<textarea class="form-control" id="private_repo_owners" name="private_repo_owners" rows="3" placeholder="FriendsOfREDAXO, yakamara, mein-username">' . rex_escape($privateRepoOwners) . '</textarea>';
82+
$n['note'] = rex_i18n::msg('zip_install_settings_private_repo_owners_info');
83+
$formElements[] = $n;
84+
7585

7686
$fragment = new rex_fragment();
7787
$fragment->setVar('elements', $formElements, false);

pages/install.zip_install.upload.php

Lines changed: 27 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
$commonAuthors = [
99
'FriendsOfREDAXO',
1010
'yakamara',
11-
'alexplusde',
11+
'skerbis',
1212
'AndiLeni',
1313
'danspringer',
1414
'dtpop',
@@ -188,17 +188,25 @@
188188

189189
// Show repos if we have results
190190
if (isset($repos) && is_array($repos)) {
191-
$githubContent .= '<div class="row" id="zip_install_repos">';
191+
$githubContent .= '<div id="zip_install_repos">';
192192
foreach ($repos as $repo) {
193+
// Add private label if repository is private
194+
$privateLabel = '';
195+
if (!empty($repo['private'])) {
196+
$privateLabel = ' <span class="label label-warning"><i class="fa fa-lock"></i> ' . rex_i18n::msg('zip_install_private') . '</span>';
197+
}
198+
193199
$githubContent .= '
194-
<div class="col-sm-12">
195-
<div class="zip-panel">
196-
<div class="zip-panel-header">
197-
<div class="zip-panel-header-content">
200+
<div class="zip-panel">
201+
<div class="zip-panel-header">
202+
<div class="row">
203+
<div class="col-sm-9">
198204
<h4 class="zip-panel-title">
199-
<a href="' . $repo['url'] . '" target="_blank">' . rex_escape($repo['name']) . '</a>
205+
<a href="' . $repo['url'] . '" target="_blank">' . rex_escape($repo['name']) . '</a>' . $privateLabel . '
200206
</h4>
201-
<form method="post" class="zip-download-form">
207+
</div>
208+
<div class="col-sm-3 text-right">
209+
<form method="post" style="display: inline-block; margin: 0;">
202210
' . $csrfField . '
203211
<input type="hidden" name="zip_url" value="' . $repo['download_url'] . '">
204212
<button type="submit" class="btn btn-primary btn-sm">
@@ -207,10 +215,17 @@
207215
</form>
208216
</div>
209217
</div>
210-
<div class="zip-panel-body">
211-
<div class="zip-description">' . rex_escape($repo['description']) . '</div>
212-
</div>
213-
</div>
218+
</div>';
219+
220+
// Only show body if there's a description
221+
if (!empty($repo['description'])) {
222+
$githubContent .= '
223+
<div class="zip-panel-body">
224+
<div class="zip-description">' . rex_escape($repo['description']) . '</div>
225+
</div>';
226+
}
227+
228+
$githubContent .= '
214229
</div>';
215230
}
216231
$githubContent .= '</div>';

0 commit comments

Comments
 (0)