diff --git a/extensions/likes/.gitignore b/extensions/likes/.gitignore index a4f3b125e..43eeee7fe 100644 --- a/extensions/likes/.gitignore +++ b/extensions/likes/.gitignore @@ -2,3 +2,5 @@ composer.phar .DS_Store Thumbs.db +bower_components +node_modules \ No newline at end of file diff --git a/extensions/likes/bootstrap.php b/extensions/likes/bootstrap.php index 1452bd2b1..6049f77ff 100644 --- a/extensions/likes/bootstrap.php +++ b/extensions/likes/bootstrap.php @@ -9,6 +9,13 @@ * file that was distributed with this source code. */ -require __DIR__.'/vendor/autoload.php'; +use Flarum\Likes\Listener; +use Illuminate\Contracts\Events\Dispatcher; -return 'Flarum\Likes\Extension'; +return function (Dispatcher $events) { + $events->subscribe(Listener\AddClientAssets::class); + $events->subscribe(Listener\AddPostLikesRelationship::class); + $events->subscribe(Listener\SaveLikesToDatabase::class); + $events->subscribe(Listener\SendNotificationWhenPostIsLiked::class); + +}; diff --git a/extensions/likes/composer.json b/extensions/likes/composer.json index 44307504a..426729190 100644 --- a/extensions/likes/composer.json +++ b/extensions/likes/composer.json @@ -1,10 +1,34 @@ { + "name": "flarum/likes", + "description": "Allow users to like posts.", + "type": "flarum-extension", + "license": "MIT", + "authors": [ + { + "name": "Toby Zerner", + "email": "toby.zerner@gmail.com" + } + ], + "support": { + "issues": "https://github.com/flarum/core/issues", + "source": "https://github.com/flarum/likes" + }, + "require": { + "flarum/core": "^0.1.0-beta.3" + }, "autoload": { "psr-4": { "Flarum\\Likes\\": "src/" } }, - "scripts": { - "style": "phpcs --standard=PSR2 -np src" + "extra": { + "flarum-extension": { + "title": "Likes", + "icon": { + "name": "thumbs-o-up", + "backgroundColor": "#3A649D", + "color": "#fff" + } + } } } diff --git a/extensions/likes/flarum.json b/extensions/likes/flarum.json deleted file mode 100644 index 2150104d6..000000000 --- a/extensions/likes/flarum.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "name": "likes", - "title": "Likes", - "description": "Allows users to like posts.", - "keywords": ["discussions"], - "version": "0.1.0-beta.2", - "author": { - "name": "Toby Zerner", - "email": "toby@flarum.org", - "homepage": "http://tobyzerner.com" - }, - "license": "MIT", - "require": { - "flarum": ">=0.1.0-beta.2" - }, - "support": { - "source": "https://github.com/flarum/likes", - "issues": "https://github.com/flarum/core/issues" - }, - "icon": { - "name": "thumbs-o-up", - "backgroundColor": "#3A649D", - "color": "#fff" - } -} diff --git a/extensions/likes/js/.gitignore b/extensions/likes/js/.gitignore deleted file mode 100644 index 372e20a51..000000000 --- a/extensions/likes/js/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -bower_components -node_modules -dist diff --git a/extensions/likes/js/admin/Gulpfile.js b/extensions/likes/js/admin/Gulpfile.js index d2e5ea63b..a2196c62f 100644 --- a/extensions/likes/js/admin/Gulpfile.js +++ b/extensions/likes/js/admin/Gulpfile.js @@ -2,6 +2,6 @@ var gulp = require('flarum-gulp'); gulp({ modules: { - 'likes': 'src/**/*.js' + 'flarum/likes': 'src/**/*.js' } }); diff --git a/extensions/likes/js/admin/dist/extension.js b/extensions/likes/js/admin/dist/extension.js new file mode 100644 index 000000000..ac2b8c819 --- /dev/null +++ b/extensions/likes/js/admin/dist/extension.js @@ -0,0 +1,26 @@ +System.register('flarum/likes/main', ['flarum/extend', 'flarum/app', 'flarum/components/PermissionGrid'], function (_export) { + 'use strict'; + + var extend, app, PermissionGrid; + return { + setters: [function (_flarumExtend) { + extend = _flarumExtend.extend; + }, function (_flarumApp) { + app = _flarumApp['default']; + }, function (_flarumComponentsPermissionGrid) { + PermissionGrid = _flarumComponentsPermissionGrid['default']; + }], + execute: function () { + + app.initializers.add('flarum-likes', function () { + extend(PermissionGrid.prototype, 'replyItems', function (items) { + items.add('likePosts', { + icon: 'thumbs-o-up', + label: 'Like posts', + permission: 'discussion.likePosts' + }); + }); + }); + } + }; +}); \ No newline at end of file diff --git a/extensions/likes/js/admin/src/main.js b/extensions/likes/js/admin/src/main.js index 2d726364e..beaa1d08f 100644 --- a/extensions/likes/js/admin/src/main.js +++ b/extensions/likes/js/admin/src/main.js @@ -2,7 +2,7 @@ import { extend } from 'flarum/extend'; import app from 'flarum/app'; import PermissionGrid from 'flarum/components/PermissionGrid'; -app.initializers.add('likes', () => { +app.initializers.add('flarum-likes', () => { extend(PermissionGrid.prototype, 'replyItems', items => { items.add('likePosts', { icon: 'thumbs-o-up', diff --git a/extensions/likes/js/forum/Gulpfile.js b/extensions/likes/js/forum/Gulpfile.js index d2e5ea63b..a2196c62f 100644 --- a/extensions/likes/js/forum/Gulpfile.js +++ b/extensions/likes/js/forum/Gulpfile.js @@ -2,6 +2,6 @@ var gulp = require('flarum-gulp'); gulp({ modules: { - 'likes': 'src/**/*.js' + 'flarum/likes': 'src/**/*.js' } }); diff --git a/extensions/likes/js/forum/dist/extension.js b/extensions/likes/js/forum/dist/extension.js new file mode 100644 index 000000000..5d8eb5162 --- /dev/null +++ b/extensions/likes/js/forum/dist/extension.js @@ -0,0 +1,285 @@ +System.register('flarum/likes/addLikeAction', ['flarum/extend', 'flarum/app', 'flarum/components/Button', 'flarum/components/CommentPost'], function (_export) { + 'use strict'; + + var extend, app, Button, CommentPost; + return { + setters: [function (_flarumExtend) { + extend = _flarumExtend.extend; + }, function (_flarumApp) { + app = _flarumApp['default']; + }, function (_flarumComponentsButton) { + Button = _flarumComponentsButton['default']; + }, function (_flarumComponentsCommentPost) { + CommentPost = _flarumComponentsCommentPost['default']; + }], + execute: function () { + _export('default', function () { + extend(CommentPost.prototype, 'actionItems', function (items) { + var post = this.props.post; + + if (post.isHidden() || !post.canLike()) return; + + var isLiked = app.session.user && post.likes().some(function (user) { + return user === app.session.user; + }); + + items.add('like', Button.component({ + children: app.trans(isLiked ? 'flarum-likes.forum.unlike_action' : 'flarum-likes.forum.like_action'), + className: 'Button Button--link', + onclick: function onclick() { + isLiked = !isLiked; + + post.save({ isLiked: isLiked }); + + // We've saved the fact that we do or don't like the post, but in order + // to provide instantaneous feedback to the user, we'll need to add or + // remove the like from the relationship data manually. + var data = post.data.relationships.likes.data; + data.some(function (like, i) { + if (like.id === app.session.user.id()) { + data.splice(i, 1); + return true; + } + }); + + if (isLiked) { + data.unshift({ type: 'users', id: app.session.user.id() }); + } + } + })); + }); + }); + } + }; +});;System.register('flarum/likes/addLikesList', ['flarum/extend', 'flarum/app', 'flarum/components/CommentPost', 'flarum/helpers/punctuateSeries', 'flarum/helpers/username', 'flarum/helpers/icon', 'flarum/likes/components/PostLikesModal'], function (_export) { + 'use strict'; + + var extend, app, CommentPost, punctuateSeries, username, icon, PostLikesModal; + return { + setters: [function (_flarumExtend) { + extend = _flarumExtend.extend; + }, function (_flarumApp) { + app = _flarumApp['default']; + }, function (_flarumComponentsCommentPost) { + CommentPost = _flarumComponentsCommentPost['default']; + }, function (_flarumHelpersPunctuateSeries) { + punctuateSeries = _flarumHelpersPunctuateSeries['default']; + }, function (_flarumHelpersUsername) { + username = _flarumHelpersUsername['default']; + }, function (_flarumHelpersIcon) { + icon = _flarumHelpersIcon['default']; + }, function (_flarumLikesComponentsPostLikesModal) { + PostLikesModal = _flarumLikesComponentsPostLikesModal['default']; + }], + execute: function () { + _export('default', function () { + extend(CommentPost.prototype, 'footerItems', function (items) { + var post = this.props.post; + var likes = post.likes(); + + if (likes && likes.length) { + var limit = 3; + + // Construct a list of names of users who have like this post. Make sure the + // current user is first in the list, and cap a maximum of 3 names. + var names = likes.sort(function (a) { + return a === app.session.user ? -1 : 1; + }).slice(0, limit).map(function (user) { + return m( + 'a', + { href: app.route.user(user), config: m.route }, + user === app.session.user ? app.trans('flarum-likes.forum.you') : username(user) + ); + }); + + // If there are more users that we've run out of room to display, add a "x + // others" name to the end of the list. Clicking on it will display a modal + // with a full list of names. + if (likes.length > limit) { + names.push(m( + 'a', + { href: '#', onclick: function (e) { + e.preventDefault(); + app.modal.show(new PostLikesModal({ post: post })); + } }, + app.trans('flarum-likes.forum.others', { count: likes.length - limit }) + )); + } + + items.add('liked', m( + 'div', + { className: 'Post-likedBy' }, + icon('thumbs-o-up'), + app.trans('flarum-likes.forum.post_liked_by' + (likes[0] === app.session.user ? '_self' : ''), { + count: names.length, + users: punctuateSeries(names) + }) + )); + } + }); + }); + } + }; +});;System.register('flarum/likes/main', ['flarum/extend', 'flarum/app', 'flarum/models/Post', 'flarum/Model', 'flarum/components/NotificationGrid', 'flarum/likes/addLikeAction', 'flarum/likes/addLikesList', 'flarum/likes/components/PostLikedNotification'], function (_export) { + 'use strict'; + + var extend, app, Post, Model, NotificationGrid, addLikeAction, addLikesList, PostLikedNotification; + return { + setters: [function (_flarumExtend) { + extend = _flarumExtend.extend; + }, function (_flarumApp) { + app = _flarumApp['default']; + }, function (_flarumModelsPost) { + Post = _flarumModelsPost['default']; + }, function (_flarumModel) { + Model = _flarumModel['default']; + }, function (_flarumComponentsNotificationGrid) { + NotificationGrid = _flarumComponentsNotificationGrid['default']; + }, function (_flarumLikesAddLikeAction) { + addLikeAction = _flarumLikesAddLikeAction['default']; + }, function (_flarumLikesAddLikesList) { + addLikesList = _flarumLikesAddLikesList['default']; + }, function (_flarumLikesComponentsPostLikedNotification) { + PostLikedNotification = _flarumLikesComponentsPostLikedNotification['default']; + }], + execute: function () { + + app.initializers.add('flarum-likes', function () { + app.notificationComponents.postLiked = PostLikedNotification; + + Post.prototype.canLike = Model.attribute('canLike'); + Post.prototype.likes = Model.hasMany('likes'); + + addLikeAction(); + addLikesList(); + + extend(NotificationGrid.prototype, 'notificationTypes', function (items) { + items.add('postLiked', { + name: 'postLiked', + icon: 'thumbs-o-up', + label: app.trans('flarum-likes.forum.notify_post_liked') + }); + }); + }); + } + }; +});;System.register('flarum/likes/components/PostLikedNotification', ['flarum/components/Notification', 'flarum/helpers/username', 'flarum/helpers/punctuate'], function (_export) { + 'use strict'; + + var Notification, username, punctuate, PostLikedNotification; + return { + setters: [function (_flarumComponentsNotification) { + Notification = _flarumComponentsNotification['default']; + }, function (_flarumHelpersUsername) { + username = _flarumHelpersUsername['default']; + }, function (_flarumHelpersPunctuate) { + punctuate = _flarumHelpersPunctuate['default']; + }], + execute: function () { + PostLikedNotification = (function (_Notification) { + babelHelpers.inherits(PostLikedNotification, _Notification); + + function PostLikedNotification() { + babelHelpers.classCallCheck(this, PostLikedNotification); + babelHelpers.get(Object.getPrototypeOf(PostLikedNotification.prototype), 'constructor', this).apply(this, arguments); + } + + babelHelpers.createClass(PostLikedNotification, [{ + key: 'icon', + value: function icon() { + return 'thumbs-o-up'; + } + }, { + key: 'href', + value: function href() { + return app.route.post(this.props.notification.subject()); + } + }, { + key: 'content', + value: function content() { + var notification = this.props.notification; + var user = notification.sender(); + var auc = notification.additionalUnreadCount(); + + return app.trans('flarum-likes.forum.post_liked_notification', { + user: user, + username: auc ? punctuate([username(user), app.trans('flarum-likes.forum.others', { count: auc })]) : undefined + }); + } + }, { + key: 'excerpt', + value: function excerpt() { + return this.props.notification.subject().contentPlain(); + } + }]); + return PostLikedNotification; + })(Notification); + + _export('default', PostLikedNotification); + } + }; +});;System.register('flarum/likes/components/PostLikesModal', ['flarum/components/Modal', 'flarum/helpers/avatar', 'flarum/helpers/username'], function (_export) { + 'use strict'; + + var Modal, avatar, username, PostLikesModal; + return { + setters: [function (_flarumComponentsModal) { + Modal = _flarumComponentsModal['default']; + }, function (_flarumHelpersAvatar) { + avatar = _flarumHelpersAvatar['default']; + }, function (_flarumHelpersUsername) { + username = _flarumHelpersUsername['default']; + }], + execute: function () { + PostLikesModal = (function (_Modal) { + babelHelpers.inherits(PostLikesModal, _Modal); + + function PostLikesModal() { + babelHelpers.classCallCheck(this, PostLikesModal); + babelHelpers.get(Object.getPrototypeOf(PostLikesModal.prototype), 'constructor', this).apply(this, arguments); + } + + babelHelpers.createClass(PostLikesModal, [{ + key: 'className', + value: function className() { + return 'PostLikesModal Modal--small'; + } + }, { + key: 'title', + value: function title() { + return app.trans('likes.post_likes_modal_title'); + } + }, { + key: 'content', + value: function content() { + return m( + 'div', + { className: 'Modal-body' }, + m( + 'ul', + { className: 'PostLikesModal-list' }, + this.props.post.likes().map(function (user) { + return m( + 'li', + null, + m( + 'a', + { href: app.route.user(user), config: m.route }, + avatar(user), + ' ', + ' ', + username(user) + ) + ); + }) + ) + ); + } + }]); + return PostLikesModal; + })(Modal); + + _export('default', PostLikesModal); + } + }; +}); \ No newline at end of file diff --git a/extensions/likes/js/forum/src/addLikeAction.js b/extensions/likes/js/forum/src/addLikeAction.js index 639728ddc..c2498ac62 100644 --- a/extensions/likes/js/forum/src/addLikeAction.js +++ b/extensions/likes/js/forum/src/addLikeAction.js @@ -13,7 +13,7 @@ export default function() { items.add('like', Button.component({ - children: app.trans(isLiked ? 'likes.unlike_action' : 'likes.like_action'), + children: app.trans(isLiked ? 'flarum-likes.forum.unlike_action' : 'flarum-likes.forum.like_action'), className: 'Button Button--link', onclick: () => { isLiked = !isLiked; diff --git a/extensions/likes/js/forum/src/addLikesList.js b/extensions/likes/js/forum/src/addLikesList.js index 571a5b105..09d8cdac2 100644 --- a/extensions/likes/js/forum/src/addLikesList.js +++ b/extensions/likes/js/forum/src/addLikesList.js @@ -1,11 +1,11 @@ import { extend } from 'flarum/extend'; import app from 'flarum/app'; import CommentPost from 'flarum/components/CommentPost'; -import punctuate from 'flarum/helpers/punctuate'; +import punctuateSeries from 'flarum/helpers/punctuateSeries'; import username from 'flarum/helpers/username'; import icon from 'flarum/helpers/icon'; -import PostLikesModal from 'likes/components/PostLikesModal'; +import PostLikesModal from 'flarum/likes/components/PostLikesModal'; export default function() { extend(CommentPost.prototype, 'footerItems', function(items) { @@ -22,7 +22,7 @@ export default function() { .map(user => { return ( - {user === app.session.user ? app.trans('likes.you') : username(user)} + {user === app.session.user ? app.trans('flarum-likes.forum.you') : username(user)} ); }); @@ -36,7 +36,7 @@ export default function() { e.preventDefault(); app.modal.show(new PostLikesModal({post})); }}> - {app.trans('likes.others', {count: likes.length - limit})} + {app.trans('flarum-likes.forum.others', {count: likes.length - limit})} ); } @@ -44,9 +44,9 @@ export default function() { items.add('liked', (
{icon('thumbs-o-up')} - {app.trans('likes.post_liked_by' + (likes[0] === app.session.user ? '_self' : ''), { + {app.trans('flarum-likes.forum.post_liked_by' + (likes[0] === app.session.user ? '_self' : ''), { count: names.length, - users: punctuate(names) + users: punctuateSeries(names) })}
)); diff --git a/extensions/likes/js/forum/src/components/PostLikedNotification.js b/extensions/likes/js/forum/src/components/PostLikedNotification.js index b78cb16aa..3da98de48 100644 --- a/extensions/likes/js/forum/src/components/PostLikedNotification.js +++ b/extensions/likes/js/forum/src/components/PostLikedNotification.js @@ -16,11 +16,11 @@ export default class PostLikedNotification extends Notification { const user = notification.sender(); const auc = notification.additionalUnreadCount(); - return app.trans('likes.post_liked_notification', { + return app.trans('flarum-likes.forum.post_liked_notification', { user, username: auc ? punctuate([ username(user), - app.trans('likes.others', {count: auc}) + app.trans('flarum-likes.forum.others', {count: auc}) ]) : undefined }); } diff --git a/extensions/likes/js/forum/src/components/PostLikesModal.js b/extensions/likes/js/forum/src/components/PostLikesModal.js index 0d1fb69ca..b10f8ba5c 100644 --- a/extensions/likes/js/forum/src/components/PostLikesModal.js +++ b/extensions/likes/js/forum/src/components/PostLikesModal.js @@ -18,7 +18,7 @@ export default class PostLikesModal extends Modal { {this.props.post.likes().map(user => (
  • - {avatar(user)}{' '} + {avatar(user)} {' '} {username(user)}
  • diff --git a/extensions/likes/js/forum/src/main.js b/extensions/likes/js/forum/src/main.js index 269dd7780..669690b6b 100644 --- a/extensions/likes/js/forum/src/main.js +++ b/extensions/likes/js/forum/src/main.js @@ -4,22 +4,24 @@ import Post from 'flarum/models/Post'; import Model from 'flarum/Model'; import NotificationGrid from 'flarum/components/NotificationGrid'; -import addLikeAction from 'likes/addLikeAction'; -import addLikesList from 'likes/addLikesList'; -import PostLikedNotification from 'likes/components/PostLikedNotification'; +import addLikeAction from 'flarum/likes/addLikeAction'; +import addLikesList from 'flarum/likes/addLikesList'; +import PostLikedNotification from 'flarum/likes/components/PostLikedNotification'; -app.notificationComponents.postLiked = PostLikedNotification; +app.initializers.add('flarum-likes', () => { + app.notificationComponents.postLiked = PostLikedNotification; -Post.prototype.canLike = Model.attribute('canLike'); -Post.prototype.likes = Model.hasMany('likes'); + Post.prototype.canLike = Model.attribute('canLike'); + Post.prototype.likes = Model.hasMany('likes'); -addLikeAction(); -addLikesList(); + addLikeAction(); + addLikesList(); -extend(NotificationGrid.prototype, 'notificationTypes', function(items) { - items.add('postLiked', { - name: 'postLiked', - icon: 'thumbs-o-up', - label: app.trans('likes.notify_post_liked') + extend(NotificationGrid.prototype, 'notificationTypes', function (items) { + items.add('postLiked', { + name: 'postLiked', + icon: 'thumbs-o-up', + label: app.trans('flarum-likes.forum.notify_post_liked') + }); }); -}); +}); \ No newline at end of file diff --git a/extensions/likes/locale/en.yml b/extensions/likes/locale/en.yml deleted file mode 100644 index 3fa9b2f62..000000000 --- a/extensions/likes/locale/en.yml +++ /dev/null @@ -1,12 +0,0 @@ -likes: - post_liked_notification: "{username} liked your post" - post_likes_modal_title: Users Who Like This - post_liked_by_self: "{users} like this." - post_liked_by: - one: "{users} likes this." - other: "{users} like this." - unlike_action: Unlike - like_action: Like - notify_post_liked: Someone likes my post - others: "{count} others" - you: You diff --git a/extensions/likes/migrations/2015_05_11_000000_create_posts_likes_table.php b/extensions/likes/migrations/2015_05_11_000000_create_posts_likes_table.php index 8f762f107..9e3b7a83d 100644 --- a/extensions/likes/migrations/2015_05_11_000000_create_posts_likes_table.php +++ b/extensions/likes/migrations/2015_05_11_000000_create_posts_likes_table.php @@ -8,18 +8,13 @@ * file that was distributed with this source code. */ -namespace Flarum\Migrations\Likes; +namespace Flarum\Likes\Migration; +use Flarum\Database\AbstractMigration; use Illuminate\Database\Schema\Blueprint; -use Flarum\Migrations\Migration; -class CreatePostsLikesTable extends Migration +class CreatePostsLikesTable extends AbstractMigration { - /** - * Run the migrations. - * - * @return void - */ public function up() { $this->schema->create('posts_likes', function (Blueprint $table) { @@ -29,11 +24,6 @@ class CreatePostsLikesTable extends Migration }); } - /** - * Reverse the migrations. - * - * @return void - */ public function down() { $this->schema->drop('posts_likes'); diff --git a/extensions/likes/migrations/2015_09_04_000000_add_default_like_permissions.php b/extensions/likes/migrations/2015_09_04_000000_add_default_like_permissions.php index cecab3abe..5e4076b18 100644 --- a/extensions/likes/migrations/2015_09_04_000000_add_default_like_permissions.php +++ b/extensions/likes/migrations/2015_09_04_000000_add_default_like_permissions.php @@ -8,20 +8,14 @@ * file that was distributed with this source code. */ -namespace Flarum\Migrations\Likes; +namespace Flarum\Likes\Migration; -use Illuminate\Database\Schema\Blueprint; -use Flarum\Migrations\Migration; -use Flarum\Core\Groups\Group; -use Flarum\Core\Groups\Permission; +use Flarum\Core\Group; +use Flarum\Core\Permission; +use Flarum\Database\AbstractMigration; -class AddDefaultLikePermissions extends Migration +class AddDefaultLikePermissions extends AbstractMigration { - /** - * Run the migrations. - * - * @return void - */ public function up() { Permission::unguard(); @@ -31,16 +25,14 @@ class AddDefaultLikePermissions extends Migration $permission->save(); } - /** - * Reverse the migrations. - * - * @return void - */ public function down() { Permission::where($this->getPermissionAttributes())->delete(); } + /** + * @return array + */ protected function getPermissionAttributes() { return [ diff --git a/extensions/likes/scripts/compile.sh b/extensions/likes/scripts/compile.sh new file mode 100755 index 000000000..b0d8e8bd3 --- /dev/null +++ b/extensions/likes/scripts/compile.sh @@ -0,0 +1,27 @@ +#!/usr/bin/env bash + +# This script compiles the extension so that it can be used in a Flarum +# installation. It should be run from the root directory of the extension. + +base=$PWD + +cd "${base}/js" + +if [ -f bower.json ]; then + bower install +fi + +for app in forum admin; do + cd "${base}/js" + + if [ -d $app ]; then + cd $app + + if [ -f bower.json ]; then + bower install + fi + + npm install + gulp --production + fi +done diff --git a/extensions/likes/src/Events/PostWasLiked.php b/extensions/likes/src/Event/PostWasLiked.php similarity index 86% rename from extensions/likes/src/Events/PostWasLiked.php rename to extensions/likes/src/Event/PostWasLiked.php index 589f8f0e0..fe5141917 100644 --- a/extensions/likes/src/Events/PostWasLiked.php +++ b/extensions/likes/src/Event/PostWasLiked.php @@ -8,10 +8,10 @@ * file that was distributed with this source code. */ -namespace Flarum\Likes\Events; +namespace Flarum\Likes\Event; -use Flarum\Core\Posts\Post; -use Flarum\Core\Users\User; +use Flarum\Core\Post; +use Flarum\Core\User; class PostWasLiked { diff --git a/extensions/likes/src/Events/PostWasUnliked.php b/extensions/likes/src/Event/PostWasUnliked.php similarity index 86% rename from extensions/likes/src/Events/PostWasUnliked.php rename to extensions/likes/src/Event/PostWasUnliked.php index 624d0c6cf..ffadb3709 100644 --- a/extensions/likes/src/Events/PostWasUnliked.php +++ b/extensions/likes/src/Event/PostWasUnliked.php @@ -8,10 +8,10 @@ * file that was distributed with this source code. */ -namespace Flarum\Likes\Events; +namespace Flarum\Likes\Event; -use Flarum\Core\Posts\Post; -use Flarum\Core\Users\User; +use Flarum\Core\Post; +use Flarum\Core\User; class PostWasUnliked { diff --git a/extensions/likes/src/Extension.php b/extensions/likes/src/Extension.php deleted file mode 100644 index a929386e7..000000000 --- a/extensions/likes/src/Extension.php +++ /dev/null @@ -1,26 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Flarum\Likes; - -use Flarum\Support\Extension as BaseExtension; -use Illuminate\Events\Dispatcher; - -class Extension extends BaseExtension -{ - public function listen(Dispatcher $events) - { - $events->subscribe('Flarum\Likes\Listeners\AddClientAssets'); - $events->subscribe('Flarum\Likes\Listeners\AddModelRelationship'); - $events->subscribe('Flarum\Likes\Listeners\AddApiAttributes'); - $events->subscribe('Flarum\Likes\Listeners\PersistData'); - $events->subscribe('Flarum\Likes\Listeners\NotifyPostLiked'); - } -} diff --git a/extensions/likes/src/Listener/AddClientAssets.php b/extensions/likes/src/Listener/AddClientAssets.php new file mode 100755 index 000000000..23f294b3c --- /dev/null +++ b/extensions/likes/src/Listener/AddClientAssets.php @@ -0,0 +1,47 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Flarum\Likes\Listener; + +use Flarum\Event\ConfigureClientView; +use Illuminate\Contracts\Events\Dispatcher; + +class AddClientAssets +{ + /** + * @param Dispatcher $events + */ + public function subscribe(Dispatcher $events) + { + $events->listen(ConfigureClientView::class, [$this, 'addAssets']); + } + + /** + * @param ConfigureClientView $event + */ + public function addAssets(ConfigureClientView $event) + { + if ($event->isForum()) { + $event->addAssets([ + __DIR__.'/../../js/forum/dist/extension.js', + __DIR__.'/../../less/forum/extension.less' + ]); + $event->addBootstrapper('flarum/likes/main'); + $event->addTranslations('flarum-likes.forum'); + } + + if ($event->isAdmin()) { + $event->addAssets([ + __DIR__.'/../../js/admin/dist/extension.js' + ]); + $event->addBootstrapper('flarum/likes/main'); + } + } +} diff --git a/extensions/likes/src/Listener/AddPostLikesRelationship.php b/extensions/likes/src/Listener/AddPostLikesRelationship.php new file mode 100755 index 000000000..fb05c52df --- /dev/null +++ b/extensions/likes/src/Listener/AddPostLikesRelationship.php @@ -0,0 +1,85 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Flarum\Likes\Listener; + +use Flarum\Api\Controller; +use Flarum\Api\Serializer\PostSerializer; +use Flarum\Api\Serializer\UserBasicSerializer; +use Flarum\Core\Post; +use Flarum\Core\User; +use Flarum\Event\ConfigureApiController; +use Flarum\Event\GetApiRelationship; +use Flarum\Event\GetModelRelationship; +use Flarum\Event\PrepareApiAttributes; +use Illuminate\Contracts\Events\Dispatcher; + +class AddPostLikesRelationship +{ + /** + * @param Dispatcher $events + */ + public function subscribe(Dispatcher $events) + { + $events->listen(GetModelRelationship::class, [$this, 'getModelRelationship']); + $events->listen(GetApiRelationship::class, [$this, 'getApiAttributes']); + $events->listen(PrepareApiAttributes::class, [$this, 'prepareApiAttributes']); + $events->listen(ConfigureApiController::class, [$this, 'includeLikes']); + } + + /** + * @param GetModelRelationship $event + * @return \Illuminate\Database\Eloquent\Relations\BelongsToMany|null + */ + public function getModelRelationship(GetModelRelationship $event) + { + if ($event->isRelationship(Post::class, 'likes')) { + return $event->model->belongsToMany(User::class, 'posts_likes', 'post_id', 'user_id', 'likes'); + } + } + + /** + * @param GetApiRelationship $event + * @return \Flarum\Api\Relationship\HasManyBuilder|null + */ + public function getApiAttributes(GetApiRelationship $event) + { + if ($event->isRelationship(PostSerializer::class, 'likes')) { + return $event->serializer->hasMany(UserBasicSerializer::class, 'likes'); + } + } + + /** + * @param PrepareApiAttributes $event + */ + public function prepareApiAttributes(PrepareApiAttributes $event) + { + if ($event->isSerializer(PostSerializer::class)) { + $event->attributes['canLike'] = (bool) $event->actor->can('like', $event->model); + } + } + + /** + * @param ConfigureApiController $event + */ + public function includeLikes(ConfigureApiController $event) + { + if ($event->isController(Controller\ShowDiscussionController::class)) { + $event->addInclude('posts.likes'); + } + + if ($event->isController(Controller\ListPostsController::class) + || $event->isController(Controller\ShowPostController::class) + || $event->isController(Controller\CreatePostController::class) + || $event->isController(Controller\UpdatePostController::class)) { + $event->addInclude('likes'); + } + } +} diff --git a/extensions/likes/src/Listeners/PersistData.php b/extensions/likes/src/Listener/SaveLikesToDatabase.php similarity index 73% rename from extensions/likes/src/Listeners/PersistData.php rename to extensions/likes/src/Listener/SaveLikesToDatabase.php index d1f7cd3c5..f7d9fbd4a 100755 --- a/extensions/likes/src/Listeners/PersistData.php +++ b/extensions/likes/src/Listener/SaveLikesToDatabase.php @@ -8,24 +8,31 @@ * file that was distributed with this source code. */ -namespace Flarum\Likes\Listeners; +namespace Flarum\Likes\Listener; -use Flarum\Likes\Events\PostWasLiked; -use Flarum\Likes\Events\PostWasUnliked; -use Flarum\Events\PostWillBeSaved; -use Flarum\Events\PostWasDeleted; -use Flarum\Core\Posts\Post; -use Flarum\Core\Exceptions\PermissionDeniedException; +use Flarum\Core\Access\AssertPermissionTrait; +use Flarum\Event\PostWasDeleted; +use Flarum\Event\PostWillBeSaved; +use Flarum\Likes\Event\PostWasLiked; +use Flarum\Likes\Event\PostWasUnliked; use Illuminate\Contracts\Events\Dispatcher; -class PersistData +class SaveLikesToDatabase { + use AssertPermissionTrait; + + /** + * @param Dispatcher $events + */ public function subscribe(Dispatcher $events) { $events->listen(PostWillBeSaved::class, [$this, 'whenPostWillBeSaved']); $events->listen(PostWasDeleted::class, [$this, 'whenPostWasDeleted']); } + /** + * @param PostWillBeSaved $event + */ public function whenPostWillBeSaved(PostWillBeSaved $event) { $post = $event->post; @@ -35,9 +42,7 @@ class PersistData $actor = $event->actor; $liked = (bool) $data['attributes']['isLiked']; - if (! $post->can($actor, 'like')) { - throw new PermissionDeniedException; - } + $this->assertCan($actor, 'like', $post); $currentlyLiked = $post->likes()->where('user_id', $actor->id)->exists(); @@ -53,6 +58,9 @@ class PersistData } } + /** + * @param PostWasDeleted $event + */ public function whenPostWasDeleted(PostWasDeleted $event) { $event->post->likes()->detach(); diff --git a/extensions/likes/src/Listeners/NotifyPostLiked.php b/extensions/likes/src/Listener/SendNotificationWhenPostIsLiked.php similarity index 52% rename from extensions/likes/src/Listeners/NotifyPostLiked.php rename to extensions/likes/src/Listener/SendNotificationWhenPostIsLiked.php index e9a257047..e43b10b9a 100755 --- a/extensions/likes/src/Listeners/NotifyPostLiked.php +++ b/extensions/likes/src/Listener/SendNotificationWhenPostIsLiked.php @@ -8,52 +8,72 @@ * file that was distributed with this source code. */ -namespace Flarum\Likes\Listeners; +namespace Flarum\Likes\Listener; -use Flarum\Likes\Notifications\PostLikedBlueprint; -use Flarum\Events\RegisterNotificationTypes; -use Flarum\Likes\Events\PostWasLiked; -use Flarum\Likes\Events\PostWasUnliked; -use Flarum\Core\Posts\Post; -use Flarum\Core\Users\User; -use Flarum\Core\Notifications\NotificationSyncer; +use Flarum\Api\Serializer\PostBasicSerializer; +use Flarum\Core\Notification\NotificationSyncer; +use Flarum\Core\Post; +use Flarum\Core\User; +use Flarum\Event\ConfigureNotificationTypes; +use Flarum\Likes\Event\PostWasLiked; +use Flarum\Likes\Event\PostWasUnliked; +use Flarum\Likes\Notification\PostLikedBlueprint; use Illuminate\Contracts\Events\Dispatcher; -class NotifyPostLiked +class SendNotificationWhenPostIsLiked { + /** + * @var NotificationSyncer + */ protected $notifications; + /** + * @param NotificationSyncer $notifications + */ public function __construct(NotificationSyncer $notifications) { $this->notifications = $notifications; } + /** + * @param Dispatcher $events + */ public function subscribe(Dispatcher $events) { - $events->listen(RegisterNotificationTypes::class, [$this, 'registerNotificationType']); + $events->listen(ConfigureNotificationTypes::class, [$this, 'registerNotificationType']); $events->listen(PostWasLiked::class, [$this, 'whenPostWasLiked']); $events->listen(PostWasUnliked::class, [$this, 'whenPostWasUnliked']); } - public function registerNotificationType(RegisterNotificationTypes $event) + /** + * @param ConfigureNotificationTypes $event + */ + public function registerNotificationType(ConfigureNotificationTypes $event) { - $event->register( - 'Flarum\Likes\Notifications\PostLikedBlueprint', - 'Flarum\Api\Serializers\PostBasicSerializer', - ['alert'] - ); + $event->add(PostLikedBlueprint::class, PostBasicSerializer::class, ['alert']); } + /** + * @param PostWasLiked $event + */ public function whenPostWasLiked(PostWasLiked $event) { $this->sync($event->post, $event->user, [$event->post->user]); } + /** + * @param PostWasUnliked $event + */ public function whenPostWasUnliked(PostWasUnliked $event) { $this->sync($event->post, $event->user, []); } + /** + * @param Post $post + * @param User $user + * @param array $recipients + */ public function sync(Post $post, User $user, array $recipients) { if ($post->user->id != $user->id) { diff --git a/extensions/likes/src/Listeners/AddApiAttributes.php b/extensions/likes/src/Listeners/AddApiAttributes.php deleted file mode 100755 index 34a090c1c..000000000 --- a/extensions/likes/src/Listeners/AddApiAttributes.php +++ /dev/null @@ -1,60 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Flarum\Likes\Listeners; - -use Flarum\Events\ApiAttributes; -use Flarum\Events\ApiRelationship; -use Flarum\Events\BuildApiAction; -use Illuminate\Contracts\Events\Dispatcher; -use Flarum\Api\Serializers\PostSerializer; -use Flarum\Api\Actions\Discussions; -use Flarum\Api\Actions\Posts; - -class AddApiAttributes -{ - public function subscribe(Dispatcher $events) - { - $events->listen(ApiAttributes::class, [$this, 'addAttributes']); - $events->listen(ApiRelationship::class, [$this, 'addRelationship']); - $events->listen(BuildApiAction::class, [$this, 'includeLikes']); - } - - public function addAttributes(ApiAttributes $event) - { - if ($event->serializer instanceof PostSerializer) { - $event->attributes['canLike'] = (bool) $event->model->can($event->actor, 'like'); - } - } - - public function addRelationship(ApiRelationship $event) - { - if ($event->serializer instanceof PostSerializer && - $event->relationship === 'likes') { - return $event->serializer->hasMany('Flarum\Api\Serializers\UserBasicSerializer', 'likes'); - } - } - - public function includeLikes(BuildApiAction $event) - { - $action = $event->action; - - if ($action instanceof Discussions\ShowAction) { - $event->addInclude('posts.likes'); - } - - if ($action instanceof Posts\IndexAction || - $action instanceof Posts\ShowAction || - $action instanceof Posts\CreateAction || - $action instanceof Posts\UpdateAction) { - $event->addInclude('likes'); - } - } -} diff --git a/extensions/likes/src/Listeners/AddClientAssets.php b/extensions/likes/src/Listeners/AddClientAssets.php deleted file mode 100755 index f54f21699..000000000 --- a/extensions/likes/src/Listeners/AddClientAssets.php +++ /dev/null @@ -1,57 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Flarum\Likes\Listeners; - -use Flarum\Events\RegisterLocales; -use Flarum\Events\BuildClientView; -use Illuminate\Contracts\Events\Dispatcher; - -class AddClientAssets -{ - public function subscribe(Dispatcher $events) - { - $events->listen(RegisterLocales::class, [$this, 'addLocale']); - $events->listen(BuildClientView::class, [$this, 'addAssets']); - } - - public function addLocale(RegisterLocales $event) - { - $event->addTranslations('en', __DIR__.'/../../locale/en.yml'); - } - - public function addAssets(BuildClientView $event) - { - $event->forumAssets([ - __DIR__.'/../../js/forum/dist/extension.js', - __DIR__.'/../../less/forum/extension.less' - ]); - - $event->forumBootstrapper('likes/main'); - - $event->forumTranslations([ - 'likes.post_liked_notification', - 'likes.post_likes_modal_title', - 'likes.post_liked_by_self', - 'likes.post_liked_by', - 'likes.unlike_action', - 'likes.like_action', - 'likes.notify_post_liked', - 'likes.others', - 'likes.you' - ]); - - $event->adminAssets([ - __DIR__.'/../../js/admin/dist/extension.js' - ]); - - $event->adminBootstrapper('likes/main'); - } -} diff --git a/extensions/likes/src/Listeners/AddModelRelationship.php b/extensions/likes/src/Listeners/AddModelRelationship.php deleted file mode 100755 index a0eca598b..000000000 --- a/extensions/likes/src/Listeners/AddModelRelationship.php +++ /dev/null @@ -1,31 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Flarum\Likes\Listeners; - -use Flarum\Events\ModelRelationship; -use Flarum\Core\Posts\Post; -use Illuminate\Contracts\Events\Dispatcher; - -class AddModelRelationship -{ - public function subscribe(Dispatcher $events) - { - $events->listen(ModelRelationship::class, [$this, 'addRelationship']); - } - - public function addRelationship(ModelRelationship $event) - { - if ($event->model instanceof Post && - $event->relationship === 'likes') { - return $event->model->belongsToMany('Flarum\Core\Users\User', 'posts_likes', 'post_id', 'user_id', 'likes'); - } - } -} diff --git a/extensions/likes/src/Notifications/PostLikedBlueprint.php b/extensions/likes/src/Notification/PostLikedBlueprint.php similarity index 58% rename from extensions/likes/src/Notifications/PostLikedBlueprint.php rename to extensions/likes/src/Notification/PostLikedBlueprint.php index 9b932140f..d658f51d1 100644 --- a/extensions/likes/src/Notifications/PostLikedBlueprint.php +++ b/extensions/likes/src/Notification/PostLikedBlueprint.php @@ -8,46 +8,71 @@ * file that was distributed with this source code. */ -namespace Flarum\Likes\Notifications; +namespace Flarum\Likes\Notification; -use Flarum\Core\Posts\Post; -use Flarum\Core\Users\User; -use Flarum\Core\Notifications\Blueprint; +use Flarum\Core\Post; +use Flarum\Core\User; +use Flarum\Core\Notification\BlueprintInterface; -class PostLikedBlueprint implements Blueprint +class PostLikedBlueprint implements BlueprintInterface { + /** + * @var Post + */ public $post; + /** + * @var User + */ public $user; + /** + * @param Post $post + * @param User $user + */ public function __construct(Post $post, User $user) { $this->post = $post; $this->user = $user; } + /** + * {@inheritdoc} + */ public function getSubject() { return $this->post; } + /** + * {@inheritdoc} + */ public function getSender() { return $this->user; } + /** + * {@inheritdoc} + */ public function getData() { return null; } + /** + * {@inheritdoc} + */ public static function getType() { return 'postLiked'; } + /** + * {@inheritdoc} + */ public static function getSubjectModel() { - return 'Flarum\Core\Posts\Post'; + return Post::class; } }