3 namespace Friendica\Module\Admin;
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;
11 class Federation extends BaseAdminModule
13 public static function content()
17 // get counts on active friendica, diaspora, redmatrix, hubzilla, gnu
18 // social and statusnet nodes this node is knowing
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 $platforms = ['Friendi%%a', 'Diaspora', '%%red%%', 'Hubzilla', 'BlaBlaNet', 'GNU Social', 'StatusNet', 'Mastodon', 'Pleroma', 'socialhome', 'ganggo'];
27 'Friendi%%a' => '#ffc018', // orange from the logo
28 'Diaspora' => '#a1a1a1', // logo is black and white, makes a gray
29 '%%red%%' => '#c50001', // fire red from the logo
30 'Hubzilla' => '#43488a', // blue from the logo
31 'BlaBlaNet' => '#3B5998', // blue from the navbar at blablanet-dot-com
32 'GNU Social' => '#a22430', // dark red from the logo
33 'StatusNet' => '#789240', // the green from the logo (red and blue have already others
34 'Mastodon' => '#1a9df9', // blue from the Mastodon logo
35 'Pleroma' => '#E46F0F', // Orange from the text that is used on Pleroma instances
36 'socialhome' => '#52056b', // lilac from the Django Image used at the Socialhome homepage
37 'ganggo' => '#69d7e2', // from the favicon
43 foreach ($platforms as $platform) {
44 // get a total count for the platform, the name and version of the
45 // highest version and the protocol tpe
46 $platformCount = DBA::fetchFirst('SELECT
48 SUM(`registered-users`) AS `users`,
49 ANY_VALUE(`platform`) AS `platform`,
50 ANY_VALUE(`network`) AS `network`,
51 MAX(`version`) AS `version` FROM `gserver`
52 WHERE `platform` LIKE ?
53 AND `last_contact` >= `last_failure`
54 ORDER BY `version` ASC', $platform);
55 $total += $platformCount['total'];
56 $users += $platformCount['users'];
58 // what versions for that platform do we know at all?
59 // again only the active nodes
60 $versionCountsStmt = DBA::p('SELECT
62 `version` FROM `gserver`
63 WHERE `last_contact` >= `last_failure`
66 ORDER BY `version`;', $platform);
67 $versionCounts = DBA::toArray($versionCountsStmt);
70 // clean up version numbers
72 // some platforms do not provide version information, add a unkown there
73 // to the version string for the displayed list.
74 foreach ($versionCounts as $key => $value) {
75 if ($versionCounts[$key]['version'] == '') {
76 $versionCounts[$key] = ['total' => $versionCounts[$key]['total'], 'version' => L10n::t('unknown')];
80 // Reformat and compact version numbers
81 if ($platform == 'Pleroma') {
83 foreach ($versionCounts as $key => $value) {
84 $version = $versionCounts[$key]['version'];
85 $parts = explode(' ', trim($version));
87 $part = array_pop($parts);
88 } while (!empty($parts) && ((strlen($part) >= 40) || (strlen($part) <= 3)));
89 // only take the x.x.x part of the version, not the "release" after the dash
90 $part = array_shift(explode('-', $part));
92 if (empty($compacted[$part])) {
93 $compacted[$part] = $versionCounts[$key]['total'];
95 $compacted[$part] += $versionCounts[$key]['total'];
101 foreach ($compacted as $version => $pl_total) {
102 $versionCounts[] = ['version' => $version, 'total' => $pl_total];
106 // in the DB the Diaspora versions have the format x.x.x.x-xx the last
107 // part (-xx) should be removed to clean up the versions from the "head
108 // commit" information and combined into a single entry for x.x.x.x
109 if ($platform == 'Diaspora') {
112 foreach ($versionCounts as $vv) {
113 $newVC = $vv['total'];
114 $newVV = $vv['version'];
115 $posDash = strpos($newVV, '-');
117 $newVV = substr($newVV, 0, $posDash);
119 if (isset($newV[$newVV])) {
120 $newV[$newVV] += $newVC;
122 $newV[$newVV] = $newVC;
125 foreach ($newV as $key => $value) {
126 array_push($newVv, ['total' => $value, 'version' => $key]);
128 $versionCounts = $newVv;
131 // early friendica versions have the format x.x.xxxx where xxxx is the
132 // DB version stamp; those should be operated out and versions be
134 if ($platform == 'Friendi%%a') {
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);
145 if (isset($newV[$newVV])) {
146 $newV[$newVV] += $newVC;
148 $newV[$newVV] = $newVC;
151 foreach ($newV as $key => $value) {
152 array_push($newVv, ['total' => $value, 'version' => $key]);
154 $versionCounts = $newVv;
157 // Assure that the versions are sorted correctly
160 foreach ($versionCounts as $vv) {
161 $version = trim(strip_tags($vv["version"]));
163 $versions[] = $version;
166 usort($versions, 'version_compare');
169 foreach ($versions as $version) {
170 $versionCounts[] = $v2[$version];
173 // the 3rd array item is needed for the JavaScript graphs as JS does
174 // not like some characters in the names of variables...
175 $counts[$platform] = [$platformCount, $versionCounts, str_replace([' ', '%'], '', $platform), $colors[$platform]];
179 $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.');
180 $hint = L10n::t('The <em>Auto Discovered Contact Directory</em> feature is not enabled, it will improve the data displayed here.');
182 // load the template, replace the macros and return the page content
183 $t = Renderer::getMarkupTemplate('admin/federation.tpl');
184 return Renderer::replaceMacros($t, [
185 '$title' => L10n::t('Administration'),
186 '$page' => L10n::t('Federation Statistics'),
189 '$autoactive' => Config::get('system', 'poco_completion'),
190 '$counts' => $counts,
191 '$version' => FRIENDICA_VERSION,
192 '$legendtext' => L10n::t('Currently this node is aware of %d nodes with %d registered users from the following platforms:', $total, $users),