├── .github └── workflows │ └── publish-to-redaxo-org.yml ├── CHANGELOG.md ├── LICENSE ├── README.md ├── assets └── css │ └── styles.css ├── boot.php ├── lang ├── de_de.lang ├── en_gb.lang ├── es_es.lang ├── pt_br.lang └── sv_se.lang ├── package.yml ├── pages ├── index.php ├── info.php └── main.php ├── plugins ├── client │ ├── boot.php │ ├── install.php │ ├── install │ │ └── client │ │ │ └── redaxo_4 │ │ │ └── project_manager_client.php │ ├── lang │ │ ├── de_de.lang │ │ ├── en_gb.lang │ │ ├── es_es.lang │ │ ├── pt_br.lang │ │ └── sv_se.lang │ ├── lib │ │ └── rex_api_project_manager.php │ ├── package.yml │ └── pages │ │ ├── project_manager.client.page.php │ │ └── project_manager.client.readme.php ├── hosting │ ├── boot.php │ ├── install.php │ ├── lang │ │ ├── de_de.lang │ │ ├── en_gb.lang │ │ ├── es_es.lang │ │ ├── pt_br.lang │ │ └── sv_se.lang │ ├── lib │ │ └── project-manager-hosting.cronjob.php │ ├── package.yml │ ├── pages │ │ ├── content.hosting.php │ │ └── project_manager.hosting.overview.php │ └── uninstall.php ├── pagespeed │ ├── boot.php │ ├── install.php │ ├── lang │ │ ├── de_de.lang │ │ ├── en_gb.lang │ │ ├── es_es.lang │ │ ├── pt_br.lang │ │ └── sv_se.lang │ ├── lib │ │ └── project-manager-pagespeed.cronjob.php │ ├── package.yml │ ├── pages │ │ ├── content.pagespeed.php │ │ ├── project_manager.pagespeed.config.php │ │ └── project_manager.pagespeed.overview.php │ └── uninstall.php └── server │ ├── assets │ ├── css │ │ ├── bootstrap-tagsinput.css │ │ ├── theme.css │ │ └── theme.default.min.css │ ├── favicon │ │ ├── favicon │ │ └── redaxo-favicon.png │ └── js │ │ ├── bootstrap-tagsinput.js │ │ ├── custom.js │ │ ├── jquery.tablesorter.combined.min.js │ │ ├── jquery.tablesorter.min.js │ │ ├── jquery.tablesorter.widgets.min.js │ │ └── tablesorter-custom.js │ ├── boot.php │ ├── install.php │ ├── lang │ ├── de_de.lang │ ├── en_gb.lang │ ├── es_es.lang │ ├── pt_br.lang │ └── sv_se.lang │ ├── lib │ ├── project-manager-favicon.cronjob.php │ ├── project-manager-favicon.cronjob.txt │ ├── project-manager-logger.php │ ├── project-manager.cronjob.php │ └── rex_api_project_manager_server.php │ ├── package.yml │ ├── pages │ ├── info.php │ ├── project_manager.server.config.php │ ├── project_manager.server.overview.php │ └── project_manager.server.projects.php │ ├── uninstall.php │ └── update.php └── update.php /.github/workflows/publish-to-redaxo-org.yml: -------------------------------------------------------------------------------- 1 | # Instructions: https://github.com/FriendsOfREDAXO/installer-action/ 2 | 3 | name: Publish to REDAXO.org 4 | on: 5 | release: 6 | types: 7 | - published 8 | 9 | jobs: 10 | redaxo_publish: 11 | runs-on: ubuntu-latest 12 | steps: 13 | - uses: actions/checkout@v3 14 | - uses: FriendsOfREDAXO/installer-action@v1 15 | with: 16 | myredaxo-username: ${{ secrets.MYREDAXO_USERNAME }} 17 | myredaxo-api-key: ${{ secrets.MYREDAXO_API_KEY }} 18 | description: ${{ github.event.release.body }} 19 | 20 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | ## Version 1.5.9 // 04.03.2025 4 | 5 | # Plugin: Server 1.5.7 6 | * Anpassungen Dark Mode allgemein #93 https://github.com/FriendsOfREDAXO/project_manager/issues/93 7 | * Weitere Redaxo Versionen aufgenommen 8 | 9 | ## Version 1.5.8 // 03.03.2025 10 | 11 | # Plugin: Server 1.5.6 12 | * Anpassungen Redaxo Dark Mode #93 https://github.com/FriendsOfREDAXO/project_manager/issues/93 13 | * Neues Feld für Bemerkungen #92 https://github.com/FriendsOfREDAXO/project_manager/issues/92 14 | * konfigurierbare Anzeige der Bemerkung in Übersicht 15 | * Einzelne Projektdaten können nun in der Übersicht abgerufen werden 16 | 17 | 18 | ## Version 1.5.5 // 12.11.2024 19 | 20 | # Plugin: Server 1.5.4 21 | * Weitere Redaxo Versionen aufgenommen 22 | * Spalten Anpassung Table Sorter 23 | 24 | 25 | ## Version 1.5.2 // 11.11.2024 26 | 27 | # Plugin: Server 1.5.2 28 | * Weitere Redaxo Versionen aufgenommen 29 | 30 | 31 | ## Version 1.5.1 // 19.03.2024 32 | 33 | # Plugin: Server 1.5.1 34 | * Weitere Redaxo Versionen aufgenommen 35 | 36 | 37 | ## Version 1.5.0 // 14.12.2022 38 | 39 | # Plugin: Server 1.5.0 40 | * Weitere Redaxo Versionen aufgenommen 41 | * Maintenance / Wartungsvertrag Icon angepasst #77 https://github.com/FriendsOfREDAXO/project_manager/issues/77 42 | * Beim Abruf der Domaindaten nun zusätzliches Logging in einzelnen Textdateien #78 https://github.com/FriendsOfREDAXO/project_manager/issues/78 43 | * Bugfix: Warnings entfernt unter R5.14.2 #79 https://github.com/FriendsOfREDAXO/project_manager/issues/79 44 | 45 | 46 | ## Version 1.4.0 // 24.05.2022 47 | 48 | # Plugin: Server 1.4.0 49 | * Parameter Übergabe bei API Aufruf zum Client 50 | * Weitere Redaxo Versionen aufgenommen 51 | * Maintenance / Wartungsvertrag Info in Listenansicht / Detailansicht 52 | 53 | # Plugin: Pagespeed 1.2.4 54 | * Favicon Breite Listenansicht angepasst 55 | * Felder Listenansicht angepasst 56 | 57 | # Plugin: Hosting 1.0.8 58 | * Favicon Breite Listenansicht angepasst 59 | * Felder Listenansicht angepasst 60 | 61 | 62 | 63 | ## Version 1.3.8 // 25.04.2022 64 | 65 | # Plugin: Server 1.3.8 66 | * YFORM 4 Kompatibel 67 | 68 | 69 | 70 | ## Version 1.3.7 // 04.01.2022 71 | 72 | # Plugin: Server 1.3.7 73 | * Favicon Cronjob an Google API angepasst 74 | 75 | 76 | ## Version 1.3.6 // 03.12.2021 77 | 78 | # Plugin: Server 1.3.6 79 | * Infotexte Icons Listenansicht 80 | 81 | # Plugin: Hosting 1.0.7 82 | * Listenansicht Redaxo 5.13 Anpassungen 83 | 84 | # Plugin: Pagespeed 1.2.3 85 | * Listenansicht Redaxo 5.13 Anpassungen 86 | 87 | 88 | 89 | ## Version 1.3.5 // 13.10.2021 90 | 91 | # Plugin: Server 1.3.5 92 | * Tablesorter in Listenansicht angepasst 93 | 94 | 95 | ## Version 1.3.4 // 11.10.2021 96 | 97 | # Plugin: Server 1.3.4 98 | * Sysloginfo zeigt Ausrufezeichen erst ab Errorlevel "Notice" 99 | 100 | 101 | ## Version 1.3.3 // 11.10.2021 102 | 103 | # Plugin: Server 1.3.3 104 | * Overview: maintenance Spalte hinzugefügt 105 | * Warnings bei fehlenden Client Daten abgefangen (Danke an https://github.com/omphteliba) 106 | 107 | 108 | ## Version 1.3.2 // 18.03.2021 109 | 110 | # Plugin: Server 1.3.2 111 | * Datenbankspalte hat beim Update gefehlt 112 | 113 | ## Version 1.3.1 // 05.03.2021 114 | 115 | # Plugin: Server 1.3.1 116 | * Datenbankspalte hat beim Update gefehlt 117 | * Weitere Redaxo Versionen aufgenommen 118 | * Useragent wird beim Abruf der Domaindaten mitgegeben 119 | * Übersetzungen hinzugefügt (Danke an interweave-media und ynamite) 120 | 121 | 122 | ## Version 1.3 // 11.01.2021 123 | 124 | # Plugin: Server 1.3 125 | * Bug: Abfrage auf Servern mit vorgeschalter index.html behoben 126 | * PHP Anforderungen package.yml um Version 8 erweitert 127 | * Listenansicht mit Redaxo Backend Link erweitert 128 | * Detailansicht mit Redaxo Backend Link 129 | 130 | # Plugin: Client 1.1 131 | * Redaxo Backend Verzeichnis wird mit übertragen 132 | 133 | 134 | ## Version 1.2.16 // 08.01.2021 135 | 136 | # Plugin: Server 1.2.10 137 | * Link "Projektdaten aktualisieren" nach Hinzufügen falsch bug #47 138 | * Fehlende Übersetzung bei Fehlermeldung #46 139 | * Uninstall Routine der Tabellen hinzugefügt 140 | 141 | # Plugin: Client 1.0.8 142 | * Overview: maintenance Spalte entfernt 143 | * Uninstall Routine der Tabellen hinzugefügt 144 | 145 | # Plugin: Pagespeed 1.2.2 146 | * Overview: maintenance Spalte entfernt 147 | * Uninstall Routine der Tabellen hinzugefügt 148 | 149 | # Plugin: Hosting 1.0.6 150 | * Overview: maintenance Spalte entfernt 151 | * Uninstall Routine der Tabellen hinzugefügt 152 | 153 | 154 | 155 | ## Version 1.2.15 // 30.03.2020 156 | 157 | # Plugin: Server 1.2.9 158 | Bugfix Version Compare 159 | 160 | ## Version 1.2.14 // 26.03.2020 161 | 162 | # Plugin: Server 1.2.8 163 | Version Compare umgestellt 164 | 165 | 166 | ## Version 1.2.12 // 26.03.2020 167 | 168 | # Plugin: Server 1.2.7 169 | * Default Config wird nun gesetzt 170 | 171 | 172 | ## Version 1.2.10 // 11.03.2020 173 | 174 | # Plugin: Server 1.2.6 175 | * Versions-Auswahl um R5.9.0 und R5.10.0 erweitert 176 | * Tablesorter in Listenansicht angepasst 177 | * Lesbare Darstellung vom Datum in Listen- und Detailansicht 178 | 179 | # Plugin: Client 1.0.7 180 | * Syslog Abfrage für > R5.9 geändert 181 | 182 | # Plugin: Pagespeed 1.2.1 183 | * Lesbare Darstellung vom Datum in Listenansicht 184 | 185 | # Plugin: Hosting 1.0.4 186 | * Lesbare Darstellung vom Datum in Listenansicht 187 | * Notices entfernt 188 | 189 | 190 | ## Version 1.2.9 // 27.11.2019 191 | 192 | ## Plugin: Server 1.2.5 193 | 194 | * Cleanup Datenbank hinzugefügt 195 | 196 | 197 | ## Version 1.2.8 // 19.11.2019 198 | 199 | * Svensk översättning - Danke @interweave-media @gharlan 200 | 201 | ## Plugin: Server 1.2.4 202 | 203 | * Versions-Auswahl um R7.1, R5.8, R5.8.1, PHP 7.4, PHP 8.0 erweitert 204 | * Fragezeichen nach Neuanlage mit API Key versehen 205 | 206 | ## Plugin: Pagespeed 1.2.0 207 | 208 | * Umstellung auf Lighthouse API V5 209 | 210 | 211 | ## Version 1.2.7 // 26.04.2019 212 | 213 | * Abhängigkeiten YFORM 3 wurden angepasst 214 | 215 | # Plugin: Server 1.2.3 216 | 217 | * Uninstallroutine für die Cronjobs 218 | 219 | 220 | ## Version 1.2.6 // 01.02.2019 221 | 222 | # Plugin: Server 1.2.2 223 | 224 | * Tablesorter speichert nun die Sortierung 225 | * REX API: Projekt Manager Server hinzugefügt 226 | * Systemlog kann für einzelnes Projekt gelöscht werden (Client muss auf Redaxo 5 laufen und mind. Client Version 1.0.6 haben) 227 | * Einzelne Projektdaten können aktualisiert werden 228 | 229 | # Plugin: Server 1.0.6 230 | 231 | * Systemlog kann vom Server aus gelöscht werden 232 | * Debugmode wird mit übermittelt 233 | 234 | # Plugin: Hosting 1.0.3 235 | 236 | * Bugfix für nicht SSL Server 237 | * Notices entfernt 238 | 239 | 240 | ## Version 1.2.5 // 30.01.2019 241 | 242 | # Plugin: Server 1.2.1 243 | 244 | * Performance Anpassungen 245 | * Limitierung aufgehoben 246 | 247 | 248 | ## Version 1.2.2 // 29.01.2019 249 | 250 | # Plugin: Server 1.2.0 251 | * Tablesorter in Listenansicht Limitierung aufgehoben 252 | * Ausschließen von Addons und Versionen bei der Prüfung 253 | * Umstellung auf bin2hex Token (Mindestanforderung für das Server Plugin PHP 7) 254 | * Tags können für ein Projekt vergeben werden 255 | 256 | # Plugin: Pagespeed 1.1.0 257 | * Performance und API Anpassungen 258 | * Screenshot wird an Server Hook übergeben 259 | 260 | 261 | ## Version 1.2.0 // 20.12.2018 262 | 263 | # Plugin: Server 1.1.0 264 | * Tablesorter in Listenansicht angepasst 265 | * Konfigurationsseite 266 | * Minimale PHP Version 267 | * Minimale CMS Version 268 | * Letzte Änderungen auf der Webseite nun in Listenansicht 269 | * Letzte Änderungen auf der Webseite nun in Detailansicht 270 | * Letzter Datenabgleich in Detailansicht 271 | * Cronjob aus Listenansicht aufrufbar 272 | 273 | # Plugin: Client 1.0.5 274 | * Letzte Änderungen auf der Webseite 275 | 276 | # Plugin: Pagespeed 1.0.4 277 | * Cronjob aus Listenansicht aufrufbar 278 | 279 | # Plugin: Hosting 1.0.2 280 | * idn_to_ascii Anpassungen PHP 7.1 281 | * Zertifikat Start/Enddatum werden abgerufen 282 | * Cronjob aus Listenansicht aufrufbar 283 | 284 | 285 | ## Version 1.1.3 // 05.11.2018 286 | 287 | # Plugin: Hosting 1.0.1 288 | * ip-api.com Aufrufe geändert 289 | 290 | ## Version 1.1.2 // 04.11.2018 291 | 292 | # Plugin: Server 1.0.7 293 | * Listenansicht hat nun einen Tablesorter 294 | * Anzahl der Domains / Projekte wird in der Übersicht angezeigt 295 | 296 | # Plugin: Pagespeed 1.0.4 297 | * Listenansicht hat nun einen Tablesorter 298 | * Anzahl der Domains / Projekte wird in der Übersicht angezeigt 299 | * Extensionpoint Aufruf angepasst 300 | 301 | # Plugin: Hosting 1.0.0 302 | * Neues Plugin für Hosting Übersicht erstellt 303 | 304 | 305 | ## Version 1.1.1 // 11.10.2018 306 | 307 | # Plugin: Server 1.0.6 308 | * Curl Aufruf mit SSL Zertifikaten (SSL_VERIFYPEER nun false) 309 | * Bei Redaxo 4 Projekten wird nun kein Syslog und keine Updates in der Übersicht angezeigt 310 | * Limit beim Favicon Cronjob entfernt 311 | 312 | 313 | ## Version 1.1.0 // 08.10.2018 314 | 315 | * Erweiterung um Rechtevergabe für das Addon und deren Plugins 316 | * project_manager[] 317 | 318 | # Plugin: Server 1.0.5 319 | * Schreibweise der Funktionen verkürzt 320 | * Erweiterung um Rechtevergabe des Plugins 321 | * project_manager_server[] 322 | * Automatisches Anlegen der Crobjobs: rex_cronjob_project_manager_data, rex_cronjob_project_manager_favicon 323 | 324 | # Plugin: Client 1.0.4 325 | * Erweiterung um Rechtevergabe des Plugins 326 | * project_manager_client[] 327 | 328 | # Plugin: PageSpeed 1.0.3 329 | * Erweiterung um Rechtevergabe des Plugins 330 | * project_manager_pagespeed[] 331 | * Automatisches Anlegen des Crobjobs: rex_cronjob_project_manager_pagespeed 332 | 333 | 334 | 335 | ## Version 1.0.9 // 05.10.2018 336 | 337 | # Plugin: Server 338 | * Detailview zeigt nun direkt die Addon Updates im Accordion 339 | * Wenn etwas im Syslog steht, wird nun ein Ausrufezeichen in der Übersicht und im Accordion in der Detailview angezeigt 340 | 341 | # Plugin: Client 342 | * Erweiterung um MySQL Version für REDAXO 4 343 | 344 | 345 | ## Version 1.0.8 // 05.10.2018 346 | 347 | * Diverse Sprachersetzungen 348 | 349 | # Plugin: Server 350 | * API Key Validierung entfernt 351 | * Erweiterung um MySQL Version 352 | * Cronjobs www entfernt 353 | 354 | # Plugin: Client 355 | * Erweiterung um MySQL Version 356 | 357 | # Plugin: PageSpeed 358 | * Domainanzeige bei Pagespeed 359 | 360 | 361 | ## Version 1.0.5 // 05.10.2018 362 | 363 | * Direkteinstieg zum Server Plugin über die Hauptnavigation nun möglich - Danke @ Dirk Schürjohann 364 | 365 | ## Version 1.0.4 // 05.10.2018 366 | 367 | * Demoplugin entfernt 368 | 369 | # Plugin: Client 370 | * Notices entfernt 371 | * Client Version wird mit übermittelt 372 | * REDAXO 4 Client Datei im Install Ordner 373 | 374 | # Plugin: Server 375 | * Assets Ordner wird nun bei der Installation vom Server Plugin angelegt 376 | * REDAXO Hauptversion kann pro Projekt angelegt werden. Der Aufruf zum Client wird nun unterschieden und für alte REDAXO 4 Instanzen gibt es eine eigene PHP Datei 377 | * YFORM Abhängigkeit hinzugefügt 378 | * Notices entfernt 379 | 380 | # Plugin: Pagespeed 381 | * Error Handling im Cronjob 382 | * Notices entfernt 383 | 384 | 385 | ## Version 1.0.0 // 02.10.2018 386 | 387 | * Projekt Manager Addon 388 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2018 Friends Of REDAXO 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 | 2 | REDAXO-AddOn: Project Manager 3 | ================================================================================ 4 | 5 | Bietet Unterstützung bei der Verwaltung und Überprüfung der eigenen REDAXO-Installationen. 6 | 7 | ## Projektübersicht 8 | ![Screenshot](https://raw.githubusercontent.com/FriendsOfREDAXO/project_manager/assets/project_manager_server.png) 9 | 10 | ## Projektdetailansicht 11 | ![Screenshot](https://raw.githubusercontent.com/FriendsOfREDAXO/project_manager/assets/project_manager_server_detail.png) 12 | 13 | ## Inhaltsübersicht 14 | 15 | * [Einleitung](#einleitung) 16 | - [Über das AddOn](#ueber-das-addon) 17 | - [Features](#section1) 18 | - [Installation](#section2) 19 | - [Plugins](#section3) 20 | 21 | * [Einstellungen](#einstellungen) 22 | * [Server-Plugin](#server-plugin) 23 | - [Server](#server) 24 | - [Editiermodus](#editiermodus) 25 | - [Sync-Cronjob](#status-cronjob) 26 | * [Client-Plugin](#client-plugin) 27 | - [Client](#client) 28 | * [Hosting-Plugin](#hosting-plugin) 29 | - [Hosting](#hosting) 30 | * [Allgemein](#allgemein) 31 | - [Changelog](#section4) 32 | - [Credits](#section5) 33 | - [Bug-Meldungen, Hilfe und Links](#section6) 34 | 35 | 36 | ## Einleitung 37 | 38 | 39 | ### Über das Addon 40 | 41 | Dieses Addon bietet Unterstützung bei der Verwaltung und Überprüfung der eigenen REDAXO-Installationen. 42 | 43 | ↑ [zurück zur Übersicht](#top) 44 | 45 | 46 | ### Features 47 | 48 | Das **Client-Plugin** ist für den Abruf der einzelnen Parameter zuständig. 49 | 50 | * Hinterlegen eines API-Keys in den Einstellungen 51 | * Abruf von Parametern der Installation, z.B. 52 | * Aktuelle PHP-Version 53 | * Installierte und updatefähige REDAXO-Addons 54 | * Vorhandene Module 55 | * Verwendete YRewrite-Domains 56 | * Letzte Logins 57 | * Letzte Änderungen im Medienpool 58 | * Letzte Änderungen in der Struktur 59 | * Letzte Meldungen aus dem Syslog 60 | * weiter geplant: Medienpool-Verzeichnisgröße, Backup-Status 61 | * weiter geplant: EXTENSION_POINT, um eigene Prüfregeln zu hinterlegen 62 | 63 | Das **Server-Plugin** dient zur Verwaltung der REDAXO Projekte 64 | 65 | * Verwaltung der REDAXO-Projekte 66 | * Darstellung der wichtigsten Parameter in der Listenansicht 67 | * Darstellung aller Parameter in der Detailansicht 68 | * Abruf und Überwachung der Parameter von den Clients 69 | * EXTENSION_POINT **PROJECT_MANAGER_SERVER_DETAIL_HOOK** zur Einbindung von weiteren Plugins und zur Darstellung in der Detailansicht 70 | * Cronjob zum automatisierten Abruf aller Parameter 71 | * Cronjob zum automatisierten Abruf der Favicons 72 | 73 | ![Screenshot](https://raw.githubusercontent.com/FriendsOfREDAXO/project_manager/assets/project_manager_server.png) 74 | 75 | Das **PageSpeed-Plugin** dient zur Anzeige der Google PageSpeedwerte 76 | * Abrufen der Desktop und Mobile PageSpeed Werte 77 | * Darstellung der Werte in der Listenansicht 78 | * Darstellung aller Parameter in der Detailansicht im **Server-Plugin** 79 | * Cronjob zum automatisierten Abruf der Werte 80 | 81 | ![Screenshot](https://raw.githubusercontent.com/FriendsOfREDAXO/project_manager/assets/project_manager_pagespeed.png) 82 | 83 | Das **Hosting-Plugin** dient zur Anzeige von Hosting Informationen 84 | * Abrufen von ISP, Organisation sowie die aktuelle IP Adresse über den IP-API.com Dienst 85 | * Darstellung der Werte in der Listenansicht 86 | * Darstellung aller Parameter in der Detailansicht im **Server-Plugin** 87 | * Cronjob zum automatisierten Abruf der Werte 88 | 89 | ![Screenshot](https://raw.githubusercontent.com/FriendsOfREDAXO/project_manager/assets/project_manager_hosting.png) 90 | 91 | ↑ [zurück zur Übersicht](#top) 92 | 93 | 94 | 95 | ## Installation 96 | 97 | Voraussetzung für die aktuelle Version des Projekt Manager Addons: REDAXO 5.3, Cronjob-Addon, MarkItUp-Addon 98 | Nach erfolgreicher Installation gibt es im Backend unter AddOns einen Eintrag "Projekt Manager". 99 | 100 | ↑ [zurück zur Übersicht](#top) 101 | 102 | 103 | ### Plugins 104 | 105 | Auf den REDAXO Projekten sollte nur das Plugin **Client** installiert und konfiguriert werden. 106 | Der Projekt Manager Server benötigt das Plugin **Server**. 107 | 108 | ↑ [zurück zur Übersicht](#top) 109 | 110 | 111 | ## Server-Plugin 112 | 113 | 114 | ### Server 115 | 116 | Unter dem Reiter **Übersicht** werden REDAXO-Installationen verwaltet. 117 | 118 | Es wird eine Übersicht der wichtigsten Parameter in der Listenansicht dargestellt. 119 | Neue Projekte können angelegt und vorhandene Projekte geändert werden. 120 | 121 | Die einzelnen Felder sind: 122 | 123 | * Name des Projektes 124 | * Website (Domain aus dem System oder Domain des YRewrite-Projekts, z.B. `domain.de`) 125 | * SSL Verschlüsselung 126 | * API-Key 127 | * REDAXO Hauptversion (Wird für den entsprechenden Aufruf zum Client benötigt) 128 | 129 | 130 | 131 | ### Editiermodus 132 | 133 | Im **Editiermodus** lässt sich das ausgewählte Projekt verwalten. 134 | 135 | 136 | ### Details 137 | 138 | Unter Details kann das Projekt gewählt werden und alle relevanten Inhalte zum Projekt angezeigt werden. 139 | 140 | 141 | ### Sync-Cronjob 142 | 143 | Um die Daten von den REDAXO Clients in den Projekt Manager zu laden, gibt es zwei Cronjobs welche im Cronjob Addon mit der Installation angelegt werden. 144 | * Projekt Manager: Hole Domaindaten 145 | * Projekt Manager: Hole Favicon 146 | 147 | 148 | 149 | ## Client-PlugIn 150 | 151 | 152 | ### Client 153 | 154 | Unter dem Reiter **Client** wird der API Key für die REDAXO Instanz verwaltet. 155 | 156 | Die einzelnen Felder sind: 157 | 158 | * API-Key 159 | 160 | Dieser wird beim Projekt anlegen im Server-Plugin erzeugt und kann hier ein eingetragen werden. 161 | 162 | 163 | ↑ [zurück zur Übersicht](#top) 164 | 165 | 166 | ### Einstellungen 167 | 168 | Unter dem Reiter **Einstellungen** lässt sich ein API-Key hinterlegen. Bei der Installation des Plugins wird automatisch ein API-Key voreingestellt. Anschließend lassen sich die Parameter über die URL abrufen: 169 | 170 | ``` 171 | http://www.domain.de/?rex-api-call=project_manager&api_key= 172 | ``` 173 | 174 | ↑ [zurück zur Übersicht](#top) 175 | 176 | 177 | 178 | ### REDAXO 4 179 | 180 | Für REDAXO 4 existiert unter /plugins/client/install/client/redaxo_4 eine Datei Namens **project_manager_client.php**. 181 | Diese muss in das ROOT der Client Instanz auf der REDAXO 4 läuft kopiert werden. 182 | Der Abruf erfolgt dann über den Projekt Manager Server. Dort muss das Projekt mit REDAXO 4 als Hauptversion konfiguriert sein. 183 | 184 | ``` 185 | http://www.domain.de/project_manager_client.php?rex-api-call=project_manager&api_key=legacy 186 | ``` 187 | 188 | ↑ [zurück zur Übersicht](#top) 189 | 190 | 191 | ## PageSpeed-Plugin 192 | 193 | 194 | 195 | ### PageSpeed 196 | 197 | Unter dem Reiter **Einstellungen** wird der Google PageSpeed API Key verwaltet. 198 | 199 | Die einzelnen Felder sind: 200 | 201 | * API-Key 202 | 203 | 204 | ### Installation 205 | 206 | Nach der Installation des Plugins muss in den Einstellungen der API-Key eingerichtet werden. 207 | 208 | ↑ [zurück zur Übersicht](#top) 209 | 210 | 211 | 212 | ### Einstellungen 213 | 214 | Unter dem Reiter **Einstellungen** lässt sich ein API-Key hinterlegen. Bei der Installation des Plugins wird automatisch ein API-Key voreingestellt. Anschließend lassen sich die Parameter über die URL abrufen: 215 | 216 | 217 | 218 | ### PageSpeed-Cronjob 219 | 220 | Um die Daten von den REDAXO Projekten in den Projekt Manager zu laden, gibt es einen Cronjobs welcher im Cronjob Addon mit der Installation angelegt werden. 221 | * Projekt Manager: PageSpeed Daten 222 | 223 | ↑ [zurück zur Übersicht](#top) 224 | 225 | 226 | 227 | 228 | ## Hosting-Plugin 229 | 230 | Das Hosting-Plugin holt ISP, Organisation sowie die aktuelle IP Adresse über den IP-API.com Dienst. Achtung! Es exisitert eine Limitierung von 150 Calls/Minute, daher wurde ein Timing verbaut. 231 | 232 | 233 | ### Installation 234 | 235 | Nach der Installation des Plugins sollte der Cronjob einmal ausgeführt werden. 236 | 237 | ↑ [zurück zur Übersicht](#top) 238 | 239 | 240 | 241 | ### Hosting-Cronjob 242 | 243 | Um die Hostingdaten von den REDAXO Projekten in den Projekt Manager zu laden, gibt es einen Cronjobs welcher im Cronjob Addon mit der Installation angelegt werden. 244 | * Projekt Manager: Hosting Daten 245 | 246 | ↑ [zurück zur Übersicht](#top) 247 | 248 | 249 | ## Allgemein 250 | 251 | 252 | ### Changelog 253 | 254 | siehe CHANGELOG.md des AddOns 255 | 256 | 257 | 258 | ### Bug-Meldungen, Hilfe und Links 259 | 260 | * Auf Github: https://github.com/FriendsOfREDAXO/project_manager/issues 261 | * im Forum: https://www.redaxo.org/forum/ 262 | * im Slack-Channel: https://friendsofredaxo.slack.com/ 263 | 264 | 265 | ### Lizenz 266 | 267 | siehe [LICENSE](https://github.com/FriendsOfREDAXO/project_manager/blob/master/LICENSE) 268 | 269 | ### Autor 270 | 271 | **Friends Of REDAXO** 272 | 273 | * http://www.redaxo.org 274 | * https://github.com/FriendsOfREDAXO 275 | 276 | **Projekt-Lead** 277 | * [Ronny Kemmereit](https://github.com/rkemmere) 278 | 279 | **Development-Team** 280 | * [Ronny Kemmereit](https://github.com/rkemmere) 281 | * [Pascal Schuchmann](https://github.com/pschuchmann) 282 | * [Alexander Walther](https://github.com/alexplusde) 283 | 284 | 285 | 286 | ### Credits 287 | 288 | Großes Danke geht an [Alexander Walther](https://github.com/alexplusde) - alexplusde welcher uns eine gute Codebasis für die Erstellung des Addons zur Verfügung gestellt hat. 289 | 290 | -------------------------------------------------------------------------------- /assets/css/styles.css: -------------------------------------------------------------------------------- 1 | .panel-body img { 2 | max-width: 100%; 3 | } 4 | 5 | .project_manager-tablesorter .rex-table-icon img {width: 16px;} -------------------------------------------------------------------------------- /boot.php: -------------------------------------------------------------------------------- 1 | getAssetsUrl('css/styles.css')); 12 | } 13 | -------------------------------------------------------------------------------- /lang/de_de.lang: -------------------------------------------------------------------------------- 1 | project_manager_title = Projekt Manager 2 | 3 | project_manager_main = Info 4 | 5 | project_manager_navigation = Navigation 6 | project_manager_docs = Hilfe 7 | project_manager_config = Einstellungen 8 | 9 | project_manager_config_save = Speichern 10 | project_manager_config_saved = Gespeichert! 11 | save = Speichern 12 | 13 | perm_general_project_manager[] = project_manager[] - Rechte für Projekt Manager -------------------------------------------------------------------------------- /lang/en_gb.lang: -------------------------------------------------------------------------------- 1 | project_manager_title = Project Manager 2 | 3 | project_manager_main = Info 4 | 5 | project_manager_navigation = Navigation 6 | project_manager_docs = Help 7 | project_manager_config = Settings 8 | 9 | project_manager_config_save = Save 10 | project_manager_config_saved = Saved! 11 | save = Save 12 | 13 | perm_general_project_manager[] = project_manager[] - Perms for Project Manager -------------------------------------------------------------------------------- /lang/es_es.lang: -------------------------------------------------------------------------------- 1 | project_manager_title = Gestor de proyectos 2 | 3 | project_manager_main = Información 4 | 5 | project_manager_navigation = Navegación 6 | project_manager_docs = Ayuda 7 | project_manager_config = Ajustes 8 | 9 | project_manager_config_save = Guardar 10 | project_manager_config_saved = Guardado! 11 | save = Guardar 12 | 13 | perm_general_project_manager[] = project_manager[] - Derechos 14 | perm_general_project_manager[config] = project_manager[config] - Derechos para la configuración -------------------------------------------------------------------------------- /lang/pt_br.lang: -------------------------------------------------------------------------------- 1 | project_manager_title = Gestor de projeto 2 | 3 | project_manager_main = Info 4 | 5 | project_manager_navigation = Navegação 6 | project_manager_docs = Ajuda 7 | project_manager_config = Configurações 8 | 9 | project_manager_config_save = Guardar 10 | project_manager_config_saved = Guardado! 11 | 12 | perm_general_project_manager[] = project_manager[] - Direitos 13 | perm_general_project_manager[config] = project_manager[config] - Direitos de configurações -------------------------------------------------------------------------------- /lang/sv_se.lang: -------------------------------------------------------------------------------- 1 | project_manager_title = Projektledare 2 | 3 | project_manager_main = Info 4 | 5 | project_manager_navigation = Navigering 6 | project_manager_docs = Hjälp 7 | project_manager_config = Konfiguraion 8 | 9 | project_manager_config_save = Spara 10 | project_manager_config_saved = Inställningarna har sparats! 11 | save = Spara 12 | 13 | perm_general_project_manager[] = project_manager[] - Rättigheter -------------------------------------------------------------------------------- /package.yml: -------------------------------------------------------------------------------- 1 | package: project_manager 2 | version: '1.5.9' 3 | author: 'Friends Of REDAXO' 4 | supportpage: https://github.com/FriendsOfREDAXO/project_manager 5 | 6 | # Seiten 7 | page: 8 | title: Projekt Manager 9 | perm: project_manager[] 10 | icon: rex-icon fa-handshake-o 11 | 12 | # Unterseiten 13 | subpages: 14 | main: 15 | title: 'translate:project_manager_main' 16 | perm: project_manager[] 17 | icon: rex-icon fa-info 18 | itemclass: pull-right 19 | 20 | plugins: 21 | - server 22 | - client 23 | - pagespeed 24 | - hosting 25 | 26 | # Abhängigkeiten 27 | # Anforderungen ans System oder anderere AddOns, um dieses AddOn installieren oder update zu können 28 | requires: 29 | redaxo: '^5.2' # benötigt mindestens REDAXO 5.2 30 | php: 31 | version: '>=7.0' # benötigt mindestens PHP 7 32 | 33 | # Plugins die automatisch installiert werden sollen 34 | #system_plugins: 35 | #- client 36 | -------------------------------------------------------------------------------- /pages/index.php: -------------------------------------------------------------------------------- 1 | i18n('project_manager_title')); // $this->i18n('title') ist eine Kurzform für rex_i18n::msg('demo_addon_title') 7 | 8 | // Die Subpages werden nicht mehr über den "subpage"-Parameter gesteuert, sondern über "page" (getrennt mit einem Slash, z. B. page=demo_addon/config) 9 | // Die einzelnen Teile des page-Pfades können mit der folgenden Funktion ausgelesen werden. 10 | $subpage = rex_be_controller::getCurrentPagePart(2); 11 | 12 | // Subpages können über diese Methode eingebunden werden. So ist sichergestellt, dass auch Subpages funktionieren, 13 | // die von anderen Addons/Plugins hinzugefügt wurden 14 | rex_be_controller::includeCurrentPageSubPath(); 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /pages/info.php: -------------------------------------------------------------------------------- 1 | $h2_block) { 8 | preg_match('/(.*)\n^(?:.|\n(?!#))*/m', $h2_block, $headline); 9 | if (isset($headline[1])) { 10 | $navi_list[] = '* '.$headline[1]; 11 | $content_h2_block = '# '.$headline[0]; 12 | preg_match_all('/(?!### )*^### (.*)\n((?:.|\n(?!### ))*)/m', $h2_block, $matches); 13 | if (count($matches[0]) > 0) { 14 | $navi_elements = $matches[1]; 15 | $blocks = $matches[2]; 16 | $content_blocks['chapter'.$h2_i] = $content_h2_block; 17 | foreach ($navi_elements as $h3_i => $navi_element) { 18 | $navi_list[] = ' * '.$navi_element.''; 19 | $content_blocks["chapter".$h2_i] .= "\n## ".$navi_element.$blocks[$h3_i]; 20 | } 21 | } 22 | } 23 | } 24 | reset($content_blocks); 25 | $n = rex_request('n', 'string', key($content_blocks)); 26 | 27 | if (!isset($content_blocks[$n])) { 28 | $n = key($content_blocks); 29 | } 30 | $navi_view = implode("\n", $navi_list); 31 | $blocks_view = $content_blocks[$n]; 32 | 33 | $miu = rex_markdown::factory(); 34 | 35 | // Navigation 36 | $navi_view = $miu->parse($navi_view); 37 | $fragment = new rex_fragment(); 38 | $fragment->setVar('title', rex_i18n::msg('project_manager_navigation').'', false); 39 | $fragment->setVar('body', $navi_view, false); 40 | $navi = $fragment->parse('core/page/section.php'); 41 | 42 | 43 | $blocks_view = $miu->parse($blocks_view); 44 | $fragment = new rex_fragment(); 45 | $fragment->setVar('title', $this->i18n('docs'), false); 46 | $fragment->setVar('body', $blocks_view, false); 47 | $content = $fragment->parse('core/page/section.php'); 48 | 49 | echo '
50 |
51 |
'.$navi.'
52 |
'.$content.'
53 |
54 |
'; -------------------------------------------------------------------------------- /pages/main.php: -------------------------------------------------------------------------------- 1 | isAvailable()) { 4 | 5 | 6 | // dump(rex_request("page", string)); 7 | 8 | // //rex_response::sendRedirect('index.php?page=project_manager/server/overview'); 9 | // }else { 10 | 11 | $content = file_get_contents(rex_path::addon('project_manager')."README.md"); 12 | $content_blocks = []; 13 | $h2_blocks = explode("\n## ", "\n".$content); 14 | foreach ($h2_blocks as $h2_i => $h2_block) { 15 | preg_match('/(.*)\n^(?:.|\n(?!#))*/m', $h2_block, $headline); 16 | if (isset($headline[1])) { 17 | $navi_list[] = '* '.$headline[1]; 18 | $content_h2_block = '# '.$headline[0]; 19 | preg_match_all('/(?!### )*^### (.*)\n((?:.|\n(?!### ))*)/m', $h2_block, $matches); 20 | if (count($matches[0]) > 0) { 21 | $navi_elements = $matches[1]; 22 | $blocks = $matches[2]; 23 | $content_blocks['chapter'.$h2_i] = $content_h2_block; 24 | foreach ($navi_elements as $h3_i => $navi_element) { 25 | $navi_list[] = ' * '.$navi_element.''; 26 | $content_blocks["chapter".$h2_i] .= "\n## ".$navi_element.$blocks[$h3_i]; 27 | } 28 | } 29 | } 30 | } 31 | reset($content_blocks); 32 | $n = rex_request('n', 'string', key($content_blocks)); 33 | 34 | if (!isset($content_blocks[$n])) { 35 | $n = key($content_blocks); 36 | } 37 | $navi_view = implode("\n", $navi_list); 38 | $blocks_view = $content_blocks[$n]; 39 | 40 | $miu = rex_markdown::factory(); 41 | 42 | // Navigation 43 | $navi_view = $miu->parse($navi_view); 44 | $fragment = new rex_fragment(); 45 | $fragment->setVar('title', rex_i18n::msg('project_manager_navigation').'', false); 46 | $fragment->setVar('body', $navi_view, false); 47 | $navi = $fragment->parse('core/page/section.php'); 48 | 49 | 50 | $blocks_view = $miu->parse($blocks_view); 51 | $fragment = new rex_fragment(); 52 | $fragment->setVar('title', $this->i18n('docs'), false); 53 | $fragment->setVar('body', $blocks_view, false); 54 | $content = $fragment->parse('core/page/section.php'); 55 | 56 | echo '
57 |
58 |
'.$navi.'
59 |
'.$content.'
60 |
61 |
'; 62 | //} -------------------------------------------------------------------------------- /plugins/client/boot.php: -------------------------------------------------------------------------------- 1 | getArray('SELECT VERSION()'); 22 | $update_article = $sql->getArray('SELECT `updatedate` FROM `'.$REX['TABLE_PREFIX'].'article_slice` ORDER BY `updatedate` DESC'); 23 | $update_media = $sql->getArray('SELECT `updatedate` FROM `'.$REX['TABLE_PREFIX'].'file` ORDER BY `updatedate` DESC'); 24 | 25 | $project_manager["mysql_version"] = $res[0]['VERSION()']; 26 | $project_manager["update_article"] = $update_article[0]['updatedate']; 27 | $project_manager["update_media"] = $update_media[0]['updatedate']; 28 | 29 | } 30 | 31 | } 32 | echo json_encode($project_manager); -------------------------------------------------------------------------------- /plugins/client/lang/de_de.lang: -------------------------------------------------------------------------------- 1 | 2 | 3 | client_navigation_title = Navigation [ main_navi.md ] 4 | client_content_title = Inhalt [ {0} ] 5 | 6 | client_noparser = Kein Markdown-Parser vorhanden! Bitte zuerst einen Parser installieren (Addon markitup oder textile) 7 | 8 | client_navinotfound = Navigations-Datei {0} wurde nicht gefunden!
Diese Datei ist zwingend erforderlich! 9 | client_filenotfound = Datei {0} wurde nicht gefunden. Inhalt existiert (noch) nicht.

Wir freuen uns über Mithilfe: {1} 10 | 11 | project_manager_client_menu_entry = Client 12 | project_manager_client_page_entry = Einstellungen 13 | project_manager_client_title = Einstellungen 14 | project_manager_client_readme = Hilfe 15 | project_manager_api_key_title = Client 16 | project_manager_api_key_label = API-Schlüssel 17 | project_manager_api_key_notice = API-Schlüssel aus Server Plugin eintragen, z.B. 18 | project_manager_save = Speichern 19 | 20 | 21 | perm_general_project_manager_client[] = project_manager_client[] - Rechte für Projekt Manager Client -------------------------------------------------------------------------------- /plugins/client/lang/en_gb.lang: -------------------------------------------------------------------------------- 1 | 2 | 3 | client_navigation_title = Navigation [ main_navi.md ] 4 | client_content_title = Content [ {0} ] 5 | 6 | client_noparser = No Markdown parser available! Please install a parser first (ex. addon markitup or textile) 7 | 8 | client_navinotfound = Navigation file {0} not found!
This file is required! 9 | client_filenotfound = File {0} not found! Content does not (yet) exist.

Help wanted and welcome: {1} 10 | 11 | project_manager_client_menu_entry = Client 12 | project_manager_client_page_entry = Settings 13 | project_manager_client_title = Settings 14 | project_manager_client_readme = Help 15 | project_manager_api_key_title = Client 16 | project_manager_api_key_label = API key 17 | project_manager_api_key_notice = Enter API key from Server plugin, ex.: 18 | project_manager_save = Save 19 | 20 | 21 | perm_general_project_manager_client[] = project_manager_client[] - Rights for Project Manager Client -------------------------------------------------------------------------------- /plugins/client/lang/es_es.lang: -------------------------------------------------------------------------------- 1 | client_navigation_title = Navegación [main_navi.md] 2 | client_content_title = Contenido [ {0} ] 3 | 4 | client_noparser = ¡No hay analizador de rebajas disponible! Primero instale un analizador (marcado adicional o textil) 5 | 6 | client_navinotfound = ¡No se encontró el archivo de navegación {0} !
¡Este archivo es obligatorio! 7 | client_filenotfound = No se encontró el archivo {0} . El contenido no existe (todavía).

Nos complace ayudar: {1} 8 | 9 | project_manager_client_menu_entry = Cliente 10 | project_manager_client_page_entry = Ajustes 11 | project_manager_client_title = Ajustes 12 | project_manager_client_readme = Ayuda 13 | project_manager_api_key_title = Cliente 14 | project_manager_api_key_label = Clave API 15 | project_manager_api_key_notice = Ingrese la clave API del complemento del servidor, por ejemplo: 16 | project_manager_save = Guardar 17 | 18 | 19 | perm_general_project_manager_client[] = project_manager_client[] - Derechos para Project Manager Client -------------------------------------------------------------------------------- /plugins/client/lang/pt_br.lang: -------------------------------------------------------------------------------- 1 | documentation_menu_entry = Documentação 2 | 3 | documentation_navigation_title = Navegação [ main_navi.md ] 4 | documentation_content_title = Conteúdo [ {0} ] 5 | 6 | documentation_noparser = Nenhum analisador Markdown disponível! Instale primeiro um analisador (AddOn markitup or textile) 7 | 8 | documentation_navinotfound = Arquivo de navegação {0} não localizado!
Este arquivo é necessário! 9 | documentation_filenotfound = Arquivo {0} não localizado. Conteúdos não existem (ainda)

Ficaríamos felizes se você quisesse ajudar: {1} 10 | -------------------------------------------------------------------------------- /plugins/client/lang/sv_se.lang: -------------------------------------------------------------------------------- 1 | 2 | 3 | client_navigation_title = Navigation [ main_navi.md ] 4 | client_content_title = Innehåll [ {0} ] 5 | 6 | client_noparser = Ingen markdown-parser tillgänglig! Installera först en parser (addon markitup eller textile) 7 | 8 | client_navinotfound = Navigationsfil {0} hittades inte!
Den här filen är ett måste! 9 | client_filenotfound = Filen {0} hittades inte. Innehållet finns inte (ännu).

Vi hjälper gärna till: {1} 10 | 11 | project_manager_client_menu_entry = Client 12 | project_manager_client_page_entry = Inställningar 13 | project_manager_client_title = Inställningar 14 | project_manager_client_readme = Hjälp 15 | project_manager_api_key_title = Client 16 | project_manager_api_key_label = API-key 17 | project_manager_api_key_notice = Ange API-nyckel från serverplugin, t.ex. 18 | project_manager_save = Spara 19 | 20 | 21 | perm_general_project_manager_client[] = project_manager_client [] - Rättigheter för Project Manager Client -------------------------------------------------------------------------------- /plugins/client/lib/rex_api_project_manager.php: -------------------------------------------------------------------------------- 1 | getProperty('version'); 34 | $params['client_version'] = rex_plugin::get('project_manager', 'client')->getProperty('version'); 35 | $params['rex_version'] = rex::getVersion(); 36 | $params['cms'] = "REDAXO"; 37 | $params['cms_version'] = rex::getVersion(); 38 | $params['rex_url_backend'] = rex_url::backend(); 39 | $params['php_version'] = phpversion(); 40 | $params['mysql_version'] = rex_sql::getServerVersion(); 41 | $params['status'] = 1; 42 | $params['debug'] = rex::isDebugMode(); 43 | 44 | # / REDAXO / SERVER / ALLGEMEIN 45 | 46 | # ADDONS 47 | 48 | $rex_addons = rex_addon::getInstalledAddons(); 49 | 50 | rex_install_webservice::deleteCache(); 51 | 52 | try { 53 | $installer_addons = rex_install_packages::getAddPackages(); 54 | } catch (rex_functional_exception $e) { 55 | $params['message'][] = $e->getMessage(); 56 | } 57 | 58 | foreach($rex_addons as $key => $addon) { 59 | $params['rex_addons'][$key]['name'] = $addon->getName(); 60 | $params['rex_addons'][$key]['install'] = $addon->getProperty('install'); 61 | $params['rex_addons'][$key]['status'] = $addon->getProperty('status'); 62 | $params['rex_addons'][$key]['version_current'] = $addon->getProperty('version'); 63 | if(!empty($installer_addons[$key])) { 64 | $params['rex_addons'][$key]['version_latest'] = current($installer_addons[$key]["files"])["version"]; 65 | } else { 66 | $params['rex_addons'][$key]['version_latest'] = 0; 67 | } 68 | } 69 | 70 | # / ADDONS 71 | 72 | # DOMAINS / WEBSITES 73 | 74 | $params['domains'][rex::getServer()]['name'] = rex::getServer(); 75 | $params['domains'][rex::getServer()]['url'] = rex_getUrl(rex_article::getSiteStartArticleId()); 76 | $params['domains'][rex::getServer()]['url_404'] = rex_getUrl(rex_article::getNotfoundArticleId()); 77 | 78 | if(rex_addon::get('yrewrite')->isAvailable()) { 79 | 80 | $yrewrite_domains = rex_yrewrite::getDomains(true); 81 | foreach($yrewrite_domains as $key => $domain) { 82 | $params['domains'][$key]['name'] = $domain->getName(); 83 | $params['domains'][$key]['url'] = $domain->getUrl(); 84 | $params['domains'][$key]['url_404'] = rex_yrewrite::getFullUrlByArticleId($domain->getNotfoundId()); 85 | } 86 | } 87 | 88 | # / DOMAINS / WEBSITES 89 | 90 | # SYSLOG 91 | 92 | if (version_compare(rex::getVersion(), '5.9') >= 0) { 93 | $log = new rex_log_file(rex_path::log('system.log')); 94 | } else { 95 | $log = new rex_log_file(rex_path::coreData('system.log')); 96 | } 97 | 98 | $i = 0; 99 | foreach (new LimitIterator($log, 0, 30) as $entry) { 100 | $data = $entry->getData(); 101 | $params['syslog'][$i]['timestamp'] = $entry->getTimestamp('%d.%m.%Y %H:%M:%S'); 102 | $params['syslog'][$i]['syslog_type'] = $data[0]; 103 | $params['syslog'][$i]['syslog_message'] = $data[1]; 104 | $params['syslog'][$i]['syslog_file'] = (isset($data[2]) ? $data[2] : ''); 105 | $params['syslog'][$i]['syslog_line'] = (isset($data[3]) ? $data[3] : ''); 106 | $i++; 107 | } 108 | 109 | # / SYSLOG 110 | 111 | 112 | # USER 113 | $params['user'] = rex_sql::factory()->getArray('SELECT `name`, `login`, `email`, `status`, `admin`, `lasttrydate`, `lastlogin` FROM '.rex::getTablePrefix().'user ORDER BY `admin`, `id`'); 114 | # / USER 115 | 116 | # TODO: Letzte Artikel 117 | $params['article'] = rex_sql::factory()->getArray('SELECT `name`, `updateuser`, `updatedate`, `pid` FROM `'.rex::getTablePrefix().'article` ORDER BY `updatedate` DESC LIMIT 10'); 118 | # / Letzte Artikel 119 | 120 | # TODO: Letzte Medien 121 | $params['media'] = rex_sql::factory()->getArray('SELECT `filename`, `updateuser`, `updatedate` FROM `'.rex::getTablePrefix().'media` ORDER BY `updatedate` DESC LIMIT 10'); 122 | # / Letzte Medien 123 | 124 | # Modules 125 | $params['module'] = rex_sql::factory()->getArray('SELECT `name`, `updateuser`, `updatedate` FROM `'.rex::getTablePrefix().'module` ORDER BY `name` ASC'); 126 | # / Modules 127 | } 128 | 129 | 130 | 131 | } else { 132 | $params['pm_version'] = rex_addon::get('project_manager')->getProperty('version'); 133 | $params['cms'] = "REDAXO"; 134 | $params['status'] = 0; 135 | $params['message'][] = "Falscher API-Schlüssel."; 136 | } 137 | 138 | // TODO: EP, um weitere Parameter einzuhängen 139 | 140 | header('Content-Type: application/json; charset=UTF-8'); 141 | $response = json_encode($params, true); 142 | echo $response; 143 | exit(); 144 | } 145 | } 146 | 147 | ?> -------------------------------------------------------------------------------- /plugins/client/package.yml: -------------------------------------------------------------------------------- 1 | package: project_manager/client 2 | version: '1.1.0' 3 | author: 'Friends Of REDAXO' 4 | supportpage: https://github.com/FriendsOfREDAXO/project_manager 5 | 6 | page: 7 | title: 'translate:client_menu_entry' 8 | icon: rex-icon fa-wrench # Icon von Font Awesome 9 | perm: project_manager_client[] 10 | 11 | pages: 12 | project_manager/client/page: 13 | title: translate:project_manager_client_page_entry 14 | 15 | requires: 16 | packages: 17 | project_manager: '^1.2.0' -------------------------------------------------------------------------------- /plugins/client/pages/project_manager.client.page.php: -------------------------------------------------------------------------------- 1 | setConfig(rex_post('settings', [ 6 | ['project_manager_api_key', 'string'] 7 | ])); 8 | 9 | $message = $this->i18n('project_manager_api_key_saved_successful'); 10 | } 11 | 12 | $content = ''; 13 | 14 | 15 | $formElements = []; 16 | $n = []; 17 | $n['label'] = ''; 18 | $n['field'] = ''; 19 | $n['note'] = $this->i18n('project_manager_api_key_notice').' 13f15d69755585c3a825c3eccf2d654fc6578dadb7e05475'; 20 | 21 | $formElements[] = $n; 22 | 23 | 24 | 25 | $fragment = new rex_fragment(); 26 | $fragment->setVar('elements', $formElements, false); 27 | $fragment->setVar('class', "panel panel-warning", false); 28 | $content .= $fragment->parse('core/form/form.php'); 29 | 30 | $formElements = []; 31 | $n = []; 32 | $n['field'] = ''; 33 | $formElements[] = $n; 34 | 35 | $fragment = new rex_fragment(); 36 | $fragment->setVar('flush', true); 37 | $fragment->setVar('elements', $formElements, false); 38 | $buttons = $fragment->parse('core/form/submit.php'); 39 | 40 | $fragment = new rex_fragment(); 41 | $fragment->setVar('class', 'edit', false); 42 | $fragment->setVar('title', $this->i18n('project_manager_client_title'), false); 43 | $fragment->setVar('body', $content, false); 44 | $fragment->setVar('buttons', $buttons, false); 45 | $content = $fragment->parse('core/page/section.php'); 46 | echo ' 47 |
48 | ' . $content . ' 49 |
'; -------------------------------------------------------------------------------- /plugins/client/pages/project_manager.client.readme.php: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FriendsOfREDAXO/project_manager/29fc69f12ae609bc9d870e96caf4b6c9dbe9a462/plugins/client/pages/project_manager.client.readme.php -------------------------------------------------------------------------------- /plugins/hosting/boot.php: -------------------------------------------------------------------------------- 1 | isAvailable()) { 4 | rex_cronjob_manager::registerType('rex_cronjob_project_manager_hosting'); 5 | } 6 | 7 | // PROJECT_MANAGER_SERVER_DETAIL_HOOK 8 | if (rex::isBackend() && rex::getUser()) { 9 | 10 | rex_extension::register('PROJECT_MANAGER_SERVER_DETAIL_HOOK', function (rex_extension_point $ep) { 11 | 12 | $exist = ''; 13 | if ($ep->getSubject() != "") { 14 | $exist = $ep->getSubject(); 15 | } 16 | 17 | $params = $ep->getParams(); 18 | $panel = include(rex_path::plugin('project_manager', 'hosting', 'pages/content.hosting.php')); 19 | 20 | $fragment = new rex_fragment(); 21 | $fragment->setVar('title', "Hosting", false); 22 | $fragment->setVar('body', $panel, false); 23 | $fragment->setVar('class', 'panel panel-info', false); 24 | $fragment->setVar('domain', $params["domain"], false); 25 | 26 | $fragment->setVar('collapse', true); 27 | $fragment->setVar('collapsed', true); 28 | $hosting = '
'.$fragment->parse('core/page/section.php').'
'; 29 | 30 | return $exist.$hosting; 31 | 32 | }, rex_extension::LATE); 33 | } 34 | 35 | 36 | if (rex::isBackend() && is_object(rex::getUser())) { 37 | rex_perm::register('project_manager_hosting[]'); 38 | } 39 | 40 | -------------------------------------------------------------------------------- /plugins/hosting/install.php: -------------------------------------------------------------------------------- 1 | ensurePrimaryIdColumn() 6 | ->ensureColumn(new rex_sql_column('domain', 'varchar(255)', false, null, ''))->setPrimaryKey('domain') 7 | ->ensureColumn(new rex_sql_column('raw', 'longtext', true)) 8 | ->ensureColumn(new rex_sql_column('ip', 'text')) 9 | ->ensureColumn(new rex_sql_column('createdate', 'timestamp', false, '0000-00-00 00:00:00', 'on update CURRENT_TIMESTAMP')) 10 | ->ensureColumn(new rex_sql_column('status', 'text')) 11 | ->ensure(); 12 | 13 | 14 | // Create cronjob 15 | $now = new DateTime(); 16 | $startdate = date('Y-m-d 00:00:00',strtotime( "tomorrow" )); 17 | 18 | $cronjob = rex_sql::factory(); 19 | $cronjob->setDebug(true); 20 | $cronjob->setQuery('SELECT id FROM '.rex::getTable('cronjob'). ' WHERE type LIKE "rex_cronjob_project_manager_hosting"'); 21 | 22 | if ($cronjob->getRows() == 0) { 23 | 24 | $cronjob = rex_sql::factory(); 25 | $cronjob->setDebug(true); 26 | $cronjob->setTable(rex::getTable('cronjob')); 27 | $cronjob->setValue('name','Projekt Manager: Hosting Daten'); 28 | $cronjob->setValue('description',''); 29 | $cronjob->setValue('type','rex_cronjob_project_manager_hosting'); 30 | $cronjob->setValue('interval','{"minutes":[0],"hours":[0],"days":"all","weekdays":"all","months":"all"}'); 31 | $cronjob->setValue('environment','|backend|'); 32 | $cronjob->setValue('execution_start','1970-01-01 01:00:00'); 33 | $cronjob->setValue('status','1'); 34 | $cronjob->setValue('parameters','[]'); 35 | $cronjob->setValue('nexttime',$startdate); 36 | $cronjob->setValue('createdate',$now->format('Y-m-d H:i:s')); 37 | $cronjob->setValue('updatedate',$now->format('Y-m-d H:i:s')); 38 | $cronjob->setValue('createuser',rex::getUser()->getLogin()); 39 | $cronjob->setValue('updateuser',rex::getUser()->getLogin()); 40 | 41 | try { 42 | $cronjob->insertOrUpdate(); 43 | echo rex_view::success('Der Cronjob "Projekt Manager: Hosting Daten" wurde angelegt. '); 44 | } catch (rex_sql_exception $e) { 45 | echo rex_view::warning('Der Cronjob "Projekt Manager: Hosting Daten" wurde nicht angelegt.
Wahrscheinlich existiert er schon.'); 46 | } 47 | } -------------------------------------------------------------------------------- /plugins/hosting/lang/de_de.lang: -------------------------------------------------------------------------------- 1 | project_manager_hosting_menu_entry = Hosting 2 | 3 | project_manager_hosting_projects = Projekte 4 | project_manager_hosting_title = Übersicht 5 | project_manager_hosting_domain_norows_message = Kein Projekt vorhanden 6 | project_manager_cronjob_hosting_name = Projekt Manager: Hole Hosting Daten 7 | 8 | project_manager_hosting_name = Projektname 9 | project_manager_hosting_domain = Domain 10 | project_manager_hosting_createdate = Letzte Änderung 11 | project_manager_hosting_ip = IPv4-Adresse 12 | project_manager_hosting_is_ssl = SSL 13 | project_manager_hosting_organisation = Organisation 14 | project_manager_hosting_isp = ISP 15 | project_manager_hosting_domain_norows_message = Keine Einträge vorhanden 16 | project_manager_hosting_validTo = Zertifikat Enddatum 17 | project_manager_hosting_validFrom = Zertifikat Startdatum 18 | 19 | perm_general_project_manager_hosting[] = project_manager_hosting[] - Rechte für Projekt Manager Hosting -------------------------------------------------------------------------------- /plugins/hosting/lang/en_gb.lang: -------------------------------------------------------------------------------- 1 | project_manager_hosting_menu_entry = Hosting 2 | 3 | project_manager_hosting_projects = Projects 4 | project_manager_hosting_title = Overview 5 | project_manager_hosting_domain_norows_message = no entries found 6 | project_manager_cronjob_hosting_name = Project Manager: get hosting date 7 | 8 | project_manager_hosting_name = Projectname 9 | project_manager_hosting_domain = Domain 10 | project_manager_hosting_createdate = Last changes 11 | project_manager_hosting_ip = IPv4-Address 12 | project_manager_hosting_is_ssl = SSL 13 | project_manager_hosting_organisation = Organisation 14 | project_manager_hosting_isp = ISP 15 | project_manager_hosting_domain_norows_message = no entries found 16 | project_manager_hosting_validTo = Certificate enddate 17 | project_manager_hosting_validFrom = Certificate startdate 18 | 19 | perm_general_project_manager_hosting[] = project_manager_hosting[] - Permissions for Project Manager Hosting 20 | -------------------------------------------------------------------------------- /plugins/hosting/lang/es_es.lang: -------------------------------------------------------------------------------- 1 | project_manager_hosting_menu_entry = Hosting 2 | 3 | project_manager_hosting_projects = Projects 4 | project_manager_hosting_title = Overview 5 | project_manager_hosting_domain_norows_message = no entries found 6 | project_manager_cronjob_hosting_name = Project Manager: get hosting date 7 | 8 | project_manager_hosting_name = Projectname 9 | project_manager_hosting_domain = Domain 10 | project_manager_hosting_createdate = Last changes 11 | project_manager_hosting_ip = IPv4-Address 12 | project_manager_hosting_is_ssl = SSL 13 | project_manager_hosting_organisation = Organisation 14 | project_manager_hosting_isp = ISP 15 | project_manager_hosting_domain_norows_message = no entries found 16 | project_manager_hosting_validTo = Certificate enddate 17 | project_manager_hosting_validFrom = Certificate startdate 18 | 19 | perm_general_project_manager_hosting[] = project_manager_hosting[] - Project Manager Hosting -------------------------------------------------------------------------------- /plugins/hosting/lang/pt_br.lang: -------------------------------------------------------------------------------- 1 | project_manager_hosting_menu_entry = Hosting 2 | 3 | project_manager_hosting_projects = Projects 4 | project_manager_hosting_title = Overview 5 | project_manager_hosting_domain_norows_message = no projects found 6 | project_manager_cronjob_hosting_name = Project Manager: get hosting date 7 | 8 | project_manager_hosting_name = Projectname 9 | project_manager_hosting_domain = Domain 10 | project_manager_hosting_createdate = Last changes 11 | project_manager_hosting_ip = IPv4-Address 12 | project_manager_hosting_is_ssl = SSL 13 | project_manager_hosting_organisation = Organisation 14 | project_manager_hosting_isp = ISP 15 | project_manager_hosting_domain_norows_message = no entries found 16 | project_manager_hosting_validTo = Certificate enddate 17 | project_manager_hosting_validFrom = Certificate startdate 18 | 19 | perm_general_project_manager_hosting[] = project_manager_hosting[] - Project Manager Hosting -------------------------------------------------------------------------------- /plugins/hosting/lang/sv_se.lang: -------------------------------------------------------------------------------- 1 | project_manager_hosting_menu_entry = Hosting 2 | 3 | project_manager_hosting_projects = Projects 4 | project_manager_hosting_title = Overview 5 | project_manager_hosting_domain_norows_message = no entries found 6 | project_manager_cronjob_hosting_name = Project Manager: get hosting date 7 | 8 | project_manager_hosting_name = Projectname 9 | project_manager_hosting_domain = Domain 10 | project_manager_hosting_createdate = Last changes 11 | project_manager_hosting_ip = IPv4-Address 12 | project_manager_hosting_is_ssl = SSL 13 | project_manager_hosting_organisation = Organisation 14 | project_manager_hosting_isp = ISP 15 | project_manager_hosting_domain_norows_message = no entries found 16 | project_manager_hosting_validTo = Certificate enddate 17 | project_manager_hosting_validFrom = Certificate startdate 18 | 19 | perm_general_project_manager_hosting[] = project_manager_hosting[] - Project Manager Hosting -------------------------------------------------------------------------------- /plugins/hosting/lib/project-manager-hosting.cronjob.php: -------------------------------------------------------------------------------- 1 | setDebug(0)->getArray('SELECT D.domain AS domain, D.is_ssl as is_ssl FROM 10 | (SELECT domain, createdate FROM rex_project_manager_domain_hosting) AS H 11 | RIGHT JOIN 12 | (SELECT domain, updatedate, is_ssl FROM rex_project_manager_domain) AS D 13 | ON 14 | H.domain = D.domain 15 | GROUP BY D.domain 16 | ORDER BY H.createdate ASC'); 17 | 18 | 19 | $message = ''; 20 | $error = false; 21 | 22 | foreach($websites as $website) { 23 | 24 | // because call limit ip-api.com 25 | usleep(800000); 26 | $domain = $website['domain']; 27 | $ip = gethostbyname(idn_to_ascii($domain, INTL_IDNA_VARIANT_UTS46)); 28 | $url = 'http://ip-api.com/json/'.$ip; 29 | 30 | $ch = curl_init(); 31 | 32 | $options = array( 33 | CURLOPT_FOLLOWLOCATION => true, 34 | CURLOPT_AUTOREFERER => true, 35 | CURLOPT_MAXREDIRS => 4, 36 | CURLOPT_HEADER => false, 37 | CURLOPT_SSL_VERIFYPEER => false, 38 | CURLOPT_RETURNTRANSFER => true, 39 | CURLOPT_TIMEOUT => 10, 40 | CURLOPT_USERAGENT => 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:86.0) Gecko/20100101 Firefox/86.0', 41 | CURLOPT_URL => $url 42 | ); 43 | 44 | curl_setopt_array($ch, $options); 45 | $resps[$domain .";hosting"] = curl_exec($ch); 46 | 47 | curl_close($ch); 48 | 49 | if($website['is_ssl']) { 50 | $prefix = "https://"; 51 | 52 | // SSL Certificate 53 | set_error_handler(function(){return true;}); 54 | $orignal_parse = parse_url($prefix.$domain, PHP_URL_HOST); 55 | $get = stream_context_create(array("ssl" => array("capture_peer_cert" => TRUE))); 56 | $read = stream_socket_client("ssl://".$orignal_parse.":443", $errno, $errstr, 30, STREAM_CLIENT_CONNECT, $get); 57 | $cert = stream_context_get_params($read); 58 | restore_error_handler(); 59 | $certinfo = openssl_x509_parse($cert['options']['ssl']['peer_certificate']); 60 | 61 | $arr = json_decode($resps[$domain .";hosting"], TRUE); 62 | $arr['validFrom'] = $certinfo['validFrom_time_t']; 63 | $arr['validTo'] = $certinfo['validTo_time_t']; 64 | $resps[$domain .";hosting"] = json_encode($arr); 65 | 66 | } else { 67 | 68 | $arr = json_decode($resps[$domain .";hosting"], TRUE); 69 | $arr['validFrom'] = "-"; 70 | $arr['validTo'] = "-"; 71 | $resps[$domain .";hosting"] = json_encode($arr); 72 | 73 | } 74 | 75 | } 76 | 77 | foreach ($resps as $key => $response) { 78 | 79 | $domain = explode(";", $key)[0]; 80 | $mode = explode(";", $key)[1]; 81 | 82 | $hosting = json_decode($response, true); 83 | $ip = ''; 84 | $ip = gethostbyname(idn_to_ascii($domain)); 85 | 86 | if(json_last_error() === JSON_ERROR_NONE && (!array_key_exists("message", $hosting))) { 87 | if($mode == "hosting") { 88 | 89 | rex_sql::factory()->setDebug(0)->setQuery('INSERT INTO ' . rex::getTable('project_manager_domain_hosting') . ' (`domain`, `raw`, `createdate`, `ip`, `status`) VALUES(:domain, :response, NOW(), :ip, 1) 90 | ON DUPLICATE KEY UPDATE domain = :domain, `raw` = :response, createdate = NOW(), `ip` = :ip, `status` = 1', [":domain" => $domain, ":response" => $response, ":ip" => $ip] ); 91 | 92 | } 93 | } else { 94 | 95 | // ERROR HANDLE 96 | if($mode == "hosting") { 97 | 98 | rex_sql::factory()->setDebug(0)->setQuery('INSERT INTO ' . rex::getTable('project_manager_domain_hosting') . ' (`domain`, `raw`, `createdate`, `ip`, `status`) VALUES(:domain, :response, NOW(), :ip, -1) 99 | ON DUPLICATE KEY UPDATE domain = :domain, `raw` = :response, createdate = NOW(), `ip` = :ip, `status` = -1', [":domain" => $domain, ":response" => $response, ":ip" => $ip] ); 100 | 101 | } 102 | 103 | $message .= $domain.': '.$hosting['status'].' '.$hosting['message'].'\n'; 104 | $error = true; 105 | 106 | } 107 | } 108 | 109 | 110 | 111 | 112 | if ($error === true) { 113 | $this->setMessage($message); 114 | return false; 115 | } else { 116 | return true; 117 | } 118 | 119 | return true; 120 | } 121 | 122 | public function getTypeName() 123 | { 124 | return rex_i18n::msg('project_manager_cronjob_hosting_name'); 125 | } 126 | 127 | public function getParamFields() 128 | { 129 | return []; 130 | } 131 | } 132 | ?> -------------------------------------------------------------------------------- /plugins/hosting/package.yml: -------------------------------------------------------------------------------- 1 | package: project_manager/hosting 2 | version: '1.0.8' 3 | author: 'Friends Of REDAXO' 4 | supportpage: https://github.com/FriendsOfREDAXO/project_manager 5 | 6 | page: 7 | title: 'translate:hosting_menu_entry' 8 | icon: rex-icon fa-server # Icon von Font Awesome 9 | perm: project_manager_hosting[] 10 | 11 | pages: 12 | project_manager/hosting/overview: 13 | title: translate:project_manager_hosting_title 14 | 15 | requires: 16 | packages: 17 | project_manager: '^1.2.0' 18 | cronjob: '>=2.3.0' 19 | project_manager/server: '>=1.3.8' -------------------------------------------------------------------------------- /plugins/hosting/pages/content.hosting.php: -------------------------------------------------------------------------------- 1 | setDebug(0)->getArray($query, [$domain]); 14 | 15 | if (count($result) > 0) { 16 | 17 | $item = $result[0]; 18 | $raw = json_decode($item['raw'], true); 19 | 20 | if(is_array($raw)) { 21 | 22 | if (is_numeric($raw['validTo'])) { 23 | 24 | if ($raw['validTo'] < (time() + 2764800) ) { 25 | $validTo = ''.rex_formatter::format($raw['validTo'],'date','d.m.Y H:i:s').''; 26 | $validFrom = rex_formatter::format($raw['validFrom'],'date','d.m.Y H:i:s'); 27 | } else if ($raw['validTo'] < time()) { 28 | $validTo = ''.rex_formatter::format($raw['validTo'],'date','d.m.Y H:i:s').''; 29 | $validFrom = rex_formatter::format($raw['validFrom'],'date','d.m.Y H:i:s'); 30 | } else { 31 | $validTo = rex_formatter::format($raw['validTo'],'date','d.m.Y H:i:s'); 32 | $validFrom = rex_formatter::format($raw['validFrom'],'date','d.m.Y H:i:s'); 33 | } 34 | } else { 35 | $validFrom = "-"; 36 | $validTo = "-"; 37 | } 38 | 39 | $output = ''; 40 | $output .= ''; 41 | $output .= '
'.$this->i18n('organisation').''.$this->i18n('isp').''. $this->i18n('project_manager_hosting_ip').''.$this->i18n('validFrom').''.$this->i18n('validTo').'
'.(isset($raw['org']) ? $raw['org'] : '').''.(isset($raw['isp']) ? $raw['isp'] : '').'
'.(isset($raw['zip']) ? $raw['zip'] : '').' '.(isset($raw['city']) ? $raw['city'] : '').'
'.(isset($raw['country']) ? $raw['country'] : '').'
'.(isset($item['ip']) ? $item['ip']: '').''.$validFrom.''.$validTo.'
'; 42 | } 43 | 44 | } else { 45 | $output = "Keine Hostingdaten vorhanden!"; 46 | } 47 | 48 | return $output; 49 | 50 | } 51 | 52 | 53 | -------------------------------------------------------------------------------- /plugins/hosting/pages/project_manager.hosting.overview.php: -------------------------------------------------------------------------------- 1 | getValue(); 7 | $csrf = rex_csrf_token::factory('project_manager'); 8 | 9 | ############### 10 | ### 11 | ### LISTVIEW 12 | ### 13 | ############### 14 | if ($showlist) { 15 | 16 | $sql = 'SELECT * FROM ( 17 | SELECT * FROM '. rex::getTable('project_manager_domain') . ' as X ORDER BY name ASC 18 | ) AS D 19 | LEFT JOIN ( 20 | SELECT status as status_hosting, createdate as createdate_hosting, domain as hostingdomain, ip, raw 21 | FROM ' . rex::getTable('project_manager_domain_hosting') . ' 22 | ) as H 23 | ON D.domain = H.hostingdomain 24 | GROUP by D.domain 25 | ORDER BY name ASC'; 26 | 27 | $items = rex_sql::factory()->getArray($sql); 28 | 29 | // Cronjobcall 30 | $sql2 = 'SELECT * FROM '. rex::getTable('cronjob').' 31 | WHERE type = "rex_cronjob_project_manager_hosting"'; 32 | $cronjob = rex_sql::factory()->getArray($sql2); 33 | $cronjobId = $cronjob[0]['id']; 34 | 35 | $refresh = ''; 36 | if ($cronjobId != NULL) { 37 | $refresh = ' Hosting Daten aktualisieren'; 38 | } 39 | echo rex_view::info("Anzahl der Domains und Projekte: ".count($items) . $refresh); 40 | 41 | $list = rex_list::factory($sql, 1000); 42 | $list->addTableAttribute('class', 'table-striped'); 43 | $list->setNoRowsMessage($this->i18n('project_manager_hosting_domain_norows_message')); 44 | 45 | 46 | $list->setColumnFormat('id', 'Id'); 47 | $list->addParam('page', 'project_manager/server'); 48 | 49 | $list->setColumnParams('id', ['data_id' => '###id###', 'func' => 'edit']); 50 | $list->setColumnSortable('id'); 51 | 52 | $list->removeColumn('id'); 53 | $list->removeColumn('description'); 54 | $list->removeColumn('api_key'); 55 | $list->removeColumn('tags'); 56 | $list->removeColumn('cms'); 57 | $list->removeColumn('cms_version'); 58 | $list->removeColumn('createdate'); 59 | $list->removeColumn('createdate_hosting'); 60 | $list->removeColumn('rex_version'); 61 | $list->removeColumn('status'); 62 | $list->removeColumn('http_code'); 63 | $list->removeColumn('raw'); 64 | $list->removeColumn('domain'); 65 | $list->removeColumn('hostingdomain'); 66 | $list->removeColumn('updatedate'); 67 | $list->removeColumn('logdate'); 68 | $list->removeColumn('maintenance'); 69 | $list->removeColumn('param'); 70 | 71 | $list->setColumnLabel('name', $this->i18n('project_manager_hosting_name')); 72 | $list->setColumnParams('name', ['page' => 'project_manager/server/projects', 'func' => 'updateinfos', 'domain' => '###domain###']); 73 | 74 | $list->setColumnLabel('createdate_psi', $this->i18n('project_manager_hosting_updatedate')); 75 | $list->setColumnFormat('createdate_psi', 'custom', function ($params) { 76 | return (rex_formatter::format($params['list']->getValue('createdate_psi'),'date','d.m.Y H:i:s')); 77 | }); 78 | 79 | // icon column (Domain hinzufügen bzw. bearbeiten) 80 | $thIcon = ''; 81 | $tdIcon = ''; 82 | $list->addColumn($thIcon, $tdIcon, 0, ['###VALUE###', '###VALUE###']); 83 | $list->setColumnParams($thIcon, ['func' => 'domain_edit', 'id' => '###id###']); 84 | $list->setColumnFormat($thIcon, 'custom', function ($params) { 85 | $filename = ''; 86 | if (file_exists(rex_plugin::get('project_manager', 'server')->getAssetsPath('favicon/'.$params['list']->getValue('domain').'.png'))) { 87 | $filename = rex_plugin::get('project_manager', 'server')->getAssetsUrl('favicon/'.$params['list']->getValue('domain').'.png'); 88 | return ''; 89 | } else { 90 | return ''; 91 | } 92 | }); 93 | 94 | $list->addColumn($this->i18n('project_manager_hosting_domain'), '###domain###', 3); 95 | //$list->setColumnParams($this->i18n('project_manager_hosting_domain'), ['page' => 'project_manager/server/projects', 'func' => 'updateinfos', 'domain' => '###domain###']); 96 | $list->setColumnFormat($this->i18n('project_manager_hosting_domain'), 'custom', function ($params) { 97 | return ''.$params['list']->getValue('domain').''; 98 | }); 99 | 100 | 101 | $list->setColumnLabel('is_ssl', $this->i18n('is_ssl')); 102 | $list->setColumnLayout('is_ssl', ['###VALUE###', '###VALUE###']); 103 | $list->setColumnFormat('is_ssl', 'custom', function ($params) { 104 | if ($params['list']->getValue('is_ssl') == "1") { 105 | return ''; 106 | } else if ($params['list']->getValue('is_ssl') == "0") { 107 | return ''; 108 | } else { 109 | return "?"; 110 | } 111 | }); 112 | 113 | $list->addColumn($this->i18n('organisation'), false, -1, ['###VALUE###', '###VALUE### ']); 114 | $list->setColumnLabel($this->i18n('organisation'), $this->i18n('organisation')); 115 | $list->setColumnFormat($this->i18n('organisation'), 'custom', function ($params) { 116 | 117 | if($params['list']->getValue('raw')) { 118 | $raw= json_decode($params['list']->getValue('raw'), true); 119 | if (array_key_exists("org", $raw)) { 120 | return $raw['org']; 121 | } 122 | } 123 | }); 124 | 125 | $list->setColumnLabel('ip', $this->i18n('project_manager_hosting_ip')); 126 | 127 | $list->setColumnLabel('status_hosting', $this->i18n('status')); 128 | $list->setColumnFormat('status_hosting', 'custom', function ($params) { 129 | if ($params['list']->getValue('status_hosting') == "1") { 130 | return ''; 131 | } else if ($params['list']->getValue('status_hosting') == "0") { 132 | return ''; 133 | } else if ($params['list']->getValue('status_hosting') == "-1") { 134 | return ''; 135 | } else if ($params['list']->getValue('status_hosting') == "2") { 136 | return ''; 137 | } 138 | }); 139 | $list->setColumnLayout('status', ['###VALUE###', '###VALUE###']); 140 | 141 | $list->addColumn($this->i18n('validTo'), false, -1, ['###VALUE###', '###VALUE### ']); 142 | $list->setColumnLabel($this->i18n('validTo'), $this->i18n('validTo')); 143 | $list->setColumnFormat($this->i18n('validTo'), 'custom', function ($params) { 144 | 145 | if($params['list']->getValue('raw')) { 146 | $raw= json_decode($params['list']->getValue('raw'), true); 147 | if (array_key_exists("validTo", $raw)) { 148 | 149 | if (is_numeric($raw['validTo'])) { 150 | 151 | if ($raw['validTo'] < (time() + 2764800) ) { 152 | return ''.rex_formatter::format($raw['validTo'],'date','d.m.Y H:i:s').''; 153 | } else if ($raw['validTo'] < time()) { 154 | return ''.rex_formatter::format($raw['validTo'],'date','d.m.Y H:i:s').''; 155 | } else { 156 | return rex_formatter::format($raw['validTo'],'date','d.m.Y H:i:s'); 157 | } 158 | } else { 159 | return "-"; 160 | } 161 | 162 | } 163 | } 164 | }); 165 | 166 | $content = $list->get(); 167 | $content = str_replace('setVar('title', $this->i18n('projects')); 171 | $fragment->setVar('content', $content, false); 172 | echo $fragment->parse('core/page/section.php'); 173 | } 174 | -------------------------------------------------------------------------------- /plugins/hosting/uninstall.php: -------------------------------------------------------------------------------- 1 | setQuery("DELETE FROM ". rex::getTablePrefix() ."cronjob WHERE type LIKE 'rex_cronjob_project_manager_hosting%'"); 4 | 5 | rex_sql_table::get(rex::getTable('project_manager_domain_hosting'))->drop(); 6 | -------------------------------------------------------------------------------- /plugins/pagespeed/boot.php: -------------------------------------------------------------------------------- 1 | isAvailable()) { 4 | rex_cronjob_manager::registerType('rex_cronjob_project_manager_pagespeed'); 5 | } 6 | 7 | // PROJECT_MANAGER_SERVER_DETAIL_HOOK 8 | if (rex::isBackend() && rex::getUser()) { 9 | 10 | rex_extension::register('PROJECT_MANAGER_SERVER_DETAIL_HOOK', function (rex_extension_point $ep) { 11 | 12 | $exist = ''; 13 | if ($ep->getSubject() != "") { 14 | $exist = $ep->getSubject(); 15 | } 16 | 17 | $params = $ep->getParams(); 18 | $panel = include(rex_path::plugin('project_manager', 'pagespeed', 'pages/content.pagespeed.php')); 19 | 20 | $fragment = new rex_fragment(); 21 | $fragment->setVar('title', "PageSpeed", false); 22 | $fragment->setVar('body', $panel, false); 23 | $fragment->setVar('class', 'panel panel-info', false); 24 | $fragment->setVar('domain', $params["domain"], false); 25 | 26 | $fragment->setVar('collapse', true); 27 | $fragment->setVar('collapsed', true); 28 | $pagespeed = '
'.$fragment->parse('core/page/section.php').'
'; 29 | 30 | return $exist.$pagespeed; 31 | 32 | }); 33 | 34 | } 35 | 36 | 37 | if (rex::isBackend() && is_object(rex::getUser())) { 38 | rex_perm::register('project_manager_pagespeed[]'); 39 | } 40 | 41 | -------------------------------------------------------------------------------- /plugins/pagespeed/install.php: -------------------------------------------------------------------------------- 1 | ensurePrimaryIdColumn() 6 | ->ensureColumn(new rex_sql_column('domain', 'varchar(255)', false, null, ''))->setPrimaryKey('domain') 7 | ->ensureColumn(new rex_sql_column('raw', 'longtext', true)) 8 | ->ensureColumn(new rex_sql_column('createdate', 'timestamp', false, '0000-00-00 00:00:00', 'on update CURRENT_TIMESTAMP')) 9 | ->ensureColumn(new rex_sql_column('score_desktop', 'text')) 10 | ->ensureColumn(new rex_sql_column('score_mobile', 'text')) 11 | ->ensureColumn(new rex_sql_column('status', 'text')) 12 | ->ensure(); 13 | 14 | 15 | // Create cronjob 16 | $now = new DateTime(); 17 | $startdate = date('Y-m-d 00:00:00',strtotime( "tomorrow" )); 18 | 19 | $cronjob = rex_sql::factory(); 20 | $cronjob->setDebug(true); 21 | $cronjob->setQuery('SELECT id FROM '.rex::getTable('cronjob'). ' WHERE type LIKE "rex_cronjob_project_manager_pagespeed"'); 22 | 23 | if ($cronjob->getRows() == 0) { 24 | 25 | $cronjob = rex_sql::factory(); 26 | $cronjob->setDebug(true); 27 | $cronjob->setTable(rex::getTable('cronjob')); 28 | $cronjob->setValue('name','Projekt Manager: PageSpeed Daten'); 29 | $cronjob->setValue('description',''); 30 | $cronjob->setValue('type','rex_cronjob_project_manager_pagespeed'); 31 | $cronjob->setValue('interval','{"minutes":[0],"hours":[0],"days":"all","weekdays":"all","months":"all"}'); 32 | $cronjob->setValue('environment','|backend|'); 33 | $cronjob->setValue('execution_start','1970-01-01 01:00:00'); 34 | $cronjob->setValue('status','1'); 35 | $cronjob->setValue('parameters','[]'); 36 | $cronjob->setValue('nexttime',$startdate); 37 | $cronjob->setValue('createdate',$now->format('Y-m-d H:i:s')); 38 | $cronjob->setValue('updatedate',$now->format('Y-m-d H:i:s')); 39 | $cronjob->setValue('createuser',rex::getUser()->getLogin()); 40 | $cronjob->setValue('updateuser',rex::getUser()->getLogin()); 41 | 42 | try { 43 | $cronjob->insertOrUpdate(); 44 | echo rex_view::success('Der Cronjob "Projekt Manager: PageSpeed Daten" wurde angelegt. '); 45 | } catch (rex_sql_exception $e) { 46 | echo rex_view::warning('Der Cronjob "Projekt Manager: PageSpeed Daten" wurde nicht angelegt.
Wahrscheinlich existiert er schon.'); 47 | } 48 | } -------------------------------------------------------------------------------- /plugins/pagespeed/lang/de_de.lang: -------------------------------------------------------------------------------- 1 | project_manager_pagespeed_menu_entry = PageSpeed 2 | 3 | project_manager_pagespeed_projects = Projekte 4 | project_manager_pagespeed_title = Übersicht 5 | project_manager_pagespeed_config = Einstellungen 6 | project_manager_pagespeed_api_key_title = Einstellungen 7 | project_manager_pagespeed_api_key_label = PageSpeed API-Schlüssel 8 | project_manager_pagespeed_api_key_notice = PageSpeed API-Schlüssel, z.B. AIzaSyCp0Em_UPY78238es-9CZViEbq7CB_zcFBs 9 | project_manager_pagespeed_domain_norows_message = Kein Projekt vorhanden 10 | project_manager_cronjob_pagespeed_name = Projekt Manager: Hole Pagespeed Daten 11 | 12 | 13 | project_manager_pagespeed_name = Projektname 14 | project_manager_pagespeed_domain = Domain 15 | project_manager_pagespeed_updatedate = Letzte Änderung 16 | project_manager_pagespeed_logdate = Letzter Datenfetch 17 | project_manager_pagespeed_domain_norows_message = Keine Einträge vorhanden 18 | 19 | perm_general_project_manager_pagespeed[] = project_manager_pagespeed[] - Rechte für Projekt Manager PageSpeed -------------------------------------------------------------------------------- /plugins/pagespeed/lang/en_gb.lang: -------------------------------------------------------------------------------- 1 | project_manager_pagespeed_menu_entry = PageSpeed 2 | 3 | project_manager_pagespeed_projects = Projects 4 | project_manager_pagespeed_title = Overview 5 | project_manager_pagespeed_config = Settings 6 | project_manager_pagespeed_api_key_title = Settings 7 | project_manager_pagespeed_api_key_label = PageSpeed API key 8 | project_manager_pagespeed_api_key_notice = PageSpeed API key, ex. AIzaSyCp0Em_UPY78238es-9CZViEbq7CB_zcFBs 9 | project_manager_pagespeed_domain_norows_message = No entries found 10 | project_manager_cronjob_pagespeed_name = Project manager: get PageSpeed data 11 | 12 | 13 | project_manager_pagespeed_name = Project name 14 | project_manager_pagespeed_domain = Domain 15 | project_manager_pagespeed_updatedate = Last update 16 | project_manager_pagespeed_logdate = Last data fetch 17 | project_manager_pagespeed_domain_norows_message = No entries found 18 | 19 | perm_general_project_manager_pagespeed[] = project_manager_pagespeed[] - Permissions for Project Manager Pagespeed -------------------------------------------------------------------------------- /plugins/pagespeed/lang/es_es.lang: -------------------------------------------------------------------------------- 1 | documentation_menu_entry = Documentación 2 | 3 | documentation_navigation_title = Navegación [main_navi.md] 4 | documentation_content_title = Contenido [ {0} ] 5 | 6 | documentation_noparser = ¡No hay ningún Markdown parser disponible! Instale primero un analizador (addon markitup o textil) 7 | 8 | documentation_navinotfound = ¡No se encontró el archivo de navegación {0}!
¡Este archivo es obligatorio! 9 | documentation_filenotfound = No se encontró el archivo {0}. El contenido no existe (aún).

Estamos entusiasmados con la ayuda: {1} 10 | -------------------------------------------------------------------------------- /plugins/pagespeed/lang/pt_br.lang: -------------------------------------------------------------------------------- 1 | documentation_menu_entry = Documentação 2 | 3 | documentation_navigation_title = Navegação [ main_navi.md ] 4 | documentation_content_title = Conteúdo [ {0} ] 5 | 6 | documentation_noparser = Nenhum analisador Markdown disponível! Instale primeiro um analisador (AddOn markitup or textile) 7 | 8 | documentation_navinotfound = Arquivo de navegação {0} não localizado!
Este arquivo é necessário! 9 | documentation_filenotfound = Arquivo {0} não localizado. Conteúdos não existem (ainda)

Ficaríamos felizes se você quisesse ajudar: {1} 10 | -------------------------------------------------------------------------------- /plugins/pagespeed/lang/sv_se.lang: -------------------------------------------------------------------------------- 1 | project_manager_pagespeed_menu_entry = PageSpeed 2 | 3 | project_manager_pagespeed_projects = Projekter 4 | project_manager_pagespeed_title = Översikt 5 | project_manager_pagespeed_config = Inställningar 6 | project_manager_pagespeed_api_key_title = Inställningar 7 | project_manager_pagespeed_api_key_label = PageSpeed API-key 8 | project_manager_pagespeed_api_key_notice = PageSpeed API-nyckel, t.ex. AIzaSyCp0Em_UPY78238es-9CZViEbq7CB_zcFBs 9 | project_manager_pagespeed_domain_norows_message = Inga poster tillgängliga 10 | project_manager_cronjob_pagespeed_name = Projektledare: Hämta PageSpeed-uppgifter 11 | 12 | 13 | project_manager_pagespeed_name = Projektnamn 14 | project_manager_pagespeed_domain = Domän 15 | project_manager_pagespeed_updatedate = Senaste ändring 16 | project_manager_pagespeed_logdate = Senaste datafetch 17 | project_manager_pagespeed_domain_norows_message = Inga poster tillgängliga 18 | 19 | perm_general_project_manager_pagespeed[] = project_manager_pagespeed [] - Rättigheter till Projekt Manager PageSpeed -------------------------------------------------------------------------------- /plugins/pagespeed/lib/project-manager-pagespeed.cronjob.php: -------------------------------------------------------------------------------- 1 | setDebug(0)->getArray('SELECT count(*) as count FROM rex_project_manager_domain'); 9 | if ($count[0]['count'] <= 10) { 10 | $count = 1; 11 | } else { 12 | $count = $count[0]['count'] / 10; 13 | $count = round($count, 0, PHP_ROUND_HALF_UP); 14 | } 15 | 16 | for ($i = 0; $i < $count; $i++) { 17 | $this->getData(); 18 | } 19 | 20 | return true; 21 | 22 | } 23 | 24 | public function getData() { 25 | 26 | $websites = rex_sql::factory()->setDebug(0)->getArray('SELECT D.domain AS domain, D.is_ssl as is_ssl FROM 27 | (SELECT domain, createdate FROM rex_project_manager_domain_psi) AS PSI 28 | RIGHT JOIN 29 | (SELECT domain, updatedate, is_ssl FROM rex_project_manager_domain) AS D 30 | ON 31 | PSI.domain = D.domain 32 | GROUP BY D.domain 33 | ORDER BY PSI.createdate ASC LIMIT 10'); 34 | 35 | $error = false; 36 | $multi_curl = curl_multi_init(); 37 | $resps = array(); 38 | $options = array( 39 | CURLOPT_FOLLOWLOCATION => true, 40 | CURLOPT_AUTOREFERER => true, 41 | CURLOPT_MAXREDIRS => 4, 42 | CURLOPT_HEADER => false, 43 | CURLOPT_RETURNTRANSFER => true, 44 | CURLOPT_SSL_VERIFYPEER => false, 45 | CURLOPT_USERAGENT => 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:86.0) Gecko/20100101 Firefox/86.0', 46 | CURLOPT_TIMEOUT => 30 // seconds 47 | ); 48 | 49 | foreach($websites as $website) { 50 | 51 | $fstreams = array(); 52 | 53 | $domain = $website['domain']; 54 | if($website['is_ssl']) { 55 | $prefix = "https://"; 56 | } else { 57 | $prefix = "http://"; 58 | } 59 | 60 | $url_desktop = 'https://www.googleapis.com/pagespeedonline/v5/runPagespeed?filter_third_party_resources=false&locale=de_DE&screenshot=true&snapshots=false&strategy=desktop&key='.rex_config::get('project_manager/pagespeed', 'project_manager_pagespeed_api_key').'&url='.urlencode($prefix.$website['domain']); 61 | $url_mobile = 'https://www.googleapis.com/pagespeedonline/v5/runPagespeed?filter_third_party_resources=false&locale=de_DE&screenshot=true&snapshots=false&strategy=mobile&key='.rex_config::get('project_manager/pagespeed', 'project_manager_pagespeed_api_key').'&url='.urlencode($prefix.$website['domain']); 62 | $resps[$domain.";mobile"] = curl_init($url_mobile); 63 | $resps[$domain.";desktop"] = curl_init($url_desktop); 64 | curl_setopt_array($resps[$domain.";mobile"], $options); 65 | curl_setopt_array($resps[$domain.";desktop"], $options); 66 | curl_multi_add_handle($multi_curl, $resps[$domain.";mobile"]); 67 | curl_multi_add_handle($multi_curl, $resps[$domain.";desktop"]); 68 | 69 | } 70 | 71 | $active = null; 72 | do { 73 | curl_multi_exec($multi_curl, $active); 74 | } while ($active > 0); 75 | 76 | 77 | foreach ($resps as $key => $response) { 78 | $domain = explode(";", $key)[0]; 79 | $mode = explode(";", $key)[1]; 80 | $resp = curl_multi_getcontent($response); 81 | curl_multi_remove_handle($multi_curl, $response); 82 | $pagespeed = json_decode($resp, true); 83 | 84 | $score_mobile = 0; 85 | $score_desktop = 0; 86 | if (isset($pagespeed['lighthouseResult'])) { 87 | if ($pagespeed['lighthouseResult']['categories']['performance']['score'] != NULL) $score_mobile = $pagespeed['lighthouseResult']['categories']['performance']['score']; 88 | if ($pagespeed['lighthouseResult']['categories']['performance']['score'] != NULL) $score_desktop = $pagespeed['lighthouseResult']['categories']['performance']['score']; 89 | } 90 | if(json_last_error() === JSON_ERROR_NONE && (!array_key_exists("error", $pagespeed))) { 91 | if($mode == "mobile") { 92 | rex_sql::factory()->setDebug(0)->setQuery('INSERT INTO ' . rex::getTable('project_manager_domain_psi') . ' (`domain`, `raw`, `createdate`, `score_mobile`, `status`) VALUES(:domain, :resp, NOW(), :score_mobile, 1) 93 | ON DUPLICATE KEY UPDATE domain = :domain, `raw` = :resp, createdate = NOW(), `score_mobile` = :score_mobile, `status` = 1', [":domain" => $domain, ":resp" => $resp, ":score_mobile" => $score_mobile] ); 94 | } else if($mode == "desktop") { 95 | rex_sql::factory()->setDebug(0)->setQuery('INSERT INTO ' . rex::getTable('project_manager_domain_psi') . ' (`domain`, `raw`, `createdate`, `score_desktop`, `status`) VALUES(:domain, :resp, NOW(), :score_desktop, 1) 96 | ON DUPLICATE KEY UPDATE domain = :domain, `raw` = :resp, createdate = NOW(), `score_desktop` = :score_desktop, `status` = 1', [":domain" => $domain, ":resp" => $resp, ":score_desktop" => $score_desktop] ); 97 | } 98 | } else { 99 | 100 | // ERROR HANDLE 101 | if($mode == "desktop") { 102 | 103 | rex_sql::factory()->setDebug(0)->setQuery('INSERT INTO ' . rex::getTable('project_manager_domain_psi') . ' (`domain`, `raw`, `createdate`, `status`) VALUES(:domain, :resp, NOW(), -1) 104 | ON DUPLICATE KEY UPDATE domain = :domain, `raw` = :resp, createdate = NOW(), `status` = -1', [":domain" => $domain, ":resp" => $resp] ); 105 | 106 | } else if($mode == "mobile") { 107 | rex_sql::factory()->setDebug(0)->setQuery('INSERT INTO ' . rex::getTable('project_manager_domain_psi') . ' (`domain`, `raw`, `createdate`, `status`) VALUES(:domain, :resp, NOW(), -1) 108 | ON DUPLICATE KEY UPDATE domain = :domain, `raw` = :resp, createdate = NOW(), `status` = -1', [":domain" => $domain, ":resp" => $resp] ); 109 | 110 | } 111 | 112 | $this->setMessage($pagespeed['error']['errors'][0]['message'].': '.$pagespeed['error']['errors'][0]['reason']); 113 | $error = true; 114 | 115 | } 116 | } 117 | curl_multi_close($multi_curl); 118 | 119 | if ($error === true) { 120 | return false; 121 | } else { 122 | return true; 123 | } 124 | } 125 | public function getTypeName() 126 | { 127 | return rex_i18n::msg('project_manager_cronjob_pagespeed_name'); 128 | } 129 | 130 | public function getParamFields() 131 | { 132 | return []; 133 | } 134 | } 135 | ?> -------------------------------------------------------------------------------- /plugins/pagespeed/package.yml: -------------------------------------------------------------------------------- 1 | package: project_manager/pagespeed 2 | version: '1.2.4' 3 | author: 'Friends Of REDAXO' 4 | supportpage: https://github.com/FriendsOfREDAXO/project_manager 5 | 6 | page: 7 | title: 'translate:pagespeed_menu_entry' 8 | icon: rex-icon fa-tachometer # Icon von Font Awesome 9 | perm: project_manager_pagespeed[] 10 | 11 | pages: 12 | project_manager/pagespeed/overview: 13 | title: 'translate:project_manager_pagespeed_title' 14 | project_manager/pagespeed/config: 15 | title: 'translate:project_manager_pagespeed_config' 16 | 17 | requires: 18 | packages: 19 | project_manager: '^1.0.0' 20 | cronjob: '>=2.3.0' 21 | project_manager/server: '>=1.3.8' -------------------------------------------------------------------------------- /plugins/pagespeed/pages/content.pagespeed.php: -------------------------------------------------------------------------------- 1 | setDebug(0)->getArray($query, [$domain])[0]; 15 | 16 | $raw = json_decode($item['raw'], true); 17 | 18 | if(is_array($raw)) { 19 | 20 | // PSI 21 | $query = ' 22 | SELECT * FROM (SELECT * FROM ' . rex::getTable('project_manager_domain') . ' ORDER BY domain) AS D 23 | LEFT JOIN ( 24 | SELECT domain, raw, score_desktop AS psi_score_desktop 25 | FROM ' . rex::getTable('project_manager_domain_psi') . ' 26 | WHERE score_desktop NOT LIKE "") as PSI 27 | ON D.domain = PSI.domain 28 | LEFT JOIN ( 29 | SELECT domain, score_mobile AS psi_score_mobile 30 | FROM ' . rex::getTable('project_manager_domain_psi') . ' 31 | WHERE score_mobile NOT LIKE "") as PSI2 32 | ON D.domain = PSI2.domain 33 | WHERE D.domain = ? 34 | GROUP BY D.domain 35 | ORDER BY D.domain 36 | '; 37 | 38 | $item = rex_sql::factory()->setDebug(0)->getArray($query, [$domain])[0]; 39 | 40 | // Screenshot 41 | $raw= json_decode($item['raw'], true); 42 | $image = ''; 43 | $data = ''; 44 | if (isset($raw['lighthouseResult'])) { 45 | $data = $raw['lighthouseResult']['audits']['final-screenshot']['details']['data']; 46 | $image = $data; 47 | } 48 | 49 | if($item['psi_score_desktop'] < 0.7) { 50 | $class = ' '; 51 | } else if($item['psi_score_desktop'] < 0.9) { 52 | $class = ' '; 53 | } else { 54 | $class = ' '; 55 | } 56 | 57 | if($item['psi_score_mobile'] < 0.7) { 58 | $classmobile = ' '; 59 | } else if($item['psi_score_mobile'] < 0.9) { 60 | $classmobile = ' '; 61 | } else { 62 | $classmobile = ' '; 63 | } 64 | 65 | $output = ''; 66 | $output = '
'; 67 | $output .= ''; 68 | $output .= '
NameResultScreenshot
Page Speed'.$class.$item['psi_score_desktop'].' | '.$classmobile.$item['psi_score_mobile'].'
'; 69 | 70 | return $output; 71 | 72 | } 73 | } 74 | 75 | 76 | -------------------------------------------------------------------------------- /plugins/pagespeed/pages/project_manager.pagespeed.config.php: -------------------------------------------------------------------------------- 1 | setConfig(rex_post('config', [ 6 | ['project_manager_pagespeed_api_key', 'string'] 7 | ])); 8 | 9 | $message = $this->i18n('project_manager_pagespeed_api_key_saved_successful'); 10 | } 11 | 12 | $content = ''; 13 | 14 | 15 | $formElements = []; 16 | $n = []; 17 | $n['label'] = ''; 18 | $n['field'] = ''; 19 | $n['note'] = $this->i18n('project_manager_pagespeed_api_key_notice'); 20 | $formElements[] = $n; 21 | 22 | $fragment = new rex_fragment(); 23 | $fragment->setVar('elements', $formElements, false); 24 | $fragment->setVar('class', "panel panel-warning", false); 25 | $content .= $fragment->parse('core/form/form.php'); 26 | 27 | $formElements = []; 28 | $n = []; 29 | $n['field'] = ''; 30 | $formElements[] = $n; 31 | 32 | $fragment = new rex_fragment(); 33 | $fragment->setVar('flush', true); 34 | $fragment->setVar('elements', $formElements, false); 35 | $buttons = $fragment->parse('core/form/submit.php'); 36 | 37 | $fragment = new rex_fragment(); 38 | $fragment->setVar('class', 'edit', false); 39 | $fragment->setVar('title', $this->i18n('project_manager_pagespeed_api_key_title'), false); 40 | $fragment->setVar('body', $content, false); 41 | $fragment->setVar('buttons', $buttons, false); 42 | $content = $fragment->parse('core/page/section.php'); 43 | echo ' 44 |
45 | ' . $content . ' 46 |
'; -------------------------------------------------------------------------------- /plugins/pagespeed/pages/project_manager.pagespeed.overview.php: -------------------------------------------------------------------------------- 1 | getValue(); 7 | $csrf = rex_csrf_token::factory('project_manager'); 8 | 9 | ############### 10 | ### 11 | ### LISTVIEW 12 | ### 13 | ############### 14 | if ($showlist) { 15 | 16 | $sql = 'SELECT * FROM ( 17 | SELECT * FROM '. rex::getTable('project_manager_domain') . ' as X ORDER BY name ASC 18 | ) AS D 19 | LEFT JOIN ( 20 | SELECT status as status_psi, createdate as createdate_psi, domain as psidomain, score_desktop AS psi_score_desktop, score_mobile AS psi_score_mobile 21 | FROM ' . rex::getTable('project_manager_domain_psi') . ' 22 | ) as PSI 23 | ON D.domain = PSI.psidomain 24 | GROUP by D.domain 25 | ORDER BY name ASC 26 | '; 27 | 28 | $items = rex_sql::factory()->getArray($sql); 29 | 30 | $sql2 = 'SELECT * FROM '. rex::getTable('cronjob').' 31 | WHERE type = "rex_cronjob_project_manager_pagespeed"'; 32 | $cronjob = rex_sql::factory()->getArray($sql2); 33 | $cronjobId = $cronjob[0]['id']; 34 | 35 | $refresh = ''; 36 | if ($cronjobId != NULL) { 37 | $refresh = ' PageSpeed Daten aktualisieren'; 38 | } 39 | echo rex_view::info("Anzahl der Domains und Projekte: ".count($items) . $refresh); 40 | 41 | $list = rex_list::factory($sql, 1000); 42 | $list->addTableAttribute('class', 'table-striped'); 43 | $list->setNoRowsMessage($this->i18n('project_manager_pagespeed_domain_norows_message')); 44 | 45 | $list->setColumnFormat('id', 'Id'); 46 | $list->addParam('page', 'project_manager/server'); 47 | 48 | $list->setColumnParams('id', ['data_id' => '###id###', 'func' => 'edit']); 49 | $list->setColumnSortable('id'); 50 | 51 | $list->removeColumn('id'); 52 | $list->removeColumn('is_ssl'); 53 | $list->removeColumn('description'); 54 | $list->removeColumn('api_key'); 55 | $list->removeColumn('tags'); 56 | $list->removeColumn('cms'); 57 | $list->removeColumn('cms_version'); 58 | $list->removeColumn('createdate'); 59 | $list->removeColumn('rex_version'); 60 | $list->removeColumn('status'); 61 | $list->removeColumn('http_code'); 62 | $list->removeColumn('is_ssl'); 63 | $list->removeColumn('domain'); 64 | $list->removeColumn('psidomain'); 65 | $list->removeColumn('updatedate'); 66 | $list->removeColumn('createdate'); 67 | $list->removeColumn('psi_domain'); 68 | $list->removeColumn('psi_score_desktop'); 69 | $list->removeColumn('psi_score_mobile'); 70 | $list->removeColumn('maintenance'); 71 | $list->removeColumn('param'); 72 | 73 | $list->setColumnLabel('name', $this->i18n('project_manager_pagespeed_name')); 74 | $list->setColumnParams('name', ['page' => 'project_manager/server/projects', 'func' => 'updateinfos', 'domain' => '###domain###']); 75 | 76 | $list->setColumnLabel('createdate_psi', $this->i18n('project_manager_pagespeed_updatedate')); 77 | $list->setColumnFormat('createdate_psi', 'custom', function ($params) { 78 | return (rex_formatter::format($params['list']->getValue('createdate_psi'),'date','d.m.Y H:i:s')); 79 | }); 80 | 81 | // icon column (Domain hinzufügen bzw. bearbeiten) 82 | $thIcon = ''; 83 | $tdIcon = ''; 84 | $list->addColumn($thIcon, $tdIcon, 0, ['###VALUE###', '###VALUE###']); 85 | $list->setColumnParams($thIcon, ['func' => 'domain_edit', 'id' => '###id###']); 86 | $list->setColumnFormat($thIcon, 'custom', function ($params) { 87 | $filename = ''; 88 | if (file_exists(rex_plugin::get('project_manager', 'server')->getAssetsPath('favicon/'.$params['list']->getValue('domain').'.png'))) { 89 | $filename = rex_plugin::get('project_manager', 'server')->getAssetsUrl('favicon/'.$params['list']->getValue('domain').'.png'); 90 | return ''; 91 | } else { 92 | return ''; 93 | } 94 | }); 95 | 96 | $list->addColumn($this->i18n('project_manager_pagespeed_domain'), '###domain###', 3); 97 | //$list->setColumnParams($this->i18n('project_manager_pagespeed_domain'), ['page' => 'project_manager/server/projects', 'func' => 'updateinfos', 'domain' => '###domain###']); 98 | $list->setColumnFormat($this->i18n('project_manager_pagespeed_domain'), 'custom', function ($params) { 99 | return ''.$params['list']->getValue('domain').''; 100 | }); 101 | 102 | 103 | $list->setColumnLabel('status_psi', $this->i18n('status')); 104 | $list->setColumnFormat('status_psi', 'custom', function ($params) { 105 | if ($params['list']->getValue('status_psi') == "1") { 106 | return ''; 107 | } else if ($params['list']->getValue('status_psi') == "0") { 108 | return ''; 109 | } else if ($params['list']->getValue('status_psi') == "-1") { 110 | return ''; 111 | } else if ($params['list']->getValue('status_psi') == "2") { 112 | return ''; 113 | } else { 114 | if ($params['list']->getValue('is_ssl') == 1) 115 | return ''; 116 | 117 | if ($params['list']->getValue('is_ssl') == 0) 118 | return ''; 119 | } 120 | }); 121 | 122 | $list->setColumnLayout('status', ['###VALUE###', '###VALUE###']); 123 | 124 | 125 | $list->addColumn("Pagespeed", false, -1, ['PageSpeed', '###VALUE###']); 126 | $list->setColumnFormat("Pagespeed", 'custom', function ($params) { 127 | 128 | if($params['list']->getValue('psi_score_desktop') < 0.7) { 129 | $return = ' '.$params['list']->getValue('psi_score_desktop'); 130 | } else if($params['list']->getValue('psi_score_desktop') < 0.9) { 131 | $return = ' '.$params['list']->getValue('psi_score_desktop'); 132 | } else { 133 | $return = ' '.$params['list']->getValue('psi_score_desktop'); 134 | } 135 | $return .= " | "; 136 | if($params['list']->getValue('psi_score_mobile') < 0.7) { 137 | $return .= ' '.$params['list']->getValue('psi_score_mobile'); 138 | } else if($params['list']->getValue('psi_score_mobile') < 0.9) { 139 | $return .= ' '.$params['list']->getValue('psi_score_mobile'); 140 | } else { 141 | $return .= ' '.$params['list']->getValue('psi_score_mobile'); 142 | } 143 | return $return; 144 | }); 145 | 146 | 147 | $content = $list->get(); 148 | $content = str_replace('setVar('title', $this->i18n('projects')); 152 | $fragment->setVar('content', $content, false); 153 | echo $fragment->parse('core/page/section.php'); 154 | } 155 | -------------------------------------------------------------------------------- /plugins/pagespeed/uninstall.php: -------------------------------------------------------------------------------- 1 | setQuery("DELETE FROM ". rex::getTablePrefix() ."cronjob WHERE type LIKE 'rex_cronjob_project_manager_pagespeed%'"); 4 | 5 | rex_sql_table::get(rex::getTable('project_manager_domain_psi'))->drop(); 6 | -------------------------------------------------------------------------------- /plugins/server/assets/css/bootstrap-tagsinput.css: -------------------------------------------------------------------------------- 1 | .bootstrap-tagsinput { 2 | max-width: 100%; 3 | cursor: text; 4 | display: block; 5 | width: 100%; 6 | height: 34px; 7 | padding: 6px 12px; 8 | font-size: 14px; 9 | line-height: 1.428571429; 10 | color: #324050; 11 | background-color: #f3f6fb; 12 | background-image: none; 13 | border: 1px solid #c1c9d4; 14 | border-radius: 0; 15 | -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); 16 | box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); 17 | -webkit-transition: border-color ease-in-out 0.15s, box-shadow ease-in-out 0.15s; 18 | -o-transition: border-color ease-in-out 0.15s, box-shadow ease-in-out 0.15s; 19 | transition: border-color ease-in-out 0.15s, box-shadow ease-in-out 0.15s; 20 | } 21 | .bootstrap-tagsinput input { 22 | border: none; 23 | box-shadow: none; 24 | outline: none; 25 | background-color: transparent; 26 | padding: 0 6px; 27 | margin: 0; 28 | width: auto; 29 | max-width: inherit; 30 | min-width: 300px; 31 | } 32 | .bootstrap-tagsinput.form-control input::-moz-placeholder { 33 | color: #777; 34 | opacity: 1; 35 | } 36 | .bootstrap-tagsinput.form-control input:-ms-input-placeholder { 37 | color: #777; 38 | } 39 | .bootstrap-tagsinput.form-control input::-webkit-input-placeholder { 40 | color: #777; 41 | } 42 | .bootstrap-tagsinput input:focus { 43 | border: none; 44 | box-shadow: none; 45 | } 46 | .bootstrap-tagsinput .tag { 47 | margin-right: 2px; 48 | color: white; 49 | background-color: #192A42; 50 | font-size: 100%; 51 | font-weight: normal; 52 | } 53 | .bootstrap-tagsinput .tag [data-role="remove"] { 54 | margin-left: 8px; 55 | cursor: pointer; 56 | } 57 | .bootstrap-tagsinput .tag [data-role="remove"]:after { 58 | content: "x"; 59 | padding: 0px 2px; 60 | } 61 | .bootstrap-tagsinput .tag [data-role="remove"]:hover { 62 | box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05); 63 | } 64 | .bootstrap-tagsinput .tag [data-role="remove"]:hover:active { 65 | box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); 66 | } 67 | -------------------------------------------------------------------------------- /plugins/server/assets/css/theme.css: -------------------------------------------------------------------------------- 1 | td.alert-danger.project-manager, 2 | .tablesorter-default td.alert-danger { 3 | background-color: #d9534f !important; 4 | border-color: #d9534f !important; 5 | color: #fff !important; 6 | } 7 | td.alert-warning.project-manager, 8 | .tablesorter-default td.alert-warning { 9 | background-color: #ffaeac !important; 10 | border-color: ffaeac !important; 11 | color: #fff !important; 12 | } 13 | 14 | button.loading .fa-refresh, 15 | a.loading .fa-refresh { 16 | -webkit-animation: rotating 2s linear infinite; 17 | -moz-animation: rotating 2s linear infinite; 18 | -ms-animation: rotating 2s linear infinite; 19 | -o-animation: rotating 2s linear infinite; 20 | animation: rotating 2s linear infinite; 21 | } 22 | 23 | 24 | @-webkit-keyframes rotating /* Safari and Chrome */ { 25 | from { 26 | -webkit-transform: rotate(0deg); 27 | -o-transform: rotate(0deg); 28 | transform: rotate(0deg); 29 | } 30 | to { 31 | -webkit-transform: rotate(360deg); 32 | -o-transform: rotate(360deg); 33 | transform: rotate(360deg); 34 | } 35 | } 36 | @keyframes rotating { 37 | from { 38 | -ms-transform: rotate(0deg); 39 | -moz-transform: rotate(0deg); 40 | -webkit-transform: rotate(0deg); 41 | -o-transform: rotate(0deg); 42 | transform: rotate(0deg); 43 | } 44 | to { 45 | -ms-transform: rotate(360deg); 46 | -moz-transform: rotate(360deg); 47 | -webkit-transform: rotate(360deg); 48 | -o-transform: rotate(360deg); 49 | transform: rotate(360deg); 50 | } 51 | } 52 | .rotating { 53 | -webkit-animation: rotating 2s linear infinite; 54 | -moz-animation: rotating 2s linear infinite; 55 | -ms-animation: rotating 2s linear infinite; 56 | -o-animation: rotating 2s linear infinite; 57 | animation: rotating 2s linear infinite; 58 | } 59 | 60 | .btn-toolbar .btn.btn-project-manager-update { 61 | margin-bottom: 20px; 62 | } 63 | 64 | .project-manager-server--redaxo-favicon { 65 | height: 15px; 66 | margin-top: -3px; 67 | } 68 | 69 | .btn.btn-project-manager-update-single, 70 | .btn.btn-project-manager-update-single:active, 71 | .btn.btn-project-manager-update-single:focus { 72 | padding: 0; 73 | border: none; 74 | background: transparent; 75 | box-shadow: none; 76 | outline: none; 77 | color: #4b9ad9; 78 | } 79 | 80 | 81 | body.rex-theme-dark .tablesorter-default th, 82 | body.rex-theme-dark .tablesorter-default td { 83 | background-color: #202b35; 84 | border-bottom: 1px solid #151c22; 85 | } 86 | 87 | @media(prefers-color-scheme: dark) { 88 | .tablesorter-default th, 89 | .tablesorter-default td { 90 | background-color: #202b35; 91 | border-bottom: 1px solid #151c22; 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /plugins/server/assets/css/theme.default.min.css: -------------------------------------------------------------------------------- 1 | .tablesorter-default{width:100%;background-color:#fff;border-spacing:0;margin:10px 0 15px;text-align:left}.tablesorter-default th,.tablesorter-default thead td{background-color:#fff;border-collapse:collapse;border-bottom:#ccc 2px solid;padding:0}.tablesorter-default tfoot td,.tablesorter-default tfoot th{border:0}.tablesorter-default .header,.tablesorter-default .tablesorter-header{background-image:url(data:image/gif;base64,R0lGODlhFQAJAIAAACMtMP///yH5BAEAAAEALAAAAAAVAAkAAAIXjI+AywnaYnhUMoqt3gZXPmVg94yJVQAAOw==);background-position:center right;background-repeat:no-repeat;cursor:pointer;white-space:normal;padding:4px 20px 4px 4px}.tablesorter-default thead .headerSortUp,.tablesorter-default thead .tablesorter-headerAsc,.tablesorter-default thead .tablesorter-headerSortUp{background-image:url(data:image/gif;base64,R0lGODlhFQAEAIAAACMtMP///yH5BAEAAAEALAAAAAAVAAQAAAINjI8Bya2wnINUMopZAQA7);border-bottom:#000 2px solid}.tablesorter-default thead .headerSortDown,.tablesorter-default thead .tablesorter-headerDesc,.tablesorter-default thead .tablesorter-headerSortDown{background-image:url(data:image/gif;base64,R0lGODlhFQAEAIAAACMtMP///yH5BAEAAAEALAAAAAAVAAQAAAINjB+gC+jP2ptn0WskLQA7);border-bottom:#000 2px solid}.tablesorter-default thead .sorter-false{background-image:none;cursor:default;padding:4px}.tablesorter-default tfoot .tablesorter-headerAsc,.tablesorter-default tfoot .tablesorter-headerDesc,.tablesorter-default tfoot .tablesorter-headerSortDown,.tablesorter-default tfoot .tablesorter-headerSortUp{border-top:#000 2px solid}.tablesorter-default td{background-color:#fff;border-bottom:#ccc 1px solid;padding:4px;vertical-align:top}.tablesorter-default tbody>tr.even:hover>td,.tablesorter-default tbody>tr.hover>td,.tablesorter-default tbody>tr.odd:hover>td,.tablesorter-default tbody>tr:hover>td{background-color:#fff;color:#000}.tablesorter-default .tablesorter-processing{background-position:center center!important;background-repeat:no-repeat!important;background-image:url(data:image/gif;base64,R0lGODlhFAAUAKEAAO7u7lpaWgAAAAAAACH/C05FVFNDQVBFMi4wAwEAAAAh+QQBCgACACwAAAAAFAAUAAACQZRvoIDtu1wLQUAlqKTVxqwhXIiBnDg6Y4eyx4lKW5XK7wrLeK3vbq8J2W4T4e1nMhpWrZCTt3xKZ8kgsggdJmUFACH5BAEKAAIALAcAAAALAAcAAAIUVB6ii7jajgCAuUmtovxtXnmdUAAAIfkEAQoAAgAsDQACAAcACwAAAhRUIpmHy/3gUVQAQO9NetuugCFWAAAh+QQBCgACACwNAAcABwALAAACE5QVcZjKbVo6ck2AF95m5/6BSwEAIfkEAQoAAgAsBwANAAsABwAAAhOUH3kr6QaAcSrGWe1VQl+mMUIBACH5BAEKAAIALAIADQALAAcAAAIUlICmh7ncTAgqijkruDiv7n2YUAAAIfkEAQoAAgAsAAAHAAcACwAAAhQUIGmHyedehIoqFXLKfPOAaZdWAAAh+QQFCgACACwAAAIABwALAAACFJQFcJiXb15zLYRl7cla8OtlGGgUADs=)!important}.tablesorter-default tr.odd>td{background-color:#dfdfdf}.tablesorter-default tr.even>td{background-color:#efefef}.tablesorter-default tr.odd td.primary{background-color:#bfbfbf}.tablesorter-default td.primary,.tablesorter-default tr.even td.primary{background-color:#d9d9d9}.tablesorter-default tr.odd td.secondary{background-color:#d9d9d9}.tablesorter-default td.secondary,.tablesorter-default tr.even td.secondary{background-color:#e6e6e6}.tablesorter-default tr.odd td.tertiary{background-color:#e6e6e6}.tablesorter-default td.tertiary,.tablesorter-default tr.even td.tertiary{background-color:#f2f2f2}.tablesorter-default>caption{background-color:#fff}.tablesorter-default .tablesorter-filter-row{background-color:#eee}.tablesorter-default .tablesorter-filter-row td{background-color:#eee;border-bottom:#ccc 1px solid;line-height:normal;text-align:center;-webkit-transition:line-height .1s ease;-moz-transition:line-height .1s ease;-o-transition:line-height .1s ease;transition:line-height .1s ease}.tablesorter-default .tablesorter-filter-row .disabled{opacity:.5;cursor:not-allowed}.tablesorter-default .tablesorter-filter-row.hideme td{padding:2px;margin:0;line-height:0;cursor:pointer}.tablesorter-default .tablesorter-filter-row.hideme *{height:1px;min-height:0;border:0;padding:0;margin:0;/* don't use visibility: hidden because it disables tabbing */opacity:0}.tablesorter-default input.tablesorter-filter,.tablesorter-default select.tablesorter-filter{width:95%;height:auto;margin:4px auto;padding:4px;background-color:#fff;border:1px solid #bbb;color:#333;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;-webkit-transition:height .1s ease;-moz-transition:height .1s ease;-o-transition:height .1s ease;transition:height .1s ease}.tablesorter .filtered{display:none}.tablesorter .tablesorter-errorRow td{text-align:center;cursor:pointer;background-color:#e6bf99} -------------------------------------------------------------------------------- /plugins/server/assets/favicon/favicon: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FriendsOfREDAXO/project_manager/29fc69f12ae609bc9d870e96caf4b6c9dbe9a462/plugins/server/assets/favicon/favicon -------------------------------------------------------------------------------- /plugins/server/assets/favicon/redaxo-favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FriendsOfREDAXO/project_manager/29fc69f12ae609bc9d870e96caf4b6c9dbe9a462/plugins/server/assets/favicon/redaxo-favicon.png -------------------------------------------------------------------------------- /plugins/server/assets/js/bootstrap-tagsinput.js: -------------------------------------------------------------------------------- 1 | (function ($) { 2 | "use strict"; 3 | 4 | var defaultOptions = { 5 | tagClass: function(item) { 6 | return 'label label-info'; 7 | }, 8 | focusClass: 'focus', 9 | itemValue: function(item) { 10 | return item ? item.toString() : item; 11 | }, 12 | itemText: function(item) { 13 | return this.itemValue(item); 14 | }, 15 | itemTitle: function(item) { 16 | return null; 17 | }, 18 | freeInput: true, 19 | addOnBlur: true, 20 | maxTags: undefined, 21 | maxChars: undefined, 22 | confirmKeys: [13, 44], 23 | delimiter: ',', 24 | delimiterRegex: null, 25 | cancelConfirmKeysOnEmpty: false, 26 | onTagExists: function(item, $tag) { 27 | $tag.hide().fadeIn(); 28 | }, 29 | trimValue: false, 30 | allowDuplicates: false, 31 | triggerChange: true 32 | }; 33 | 34 | /** 35 | * Constructor function 36 | */ 37 | function TagsInput(element, options) { 38 | this.isInit = true; 39 | this.itemsArray = []; 40 | 41 | this.$element = $(element); 42 | this.$element.hide(); 43 | 44 | this.isSelect = (element.tagName === 'SELECT'); 45 | this.multiple = (this.isSelect && element.hasAttribute('multiple')); 46 | this.objectItems = options && options.itemValue; 47 | this.placeholderText = element.hasAttribute('placeholder') ? this.$element.attr('placeholder') : ''; 48 | this.inputSize = Math.max(1, this.placeholderText.length); 49 | 50 | this.$container = $('
'); 51 | this.$input = $('').appendTo(this.$container); 52 | 53 | this.$element.before(this.$container); 54 | 55 | this.build(options); 56 | this.isInit = false; 57 | } 58 | 59 | TagsInput.prototype = { 60 | constructor: TagsInput, 61 | 62 | /** 63 | * Adds the given item as a new tag. Pass true to dontPushVal to prevent 64 | * updating the elements val() 65 | */ 66 | add: function(item, dontPushVal, options) { 67 | var self = this; 68 | 69 | if (self.options.maxTags && self.itemsArray.length >= self.options.maxTags) 70 | return; 71 | 72 | // Ignore falsey values, except false 73 | if (item !== false && !item) 74 | return; 75 | 76 | // Trim value 77 | if (typeof item === "string" && self.options.trimValue) { 78 | item = $.trim(item); 79 | } 80 | 81 | // Throw an error when trying to add an object while the itemValue option was not set 82 | if (typeof item === "object" && !self.objectItems) 83 | throw("Can't add objects when itemValue option is not set"); 84 | 85 | // Ignore strings only containg whitespace 86 | if (item.toString().match(/^\s*$/)) 87 | return; 88 | 89 | // If SELECT but not multiple, remove current tag 90 | if (self.isSelect && !self.multiple && self.itemsArray.length > 0) 91 | self.remove(self.itemsArray[0]); 92 | 93 | if (typeof item === "string" && this.$element[0].tagName === 'INPUT') { 94 | var delimiter = (self.options.delimiterRegex) ? self.options.delimiterRegex : self.options.delimiter; 95 | var items = item.split(delimiter); 96 | if (items.length > 1) { 97 | for (var i = 0; i < items.length; i++) { 98 | this.add(items[i], true); 99 | } 100 | 101 | if (!dontPushVal) 102 | self.pushVal(self.options.triggerChange); 103 | return; 104 | } 105 | } 106 | 107 | var itemValue = self.options.itemValue(item), 108 | itemText = self.options.itemText(item), 109 | tagClass = self.options.tagClass(item), 110 | itemTitle = self.options.itemTitle(item); 111 | 112 | // Ignore items allready added 113 | var existing = $.grep(self.itemsArray, function(item) { return self.options.itemValue(item) === itemValue; } )[0]; 114 | if (existing && !self.options.allowDuplicates) { 115 | // Invoke onTagExists 116 | if (self.options.onTagExists) { 117 | var $existingTag = $(".tag", self.$container).filter(function() { return $(this).data("item") === existing; }); 118 | self.options.onTagExists(item, $existingTag); 119 | } 120 | return; 121 | } 122 | 123 | // if length greater than limit 124 | if (self.items().toString().length + item.length + 1 > self.options.maxInputLength) 125 | return; 126 | 127 | // raise beforeItemAdd arg 128 | var beforeItemAddEvent = $.Event('beforeItemAdd', { item: item, cancel: false, options: options}); 129 | self.$element.trigger(beforeItemAddEvent); 130 | if (beforeItemAddEvent.cancel) 131 | return; 132 | 133 | // register item in internal array and map 134 | self.itemsArray.push(item); 135 | 136 | // add a tag element 137 | 138 | var $tag = $('' + htmlEncode(itemText) + ''); 139 | $tag.data('item', item); 140 | self.findInputWrapper().before($tag); 141 | $tag.after(' '); 142 | 143 | // Check to see if the tag exists in its raw or uri-encoded form 144 | var optionExists = ( 145 | $('option[value="' + encodeURIComponent(itemValue) + '"]', self.$element).length || 146 | $('option[value="' + htmlEncode(itemValue) + '"]', self.$element).length 147 | ); 148 | 149 | // add