]> git.mxchange.org Git - friendica.git/blob - src/Module/Admin/Federation.php
The federation statistics now contain all systems
[friendica.git] / src / Module / Admin / Federation.php
1 <?php
2
3 namespace Friendica\Module\Admin;
4
5 use Friendica\Core\Config;
6 use Friendica\Core\L10n;
7 use Friendica\Core\Renderer;
8 use Friendica\Database\DBA;
9 use Friendica\Module\BaseAdminModule;
10
11 class Federation extends BaseAdminModule
12 {
13         public static function content(array $parameters = [])
14         {
15                 parent::content($parameters);
16
17                 // get counts on active friendica, diaspora, redmatrix, hubzilla, gnu
18                 // social and statusnet nodes this node is knowing
19                 //
20                 // We are looking for the following platforms in the DB, "Red" should find
21                 // all variants of that platform ID string as the q() function is stripping
22                 // off one % two of them are needed in the query
23                 // Add more platforms if you like, when one returns 0 known nodes it is not
24                 // displayed on the stats page.
25                 $systems = [
26                         'Friendica'   => ['name' => 'Friendica', 'color' => '#ffc018'], // orange from the logo
27                         'diaspora'    => ['name' => 'Diaspora', 'color' => '#a1a1a1'], // logo is black and white, makes a gray
28                         'red'         => ['name' => 'Red Matrix', 'color' => '#c50001'], // fire red from the logo
29                         'hubzilla'    => ['name' => 'Hubzilla', 'color' => '#43488a'], // blue from the logo
30                         'gnusocial'   => ['name' => 'GNU Social', 'color' => '#a22430'], // dark red from the logo
31                         'statusnet'   => ['name' => 'StatusNet', 'color' => '#789240'], // the green from the logo (red and blue have already others
32                         'mastodon'    => ['name' => 'Mastodon', 'color' => '#1a9df9'], // blue from the Mastodon logo
33                         'pleroma'     => ['name' => 'Pleroma', 'color' => '#E46F0F'], // Orange from the text that is used on Pleroma instances
34                         'socialhome'  => ['name' => 'SocialHome', 'color' => '#52056b'], // lilac from the Django Image used at the Socialhome homepage
35                         'wordpress'   => ['name' => 'WordPress', 'color' => '#016087'], // Background color of the homepage
36                         'misskey'     => ['name' => 'Misskey', 'color' => '#ccfefd'], // Font color of the homepage
37                         'funkwhale'   => ['name' => 'Funkwhale', 'color' => '#4082B4'], // From the homepage
38                         'plume'       => ['name' => 'Plume', 'color' => '#7765e3'], // From the homepage
39                         'pixelfed'    => ['name' => 'Pixelfed', 'color' => '#11da47'], // One of the logo colors
40                         'peertube'    => ['name' => 'Peertube', 'color' => '#ffad5c'], // One of the logo colors
41                         'writefreely' => ['name' => 'WriteFreely', 'color' => '#292929'], // Font color of the homepage
42                         'other'       => ['name' => L10n::t('Other'), 'color' => '#F1007E'], // ActivityPub main color
43                 ];
44
45                 $platforms = array_keys($systems);
46
47                 $counts = [];
48                 $total = 0;
49                 $users = 0;
50
51                 $gservers = DBA::p("SELECT COUNT(*) AS `total`, SUM(`registered-users`) AS `users`, `platform`,
52                         ANY_VALUE(`network`) AS `network`, MAX(`version`) AS `version`
53                         FROM `gserver` WHERE `last_contact` >= `last_failure` GROUP BY `platform`");
54                 while ($gserver = DBA::fetch($gservers)) {
55                         $total += $gserver['total'];
56                         $users += $gserver['users'];
57
58                         $versionCounts = [];
59                         $versions = DBA::p("SELECT COUNT(*) AS `total`, `version` FROM `gserver`
60                                 WHERE `last_contact` >= `last_failure` AND `platform` = ?
61                                 GROUP BY `version` ORDER BY `version`", $gserver['platform']);
62                         while ($version = DBA::fetch($versions)) {
63                                 $version['version'] = str_replace(["\n", "\r", "\t"], " ", $version['version']);
64                                 $versionCounts[] = $version;
65                         }
66                         DBA::close($versions);
67
68                         $platform = $gserver['platform'];
69
70                         if ($platform == 'Friendika') {
71                                 $platform = 'Friendica';
72                         } elseif (in_array($platform, ['Red Matrix', 'redmatrix'])) {
73                                 $platform = 'red';
74                         } elseif(stristr($platform, 'pleroma')) {
75                                 $platform = 'pleroma';
76                         } elseif(stristr($platform, 'wordpress')) {
77                                 $platform = 'wordpress';
78                         } elseif (!in_array($platform, $platforms)) {
79                                 $platform = 'other';
80                         }
81
82                         if ($platform != $gserver['platform']) {
83                                 if ($platform == 'other') {
84                                         $versionCounts = $counts[$platform][1] ?? [];
85                                         $versionCounts[] = ['version' => $gserver['platform'] ?: L10n::t('unknown'), 'total' => $gserver['total']];
86                                         $gserver['version'] = '';
87                                 } else {
88                                         $versionCounts = array_merge($versionCounts, $counts[$platform][1] ?? []);
89                                 }
90
91                                 $gserver['platform'] = $platform;
92                                 $gserver['total'] += $counts[$platform][0]['total'] ?? 0;
93                                 $gserver['users'] += $counts[$platform][0]['users'] ?? 0;
94                         }
95
96                         if ($platform == 'Friendica') {
97                                 $versionCounts = self::reformaFriendicaVersions($versionCounts);
98                         } elseif ($platform == 'pleroma') {
99                                 $versionCounts = self::reformaPleromaVersions($versionCounts);
100                         } elseif ($platform == 'diaspora') {
101                                 $versionCounts = self::reformaDiasporaVersions($versionCounts);
102                         }
103
104                         $versionCounts = self::sortVersion($versionCounts);
105
106                         $gserver['platform'] = $systems[$platform]['name'];
107
108                         $counts[$platform] = [$gserver, $versionCounts, str_replace([' ', '%'], '', $platform), $systems[$platform]['color']];
109                 }
110                 DBA::close($gserver);
111
112                 // some helpful text
113                 $intro = L10n::t('This page offers you some numbers to the known part of the federated social network your Friendica node is part of. These numbers are not complete but only reflect the part of the network your node is aware of.');
114                 $hint = L10n::t('The <em>Auto Discovered Contact Directory</em> feature is not enabled, it will improve the data displayed here.');
115
116                 // load the template, replace the macros and return the page content
117                 $t = Renderer::getMarkupTemplate('admin/federation.tpl');
118                 return Renderer::replaceMacros($t, [
119                         '$title' => L10n::t('Administration'),
120                         '$page' => L10n::t('Federation Statistics'),
121                         '$intro' => $intro,
122                         '$hint' => $hint,
123                         '$autoactive' => Config::get('system', 'poco_completion'),
124                         '$counts' => $counts,
125                         '$version' => FRIENDICA_VERSION,
126                         '$legendtext' => L10n::t('Currently this node is aware of %d nodes with %d registered users from the following platforms:', $total, $users),
127                 ]);
128         }
129
130         // early friendica versions have the format x.x.xxxx where xxxx is the
131         // DB version stamp; those should be operated out and versions be
132         // conbined
133         private static function reformaFriendicaVersions($versionCounts)
134         {
135                 $newV = [];
136                 $newVv = [];
137                 foreach ($versionCounts as $vv) {
138                         $newVC = $vv['total'];
139                         $newVV = $vv['version'];
140                         $lastDot = strrpos($newVV, '.');
141                         $len = strlen($newVV) - 1;
142                         if (($lastDot == $len - 4) && (!strrpos($newVV, '-rc') == $len - 3)) {
143                                 $newVV = substr($newVV, 0, $lastDot);
144                         }
145                         if (isset($newV[$newVV])) {
146                                 $newV[$newVV] += $newVC;
147                         } else {
148                                 $newV[$newVV] = $newVC;
149                         }
150                 }
151                 foreach ($newV as $key => $value) {
152                         array_push($newVv, ['total' => $value, 'version' => $key]);
153                 }
154                 $versionCounts = $newVv;
155
156                 return $versionCounts;
157         }
158
159         // in the DB the Diaspora versions have the format x.x.x.x-xx the last
160         // part (-xx) should be removed to clean up the versions from the "head
161         // commit" information and combined into a single entry for x.x.x.x
162         private static function reformaDiasporaVersions($versionCounts)
163         {
164                 $newV = [];
165                 $newVv = [];
166                 foreach ($versionCounts as $vv) {
167                         $newVC = $vv['total'];
168                         $newVV = $vv['version'];
169                         $posDash = strpos($newVV, '-');
170                         if ($posDash) {
171                                 $newVV = substr($newVV, 0, $posDash);
172                         }
173                         if (isset($newV[$newVV])) {
174                                 $newV[$newVV] += $newVC;
175                         } else {
176                                 $newV[$newVV] = $newVC;
177                         }
178                 }
179                 foreach ($newV as $key => $value) {
180                         array_push($newVv, ['total' => $value, 'version' => $key]);
181                 }
182                 $versionCounts = $newVv;
183
184                 return $versionCounts;
185         }
186
187         private static function reformaPleromaVersions($versionCounts)
188         {
189                 $compacted = [];
190                 foreach ($versionCounts as $key => $value) {
191                         $version = $versionCounts[$key]['version'];
192                         $parts = explode(' ', trim($version));
193                         do {
194                                 $part = array_pop($parts);
195                         } while (!empty($parts) && ((strlen($part) >= 40) || (strlen($part) <= 3)));
196                         // only take the x.x.x part of the version, not the "release" after the dash
197                         if (!empty($part) && strpos($part, '-')) {
198                                 $part = explode('-', $part)[0];
199                         }
200                         if (!empty($part)) {
201                                 if (empty($compacted[$part])) {
202                                         $compacted[$part] = $versionCounts[$key]['total'];
203                                 } else {
204                                         $compacted[$part] += $versionCounts[$key]['total'];
205                                 }
206                         }
207                 }
208
209                 $versionCounts = [];
210                 foreach ($compacted as $version => $pl_total) {
211                         $versionCounts[] = ['version' => $version, 'total' => $pl_total];
212                 }
213
214                 return $versionCounts;
215         }
216
217         // Reformat and compact version numbers
218         private static function sortVersion($versionCounts)
219         {
220                 //
221                 // clean up version numbers
222                 //
223                 // some platforms do not provide version information, add a unkown there
224                 // to the version string for the displayed list.
225                 foreach ($versionCounts as $key => $value) {
226                         if ($versionCounts[$key]['version'] == '') {
227                                 $versionCounts[$key] = ['total' => $versionCounts[$key]['total'], 'version' => L10n::t('unknown')];
228                         }
229                 }
230
231                 // Assure that the versions are sorted correctly
232                 $v2 = [];
233                 $versions = [];
234                 foreach ($versionCounts as $vv) {
235                         $version = trim(strip_tags($vv["version"]));
236                         $v2[$version] = $vv;
237                         $versions[] = $version;
238                 }
239
240                 usort($versions, 'version_compare');
241
242                 $versionCounts = [];
243                 foreach ($versions as $version) {
244                         $versionCounts[] = $v2[$version];
245                 }
246
247                 return $versionCounts;
248         }
249 }