-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Showing
17 changed files
with
283 additions
and
94 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,26 +1,22 @@ | ||
<?php | ||
use michaelbelgium\profileviews\listeners; | ||
|
||
use Michaelbelgium\Profileviews\Listeners\AddUserProfileViewsRelationship; | ||
use Michaelbelgium\Profileviews\Controllers\CreateUserProfileViewController; | ||
use Illuminate\Contracts\Events\Dispatcher; | ||
use Flarum\Api\Serializer\UserSerializer; | ||
use Flarum\Api\Event\Serializing; | ||
use Flarum\Extend\Locales; | ||
use Flarum\Extend\Frontend; | ||
use Flarum\Extend\Routes; | ||
|
||
return [ | ||
(new Frontend('forum')) | ||
->js(__DIR__. '/js/dist/forum.js'), | ||
->js(__DIR__. '/js/dist/forum.js') | ||
->css(__DIR__. '/less/extension.less'), | ||
|
||
new Locales(__DIR__ . '/locale'), | ||
|
||
(new Routes('api')) | ||
->post('/profileview', 'profileview.create', CreateUserProfileViewController::class), | ||
|
||
function (Dispatcher $events) { | ||
$events->subscribe(listeners\AddProfileViewHandler::class); | ||
$events->subscribe(listeners\AddUserProfileViewsRelationship::class); | ||
|
||
$events->listen(Serializing::class, function (Serializing $event) { | ||
if ($event->isSerializer(UserSerializer::class)) { | ||
$event->attributes['views'] = $event->model->profileViews()->count(); | ||
} | ||
}); | ||
$events->subscribe(AddUserProfileViewsRelationship::class); | ||
} | ||
]; |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
import Model from 'flarum/Model'; | ||
|
||
export default class ProfileView extends Model { | ||
//comes from ProfileViewSerializer (viewer(), viewedUser(), visited_at) | ||
visitedAt = Model.attribute('visited_at', Model.transformDate); | ||
viewer = Model.hasOne('viewer'); | ||
viewedUser = Model.hasOne('viewedUser'); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,22 +1,76 @@ | ||
import app from 'flarum/app'; | ||
import User from 'flarum/models/User'; | ||
import UserPage from 'flarum/components/UserPage'; | ||
import UserCard from 'flarum/components/UserCard'; | ||
import FieldSet from 'flarum/components/FieldSet'; | ||
import icon from 'flarum/helpers/icon'; | ||
import avatar from 'flarum/helpers/avatar'; | ||
import username from 'flarum/helpers/username'; | ||
import Model from 'flarum/Model'; | ||
import ItemList from 'flarum/utils/ItemList'; | ||
import { extend } from 'flarum/extend'; | ||
import humanTime from 'flarum/utils/humanTime'; | ||
import ProfileView from '../ProfileView'; | ||
|
||
app.initializers.add('michaelbelgium-flarum-profile-views', function() { | ||
User.prototype.views = Model.attribute('views'); | ||
app.store.models.userprofileview = ProfileView;//".userprofileview" = serializer type "userprofileview" | ||
User.prototype.profileViews = Model.hasMany('profileViews');//comes from AddUserProfileViewsRelationship::RELATIONSHIP = php model relationship method | ||
|
||
extend(UserCard.prototype, 'infoItems', function(items) { | ||
const user = this.props.user; | ||
|
||
const count = user.profileViews() === false ? 0 : user.profileViews().length; | ||
|
||
items.add('profile-views',( | ||
<span> | ||
{icon('far fa-eye')} | ||
{' '} | ||
{app.translator.trans('flarum_profile_views.forum.user.views_count_text', {viewcount: user.views() == 0 ? '0' : user.views()})} | ||
{app.translator.trans('flarum_profile_views.forum.user.views_count_text', {viewcount: '' + count})} | ||
</span> | ||
)); | ||
}); | ||
|
||
extend(UserPage.prototype, 'sidebarItems', function(items) { | ||
const lastViewed = new ItemList(); | ||
|
||
var views = this.user.profileViews(); | ||
|
||
if(views !== false) | ||
{ | ||
if(views.length >= 5) { | ||
views = views.slice(0, 5); | ||
} | ||
|
||
views.forEach(pv => { | ||
lastViewed.add('lastUser-' + pv.viewer().id(), | ||
<a href={app.forum.attribute('baseUrl') + '/u/' + pv.viewer().username() }> | ||
{avatar(pv.viewer(), {className: 'lastUser-avatar'})} | ||
<div> | ||
{username(pv.viewer())} | ||
<span className="lastUser-visited" title={pv.visitedAt().toLocaleString()}>{humanTime(pv.visitedAt())}</span> | ||
</div> | ||
</a> | ||
); | ||
}); | ||
} | ||
|
||
items.add('lastViewedUsers', FieldSet.component({ | ||
label: app.translator.trans('flarum_profile_views.forum.user.title_last_viewers'), | ||
className: 'LastUsers', | ||
children: lastViewed.toArray() | ||
})); | ||
}); | ||
|
||
extend(UserPage.prototype, 'show', function() { | ||
if(typeof app.session.user !== 'undefined' && app.session.user.id() !== this.user.id()) | ||
{ | ||
app.request({ | ||
method: 'POST', | ||
url: app.forum.attribute('apiUrl') + '/profileview', | ||
data: { | ||
viewer: app.session.user.id(), | ||
viewedUser: this.user.id() | ||
} | ||
}); | ||
} | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
fieldset.LastUsers { | ||
ul { | ||
list-style-type: none; | ||
padding: 0; | ||
|
||
li a { | ||
display: block; | ||
|
||
span.lastUser-avatar { | ||
width: 20%; | ||
display: inline-block; | ||
height: 35px; | ||
line-height: 35px; | ||
} | ||
|
||
div { | ||
display: inline-block; | ||
width: 80%; | ||
|
||
span.username { | ||
margin-left: 6px; | ||
} | ||
|
||
span.lastUser-visited { | ||
float: right; | ||
font-size: .8em; | ||
} | ||
} | ||
} | ||
|
||
li a:hover { | ||
div > span { | ||
text-decoration: underline; | ||
} | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,5 @@ | ||
flarum_profile_views: | ||
forum: | ||
user: | ||
views_count_text: viewed {viewcount} times | ||
views_count_text: viewed {viewcount} times | ||
title_last_viewers: Last profile viewers |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
<?php | ||
|
||
use Flarum\Database\Migration; | ||
|
||
return Migration::dropColumns("user_profile_views", [ | ||
"ip" => ["string"] | ||
]); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
<?php | ||
|
||
use Flarum\Database\Migration; | ||
|
||
return Migration::addColumns("user_profile_views", [ | ||
"visited_at" => ["datetime"] | ||
]); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
<?php | ||
namespace Michaelbelgium\Profileviews\Listeners; | ||
|
||
use Illuminate\Contracts\Events\Dispatcher; | ||
use Flarum\Event\GetApiRelationship; | ||
use Flarum\Event\GetModelRelationship; | ||
use Flarum\User\User; | ||
use Flarum\Api\Event\WillGetData; | ||
use Flarum\Api\Serializer\UserSerializer; | ||
use Flarum\Api\Controller\ShowUserController; | ||
use Michaelbelgium\Profileviews\Models\UserProfileView; | ||
use Michaelbelgium\Profileviews\Serializers\UserProfileViewSerializer; | ||
|
||
class AddUserProfileViewsRelationship | ||
{ | ||
const RELATIONSHIP = "profileViews"; //$user->profileViews() | ||
const RELATIONSHIP_OTHER = "viewedProfiles"; //$user->viewedProfiles() | ||
|
||
/** | ||
* @param Dispatcher $events | ||
*/ | ||
public function subscribe(Dispatcher $events) | ||
{ | ||
$events->listen(WillGetData::class, [$this, 'includeTagsRelationship']); | ||
$events->listen(GetModelRelationship::class, [$this, 'getModelRelationship']); | ||
$events->listen(GetApiRelationship::class, [$this, 'getApiRelationship']); | ||
} | ||
|
||
public function getModelRelationship(GetModelRelationship $event) | ||
{ | ||
if($event->isRelationship(User::class, self::RELATIONSHIP)) | ||
{ | ||
return $event->model->hasMany(UserProfileView::class, 'viewed_user_id'); | ||
} | ||
|
||
if($event->isRelationship(User::class, self::RELATIONSHIP_OTHER)) | ||
{ | ||
return $event->model->hasMany(UserProfileView::class, 'viewer_id'); | ||
} | ||
} | ||
|
||
/** | ||
* @param GetApiRelationship $event | ||
* @return \Tobscure\JsonApi\Relationship|null | ||
*/ | ||
public function getApiRelationship(GetApiRelationship $event) | ||
{ | ||
if ($event->isRelationship(UserSerializer::class, self::RELATIONSHIP)) { | ||
return $event->serializer->hasMany($event->model, UserProfileViewSerializer::class, self::RELATIONSHIP); | ||
} | ||
|
||
//todo test: | ||
if ($event->isRelationship(UserSerializer::class, self::RELATIONSHIP_OTHER)) { | ||
return $event->serializer->hasMany($event->model, UserProfileViewSerializer::class, self::RELATIONSHIP_OTHER); | ||
} | ||
} | ||
|
||
/** | ||
* @param WillGetData $event | ||
*/ | ||
public function includeTagsRelationship(WillGetData $event) | ||
{ | ||
if($event->controller->serializer == UserSerializer::class) | ||
$event->addInclude([self::RELATIONSHIP, self::RELATIONSHIP.'.viewer', self::RELATIONSHIP.'.viewedUser']);//".x" comes from model relationship UserProfileView | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
<?php | ||
|
||
namespace Michaelbelgium\Profileviews\Models; | ||
|
||
use Flarum\Database\AbstractModel; | ||
use Flarum\User\User; | ||
|
||
class UserProfileView extends AbstractModel | ||
{ | ||
protected $table = 'user_profile_views'; | ||
protected $dates = ['visited_at']; | ||
|
||
public function viewedUser() | ||
{ | ||
return $this->belongsTo(User::class, 'viewed_user_id'); | ||
} | ||
|
||
public function viewer() | ||
{ | ||
return $this->belongsTo(User::class, 'viewer_id'); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
<?php | ||
|
||
namespace Michaelbelgium\Profileviews\Serializers; | ||
|
||
use Flarum\Api\Serializer\AbstractSerializer; | ||
use Flarum\Api\Serializer\UserSerializer; | ||
|
||
class UserProfileViewSerializer extends AbstractSerializer | ||
{ | ||
protected $type = 'userprofileview'; | ||
|
||
protected function getDefaultAttributes($profileview) | ||
{ | ||
return [ | ||
'visited_at' => $this->formatDate($profileview->visited_at) | ||
]; | ||
} | ||
|
||
protected function viewedUser($profileview) | ||
{ | ||
return $this->hasOne($profileview, UserSerializer::class); | ||
} | ||
|
||
protected function viewer($profileview) | ||
{ | ||
return $this->hasOne($profileview, UserSerializer::class); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
<?php | ||
|
||
namespace Michaelbelgium\Profileviews\Controllers; | ||
|
||
use Psr\Http\Message\ResponseInterface as Response; | ||
use Psr\Http\Message\ServerRequestInterface as Request; | ||
use Psr\Http\Server\RequestHandlerInterface; | ||
use Zend\Diactoros\Response\JsonResponse; | ||
use Flarum\User\User; | ||
use Carbon\Carbon; | ||
use Michaelbelgium\Profileviews\Models\UserProfileView; | ||
|
||
class CreateUserProfileViewController implements RequestHandlerInterface | ||
{ | ||
public function handle(Request $request): Response | ||
{ | ||
$viewedUserId = array_get($request->getParsedBody(), 'viewedUser'); | ||
$viewerId = array_get($request->getParsedBody(), 'viewer'); | ||
$viewedUser = User::find($viewedUserId); | ||
|
||
$profileView = $viewedUser->profileViews()->where('viewer_id', $viewerId)->first(); | ||
|
||
if(is_null($profileView)) { | ||
$profileView = new UserProfileView(); | ||
$profileView->viewedUser()->associate($viewedUser); | ||
$profileView->viewer()->associate(User::find($viewerId)); | ||
} | ||
|
||
$profileView->visited_at = Carbon::now(); | ||
$profileView->save(); | ||
|
||
return new JsonResponse($profileView->toArray()); | ||
} | ||
} |
Oops, something went wrong.