From 0136219ca35fec22ead0564af8eb8d117316eee8 Mon Sep 17 00:00:00 2001 From: Hypolite Petovan Date: Mon, 10 Jan 2022 02:17:26 -0500 Subject: [PATCH] WIP Server detail page --- src/classes/Controllers/Web/Search.php | 6 -- src/classes/Controllers/Web/Server.php | 63 +++++++++++++ src/classes/Controllers/Web/Servers.php | 45 ++-------- src/classes/Models/Server.php | 95 ++++++++++++++++++++ src/classes/Models/SiteScrape.php | 29 ++++++ src/classes/Routes/Web/Search.php | 1 - src/classes/Routes/Web/Server.php | 22 +++++ src/classes/Routes/Web/Servers.php | 1 + src/classes/Views/PhpRenderer.php | 13 ++- src/dependencies.php | 11 ++- src/routes.php | 28 +++--- src/sql/migrations/up/0009.sql | 0 src/templates/server.phtml | 112 ++++++++++++++++++++++++ src/templates/sub/server.phtml | 2 +- 14 files changed, 366 insertions(+), 62 deletions(-) create mode 100644 src/classes/Controllers/Web/Server.php create mode 100644 src/classes/Models/SiteScrape.php create mode 100644 src/classes/Routes/Web/Server.php create mode 100644 src/sql/migrations/up/0009.sql create mode 100644 src/templates/server.phtml diff --git a/src/classes/Controllers/Web/Search.php b/src/classes/Controllers/Web/Search.php index d70925a..1455dfb 100644 --- a/src/classes/Controllers/Web/Search.php +++ b/src/classes/Controllers/Web/Search.php @@ -9,10 +9,6 @@ use \Friendica\Directory\Content\Pager; */ class Search extends BaseController { - /** - * @var \Atlas\Pdo\Connection - */ - private $atlas; /** * @var \Friendica\Directory\Models\Profile */ @@ -31,14 +27,12 @@ class Search extends BaseController private $l10n; public function __construct( - \Atlas\Pdo\Connection $atlas, \Friendica\Directory\Models\Profile $profileModel, \Friendica\Directory\Views\Widget\AccountTypeTabs $accountTypeTabs, \Friendica\Directory\Views\PhpRenderer $renderer, \Gettext\TranslatorInterface $l10n ) { - $this->atlas = $atlas; $this->profileModel = $profileModel; $this->accountTypeTabs = $accountTypeTabs; $this->renderer = $renderer; diff --git a/src/classes/Controllers/Web/Server.php b/src/classes/Controllers/Web/Server.php new file mode 100644 index 0000000..4f16e14 --- /dev/null +++ b/src/classes/Controllers/Web/Server.php @@ -0,0 +1,63 @@ +serverModel = $serverModel; + $this->siteScrapeModel = $siteScrapeModel; + $this->renderer = $renderer; + $this->l10n = $l10n; + $this->simplecache = $simplecache; + } + + function render(\Slim\Http\Request $request, \Slim\Http\Response $response, array $args): array + { + $server = $this->serverModel->getByHashId($args['hashid']); + + if (empty($server) || !$server['available'] || $server['hidden']) { + throw new NotFoundException($request, $response); + } + + $stable_version = $this->simplecache->get('stable_version'); + if (!$stable_version) { + $stable_version = trim(file_get_contents('https://git.friendi.ca/friendica/friendica/raw/branch/stable/VERSION')); + $this->simplecache->set('stable_version', $stable_version); + } + + $dev_version = $this->simplecache->get('dev_version'); + if (!$dev_version) { + $dev_version = trim(file_get_contents('https://git.friendi.ca/friendica/friendica/raw/branch/develop/VERSION')); + $this->simplecache->set('dev_version', $dev_version); + } + + $rc_version = str_replace('-dev', '-rc', $dev_version); + + $vars = [ + 'server' => $server, + 'stable_version' => $stable_version, + 'dev_version' => $dev_version, + 'rc_version' => $rc_version, + ]; + + $content = $this->renderer->fetch('server.phtml', $vars); + + // Render index view + return ['content' => $content]; + } +} diff --git a/src/classes/Controllers/Web/Servers.php b/src/classes/Controllers/Web/Servers.php index a4c1d78..0459efc 100644 --- a/src/classes/Controllers/Web/Servers.php +++ b/src/classes/Controllers/Web/Servers.php @@ -29,9 +29,13 @@ class Servers extends BaseController * @var \Psr\SimpleCache\CacheInterface */ private $simplecache; + /** + * @var \Friendica\Directory\Models\Server + */ + private $serverModel; public function __construct( - \Atlas\Pdo\Connection $atlas, + \Atlas\Pdo\Connection $atlas, \Friendica\Directory\Models\Server $serverModel, \Friendica\Directory\Views\PhpRenderer $renderer, \Gettext\TranslatorInterface $l10n, \Psr\SimpleCache\CacheInterface $simplecache @@ -41,6 +45,7 @@ class Servers extends BaseController $this->renderer = $renderer; $this->l10n = $l10n; $this->simplecache = $simplecache; + $this->serverModel = $serverModel; } public function render(Request $request, Response $response, array $args): array @@ -63,43 +68,9 @@ class Servers extends BaseController $pager = new Pager($this->l10n, $request, 20); - $sql_where = ''; - $values = []; + $servers = $this->serverModel->listPageForDirectory($pager->getStart(), $pager->getItemsPerPage(), $args['language'] ?? ''); - if ($args['language']) { - $sql_where .= ' -AND LEFT(`language`, 2) = LEFT(:language, 2)'; - $values['language'] = $args['language']; - } - - $stmt = 'SELECT * -FROM `server` s -WHERE `reg_policy` != "REGISTER_CLOSED" -AND `available` -AND NOT `hidden` -' . $sql_where . ' -ORDER BY `health_score` DESC, `ssl_state` DESC, `info` != "" DESC, `last_seen` DESC -LIMIT :start, :limit'; - $listValues = array_merge($values, [ - 'start' => [$pager->getStart(), PDO::PARAM_INT], - 'limit' => [$pager->getItemsPerPage(), PDO::PARAM_INT] - ]); - $servers = $this->atlas->fetchAll($stmt, $listValues); - - foreach ($servers as $key => $server) { - $servers[$key]['user_count'] = $this->atlas->fetchValue( - 'SELECT COUNT(*) FROM `profile` WHERE `available` AND NOT `hidden` AND `server_id` = :server_id', - ['server_id' => [$server['id'], PDO::PARAM_INT]] - ); - } - - $stmt = 'SELECT COUNT(*) -FROM `server` s -WHERE `reg_policy` != "REGISTER_CLOSED" -AND `available` -AND NOT `hidden` -' . $sql_where; - $count = $this->atlas->fetchValue($stmt, $values); + $count = $this->serverModel->countForDirectory($args['language'] ?? ''); $vars = [ 'title' => $this->l10n->gettext('Public Servers'), diff --git a/src/classes/Models/Server.php b/src/classes/Models/Server.php index 9f1ec5c..5fc925b 100644 --- a/src/classes/Models/Server.php +++ b/src/classes/Models/Server.php @@ -2,11 +2,105 @@ namespace Friendica\Directory\Models; +use Hashids\Hashids; +use PDO; + /** * @author Hypolite Petovan */ class Server extends \Friendica\Directory\Model { + /** @var Hashids */ + private $hashids; + + public function __construct(\Atlas\Pdo\Connection $atlas, Hashids $hashids) + { + parent::__construct($atlas); + + $this->hashids = $hashids; + } + + /** + * @param int $start + * @param int $limit + * @param string|null $language + * @return array + */ + public function listPageForDirectory(int $start = 0, int $limit = 50, string $language = null): array + { + $sql_where = ''; + $values = []; + + if ($language) { + $sql_where .= ' +AND LEFT(`language`, 2) = LEFT(:language, 2)'; + $values['language'] = $language; + } + + $stmt = 'SELECT * +FROM `server` s +WHERE `reg_policy` != "REGISTER_CLOSED" +AND `available` +AND NOT `hidden` +' . $sql_where . ' +ORDER BY `health_score` DESC, `ssl_state` DESC, `info` != "" DESC, `last_seen` DESC +LIMIT :start, :limit'; + $listValues = array_merge($values, [ + 'start' => [$start, PDO::PARAM_INT], + 'limit' => [$limit, PDO::PARAM_INT] + ]); + $servers = $this->atlas->fetchAll($stmt, $listValues); + + array_walk($servers, function (&$server) { + $server['hashid'] = $this->hashids->encode($server['id']); + $server['user_count'] = $this->atlas->fetchValue( + 'SELECT COUNT(*) FROM `profile` WHERE `available` AND NOT `hidden` AND `server_id` = :server_id', + ['server_id' => [$server['id'], PDO::PARAM_INT]] + ); + }); + + return $servers; + } + + /** + * @param null $language + * @return int + */ + public function countForDirectory($language = null): int + { + $sql_where = ''; + $values = []; + + if ($language) { + $sql_where .= ' +AND LEFT(`language`, 2) = LEFT(:language, 2)'; + $values['language'] = $language; + } + + $stmt = 'SELECT COUNT(*) +FROM `server` s +WHERE `reg_policy` != "REGISTER_CLOSED" +AND `available` +AND NOT `hidden` +' . $sql_where; + return $this->atlas->fetchValue($stmt, $values); + } + + /** + * @param string $hashid + * @return array + */ + public function getByHashId(string $hashid): array + { + $serverId = $this->hashids->decode($hashid)[0]; + + $server = $this->atlas->fetchOne('SELECT * FROM `server` WHERE `id` = :id', + ['id' => $serverId] + ); + + return $server; + } + /** * @param string $server_url * @return array|null @@ -23,6 +117,7 @@ class Server extends \Friendica\Directory\Model } /** + * @param int $server_id * @param string $server_url */ public function addAliasToServer(int $server_id, string $server_url): void diff --git a/src/classes/Models/SiteScrape.php b/src/classes/Models/SiteScrape.php new file mode 100644 index 0000000..027bdb8 --- /dev/null +++ b/src/classes/Models/SiteScrape.php @@ -0,0 +1,29 @@ + + */ +class SiteScrape extends \Friendica\Directory\Model +{ + /** + * @param int $serverId + * @return array + */ + public function listByServerIdy(int $serverId): array + { + $stmt = 'SELECT * +FROM `site_scrape` +WHERE `server_id` = :serverId'; + $values = [ + 'serverId' => $serverId, + ]; + $siteScrapes = $this->atlas->fetchAll($stmt, $values); + + return $siteScrapes; + } +} diff --git a/src/classes/Routes/Web/Search.php b/src/classes/Routes/Web/Search.php index d758053..2c65ece 100644 --- a/src/classes/Routes/Web/Search.php +++ b/src/classes/Routes/Web/Search.php @@ -12,7 +12,6 @@ class Search extends BaseRoute parent::__construct($container); $this->controller = new \Friendica\Directory\Controllers\Web\Search( - $this->container->atlas, $this->container->get(\Friendica\Directory\Models\Profile::class), $this->container->get(\Friendica\Directory\Views\Widget\AccountTypeTabs::class), $this->container->renderer, diff --git a/src/classes/Routes/Web/Server.php b/src/classes/Routes/Web/Server.php new file mode 100644 index 0000000..3e590c1 --- /dev/null +++ b/src/classes/Routes/Web/Server.php @@ -0,0 +1,22 @@ + + */ +class Server extends BaseRoute +{ + public function __construct(\Slim\Container $container) + { + parent::__construct($container); + + $this->controller = new \Friendica\Directory\Controllers\Web\Server( + $this->container->get(\Friendica\Directory\Models\Server::class), + $this->container->get(\Friendica\Directory\Models\SiteScrape::class), + $this->container->renderer, + $this->container->l10n, + $this->container->simplecache, + ); + } +} diff --git a/src/classes/Routes/Web/Servers.php b/src/classes/Routes/Web/Servers.php index 0f35f8e..fd5544c 100644 --- a/src/classes/Routes/Web/Servers.php +++ b/src/classes/Routes/Web/Servers.php @@ -13,6 +13,7 @@ class Servers extends BaseRoute $this->controller = new \Friendica\Directory\Controllers\Web\Servers( $this->container->atlas, + $this->container->get(\Friendica\Directory\Models\Server::class), $this->container->renderer, $this->container->l10n, $this->container->simplecache diff --git a/src/classes/Views/PhpRenderer.php b/src/classes/Views/PhpRenderer.php index 3df40ac..a04c7b7 100644 --- a/src/classes/Views/PhpRenderer.php +++ b/src/classes/Views/PhpRenderer.php @@ -27,7 +27,7 @@ use Slim\Router; class PhpRenderer extends \Slim\Views\PhpRenderer { /** - * @var \Zend\Escaper\Escaper + * @var \Laminas\Escaper\Escaper */ private $escaper; /** @@ -40,7 +40,7 @@ class PhpRenderer extends \Slim\Views\PhpRenderer private $router; public function __construct( - \Zend\Escaper\Escaper $escaper, + \Laminas\Escaper\Escaper $escaper, \Gettext\TranslatorInterface $l10n, Router $router, string $templatePath = "", @@ -188,12 +188,16 @@ class PhpRenderer extends \Slim\Views\PhpRenderer * @param array $queryParams * @return string */ - function r(string $name, array $data = [], array $queryParams = []) + function r(string $name, array $data = [], array $queryParams = []): string { if ($this->getAttribute('zrl')) { $queryParams['zrl'] = $this->getAttribute('zrl'); } + array_walk($data, function(&$value) { + $value = urlencode($value); + }); + return $this->router->pathFor($name, $data, $queryParams); } @@ -201,8 +205,9 @@ class PhpRenderer extends \Slim\Views\PhpRenderer * Add sitewide ZRL support for external URLs * * @param string $url + * @return string */ - function u(string $url) + function u(string $url): string { if ($this->getAttribute('zrl')) { $uri = new \ByJG\Util\Uri($url); diff --git a/src/dependencies.php b/src/dependencies.php index 162ace8..1f0f3aa 100644 --- a/src/dependencies.php +++ b/src/dependencies.php @@ -100,9 +100,14 @@ $container[\Friendica\Directory\Models\ProfilePollQueue::class] = function (Cont }; $container[\Friendica\Directory\Models\Server::class] = function (ContainerInterface $c): Friendica\Directory\Models\Server { - return new Friendica\Directory\Models\Server($c->get('atlas')); + return new Friendica\Directory\Models\Server($c->get('atlas'), $c->get('hashids')); }; +$container[\Friendica\Directory\Models\SiteScrape::class] = function (ContainerInterface $c): Friendica\Directory\Models\SiteScrape { + return new Friendica\Directory\Models\SiteScrape($c->get('atlas')); +}; + + $container[\Friendica\Directory\Pollers\Directory::class] = function (ContainerInterface $c): Friendica\Directory\Pollers\Directory { $settings = $c->get('settings')['poller']; return new Friendica\Directory\Pollers\Directory( @@ -143,3 +148,7 @@ $container[\Friendica\Directory\Views\Widget\AccountTypeTabs::class] = function $c->get('router') ); }; + +$container['hashids'] = function (ContainerInterface $c): \Hashids\Hashids { + return new \Hashids\Hashids($_SERVER['HTTP_HOST'], 5); +}; \ No newline at end of file diff --git a/src/routes.php b/src/routes.php index 9dc2010..62a9d23 100644 --- a/src/routes.php +++ b/src/routes.php @@ -1,5 +1,7 @@ get('/servers/surprise', \Friendica\Directory\Routes\Http\Surprise::class); -$app->get('/servers[/{language}]', \Friendica\Directory\Routes\Web\Servers::class)->setName('servers'); +$app->get('/servers/surprise', Routes\Http\Surprise::class); +$app->get('/servers[/{language}]', Routes\Web\Servers::class)->setName('servers'); $app->get('/search[/{account_type}]', function (Request $request, Response $response, $args) { if ($request->getAttribute('negotiation')->getMediaType() == 'application/json') { - $route = new \Friendica\Directory\Routes\Http\Search($this); + $route = new Routes\Http\Search($this); } else { - $route = new \Friendica\Directory\Routes\Web\Search($this); + $route = new Routes\Web\Search($this); } return $route($request, $response, $args); })->setName('search'); -$app->post('/msearch', \Friendica\Directory\Routes\Http\MatchSearch::class); +$app->post('/msearch', Routes\Http\MatchSearch::class); -$app->get('/stats', \Friendica\Directory\Routes\Web\Statistics::class)->setName('stats'); +$app->get('/stats', Routes\Web\Statistics::class)->setName('stats'); -$app->get('/submit', \Friendica\Directory\Routes\Http\Submit::class); +$app->get('/submit', Routes\Http\Submit::class); -$app->get('/photo/{profile_id:[0-9]+}.jpg', \Friendica\Directory\Routes\Http\Photo::class)->setName('photo'); +$app->get('/photo/{profile_id:[0-9]+}.jpg', Routes\Http\Photo::class)->setName('photo'); -$app->get('/sync/pull/all', \Friendica\Directory\Routes\Http\SyncPull::class); -$app->get('/sync/pull/since/{since}', \Friendica\Directory\Routes\Http\SyncPull::class); +$app->get('/sync/pull/all', Routes\Http\SyncPull::class); +$app->get('/sync/pull/since/{since}', Routes\Http\SyncPull::class); $app->get('/VERSION', function (Request $request, Response $response) { $response->getBody()->write(file_get_contents(__DIR__ . '/../VERSION')); @@ -42,10 +44,12 @@ $app->get('/VERSION', function (Request $request, Response $response) { foreach(glob(__DIR__ . '/../config/pages/*.html') as $page) { $app->get('/' . strtolower(basename($page, '.html')), function (Request $request, Response $response, $args) use ($page) { - $route = new \Friendica\Directory\Routes\Web\Pages($this, $page); + $route = new Routes\Web\Pages($this, $page); return $route($request, $response, $args); }); } -$app->get('/[{account_type}]', \Friendica\Directory\Routes\Web\Directory::class)->setName('directory'); +$app->get('/[{account_type}]', Routes\Web\Directory::class)->setName('directory'); + +$app->get('/server/{hashid}', Routes\Web\Server::class)->setName('server'); diff --git a/src/sql/migrations/up/0009.sql b/src/sql/migrations/up/0009.sql new file mode 100644 index 0000000..e69de29 diff --git a/src/templates/server.phtml b/src/templates/server.phtml new file mode 100644 index 0000000..b4f9e78 --- /dev/null +++ b/src/templates/server.phtml @@ -0,0 +1,112 @@ + + ' . $this->__('Stable Version') . ''; +} elseif ($server['version'] == $dev_version || $server['version'] == $rc_version) { + $version_badge = ' ' . $this->__('Develop Version') . ''; +} else { + $version_badge = ' ' . $this->__('Outdated Version') . ''; +} + +$base_url = $server['base_url']; + +$base_url_display = substr($base_url, strpos($base_url, '/') + 2); +?> +
+

e($server['name']) ?>

+ +
+ +

+ + HTTPS + + HTTP + + e($base_url_display); ?> +

+
+
+
__('Health Score')?>
+
+ + + +
+
+ + + +
+
__('Known Users')?>
+
+ + n__('%s User', '%s Users', $server['user_count'])?> + + __('None');?> + +
+
+
+
__('Registration Policy')?>
+
+ + + __('By Approval')?> + + + + __('Open')?> + + +
+
+
+
__('Friendica Version')?>
+
+ +
+
+ +
+
__('Administrator')?>
+
+ + e($server['admin_name']); ?> + +
+
+ +
+
__('Description')?>
+
+ + e($server['info']); ?> + + __('No description provided')?> + +
+
+
diff --git a/src/templates/sub/server.phtml b/src/templates/sub/server.phtml index f1cf79d..a0425a9 100644 --- a/src/templates/sub/server.phtml +++ b/src/templates/sub/server.phtml @@ -26,7 +26,7 @@ $base_url_display = substr($base_url, strpos($base_url, '/') + 2);
- e($server['name']); ?> + e($server['name']); ?>