Skip to content

Commit

Permalink
feat: optionally display country flags for all users in post header (#42
Browse files Browse the repository at this point in the history
)

* feat: optional country flag display

* Apply fixes from StyleCI

* only apply flag when data is available

* use Intl.displaynames for country display

* only serialize country code on basic serializer

* has IP address when used as an ID in serializer

---------

Co-authored-by: StyleCI Bot <[email protected]>
  • Loading branch information
imorland and StyleCIBot authored Sep 9, 2024
1 parent ab64d25 commit 27a3615
Show file tree
Hide file tree
Showing 9 changed files with 129 additions and 31 deletions.
11 changes: 4 additions & 7 deletions extend.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@
use Flarum\Post\Post;
use Flarum\Settings\Event\Saving;
use FoF\GeoIP\Api\GeoIP;
use FoF\GeoIP\Api\Serializer\IPInfoSerializer;

return [
(new Extend\Frontend('forum'))
Expand All @@ -40,11 +39,7 @@
->listen(Saving::class, Listeners\RemoveErrorsOnSettingsUpdate::class),

(new Extend\ApiSerializer(PostSerializer::class))
->relationship('ip_info', function (PostSerializer $serializer, Post $model) {
if ($serializer->getActor()->can('viewIps', $model)) {
return $serializer->hasOne($model, IPInfoSerializer::class, 'ip_info');
}
}),
->relationship('ip_info', Api\AttachRelation::class),

(new Extend\ApiController(Controller\ListPostsController::class))
->addInclude('ip_info'),
Expand All @@ -62,7 +57,9 @@
->addInclude('posts.ip_info'),

(new Extend\Settings())
->default('fof-geoip.service', 'ipapi'),
->default('fof-geoip.service', 'ipapi')
->default('fof-geoip.showFlag', false)
->serializeToForum('fof-geoip.showFlag', 'fof-geoip.showFlag', 'boolval'),

(new Extend\Routes('api'))
->get('/ip_info/{ip}', 'fof-geoip.api.ip_info', Api\Controller\ShowIpInfoController::class),
Expand Down
6 changes: 6 additions & 0 deletions js/src/admin/components/ExtensionSettingsPage.js
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,12 @@ export default class GeoipSettingsPage extends ExtensionPage {
placeholder: 1500,
})
: []}
{this.buildSettingComponent({
setting: 'fof-geoip.showFlag',
type: 'boolean',
label: app.translator.trans('fof-geoip.admin.settings.show_flag_label'),
help: app.translator.trans('fof-geoip.admin.settings.show_flag_help'),
})}
{this.submitButton()}
</div>
</div>,
Expand Down
20 changes: 20 additions & 0 deletions js/src/forum/extenders/extendCommentPost.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import app from 'flarum/forum/app';
import { extend } from 'flarum/common/extend';
import ItemList from 'flarum/common/utils/ItemList';
import CommentPost from 'flarum/forum/components/CommentPost';
import type Mithril from 'mithril';
import { getIPData } from '../helpers/IPDataHelper';

export default function extendCommentPost() {
extend(CommentPost.prototype, 'headerItems', function (items: ItemList<Mithril.Children>) {
if (app.forum.attribute<boolean>('fof-geoip.showFlag')) {
const ipInfo = this.attrs.post.ip_info?.();
if (ipInfo) {
const { image } = getIPData(ipInfo);
if (image) {
items.add('country', image, 100);
}
}
}
});
}
16 changes: 13 additions & 3 deletions js/src/forum/helpers/IPDataHelper.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import app from 'flarum/forum/app';
import IPInfo from '../models/IPInfo';
import getFlagEmojiUrl from '../util/getFlagEmojiUrl';
import Tooltip from 'flarum/common/components/Tooltip';
Expand All @@ -11,12 +12,21 @@ export const getThreat = (ipInfo: IPInfo) => {
};

export const getFlagImage = (ipInfo: IPInfo) => {
if (ipInfo.countryCode() && ipInfo.countryCode().length > 1) {
if (ipInfo && ipInfo.countryCode() && ipInfo.countryCode().length > 1) {
const url = getFlagEmojiUrl(ipInfo.countryCode());

const currentLocale = app.translator.getLocale() as string;

// Create an instance of Intl.DisplayNames for displaying full country names
const displayNames = new Intl.DisplayNames([currentLocale], { type: 'region' });

// Get the full country name using the country code
const countryName = displayNames.of(ipInfo.countryCode());

if (url) {
return (
<Tooltip text={ipInfo.countryCode()}>
<img src={url} alt={ipInfo.countryCode()} height="16" loading="lazy" />
<Tooltip text={countryName}>
<img src={url} alt={countryName} height="16" loading="lazy" />
</Tooltip>
);
}
Expand Down
2 changes: 2 additions & 0 deletions js/src/forum/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,13 @@ import app from 'flarum/forum/app';
import extendPostMeta from './extenders/extendPostMeta';
import extendBanIPModal from './extenders/extendBanIPModal';
import extendAccessTokensList from './extenders/extendAccessTokensList';
import extendCommentPost from './extenders/extendCommentPost';

export { default as extend } from './extend';

app.initializers.add('fof/geoip', () => {
extendPostMeta();
extendBanIPModal();
extendAccessTokensList();
extendCommentPost();
});
3 changes: 3 additions & 0 deletions resources/locale/en.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@ fof-geoip:
access_key_label: Access Key
quota_label: Lookup quota

show_flag_label: Show country flag for each post
show_flag_help: Without disclosing the IP address, show the country flag of the IP address of the post author.

forum:
alerts:
ip_copied: Copied IP Address
Expand Down
28 changes: 28 additions & 0 deletions src/Api/AttachRelation.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<?php

/*
* This file is part of fof/geoip.
*
* Copyright (c) FriendsOfFlarum.
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace FoF\GeoIP\Api;

use Flarum\Api\Serializer\PostSerializer;
use Flarum\Post\Post;
use FoF\GeoIP\Api\Serializer\BasicIPInfoSerializer;
use FoF\GeoIP\Api\Serializer\IPInfoSerializer;
use Tobscure\JsonApi\Relationship;

class AttachRelation
{
public function __invoke(PostSerializer $serializer, Post $post): Relationship
{
$viewIPs = $serializer->getActor()->can('viewIps', $post);

return $serializer->hasOne($post, $viewIPs ? IPInfoSerializer::class : BasicIPInfoSerializer::class, 'ip_info');
}
}
49 changes: 49 additions & 0 deletions src/Api/Serializer/BasicIPInfoSerializer.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
<?php

/*
* This file is part of fof/geoip.
*
* Copyright (c) FriendsOfFlarum.
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace FoF\GeoIP\Api\Serializer;

use Flarum\Api\Serializer\AbstractSerializer;
use FoF\GeoIP\Model\IPInfo;
use InvalidArgumentException;

class BasicIPInfoSerializer extends AbstractSerializer
{
protected $type = 'ip_info';

/**
* @param IPInfo $ip
*
* @return array
*/
protected function getDefaultAttributes($ip): array
{
if (!($ip instanceof IPInfo)) {
throw new InvalidArgumentException(
get_class($this).' can only serialize instances of '.IPInfo::class
);
}

return [
'countryCode' => $ip->country_code,
];
}

/**
* @param IPInfo $model
*
* @return string
*/
public function getId($model)
{
return hash('sha256', $model->address);
}
}
25 changes: 4 additions & 21 deletions src/Api/Serializer/IPInfoSerializer.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,29 +11,20 @@

namespace FoF\GeoIP\Api\Serializer;

use Flarum\Api\Serializer\AbstractSerializer;
use FoF\GeoIP\Model\IPInfo;
use InvalidArgumentException;

class IPInfoSerializer extends AbstractSerializer
class IPInfoSerializer extends BasicIPInfoSerializer
{
protected $type = 'ip_info';

/**
* @param IPInfo $ip
*
* @return array
*/
protected function getDefaultAttributes($ip): array
{
if (!($ip instanceof IPInfo)) {
throw new InvalidArgumentException(
get_class($this).' can only serialize instances of '.IPInfo::class
);
}
$attrs = parent::getDefaultAttributes($ip);

return [
'countryCode' => $ip->country_code,
$moreAttrs = [
'zipCode' => $ip->zip_code,
'latitude' => $ip->latitude,
'longitude' => $ip->longitude,
Expand All @@ -48,15 +39,7 @@ protected function getDefaultAttributes($ip): array
'createdAt' => $this->formatDate($ip->created_at),
'updatedAt' => $this->formatDate($ip->updated_at),
];
}

/**
* @param IPInfo $model
*
* @return string
*/
public function getId($model)
{
return $model->address;
return array_merge($attrs, $moreAttrs);
}
}

0 comments on commit 27a3615

Please sign in to comment.