Apply fixes from StyleCI

This commit is contained in:
daniel 2018-08-28 03:07:36 +00:00 committed by StyleCI Bot
parent 75de27f482
commit b8abbdd90f
261 changed files with 3368 additions and 3231 deletions

View file

@ -2,9 +2,9 @@
namespace App\Console\Commands; namespace App\Console\Commands;
use Illuminate\Console\Command;
use App\Media;
use App\Jobs\ImageOptimizePipeline\ImageOptimize; use App\Jobs\ImageOptimizePipeline\ImageOptimize;
use App\Media;
use Illuminate\Console\Command;
class CatchUnoptimizedMedia extends Command class CatchUnoptimizedMedia extends Command
{ {

View file

@ -2,9 +2,10 @@
namespace App\Console\Commands; namespace App\Console\Commands;
use App\{Follower, Profile}; use App\Follower;
use Illuminate\Console\Command;
use App\Jobs\FollowPipeline\FollowPipeline; use App\Jobs\FollowPipeline\FollowPipeline;
use App\Profile;
use Illuminate\Console\Command;
class SeedFollows extends Command class SeedFollows extends Command
{ {
@ -46,7 +47,7 @@ class SeedFollows extends Command
$actor = Profile::inRandomOrder()->firstOrFail(); $actor = Profile::inRandomOrder()->firstOrFail();
$target = Profile::inRandomOrder()->firstOrFail(); $target = Profile::inRandomOrder()->firstOrFail();
$follow = new Follower; $follow = new Follower();
$follow->profile_id = $actor->id; $follow->profile_id = $actor->id;
$follow->following_id = $target->id; $follow->following_id = $target->id;
$follow->save(); $follow->save();

View file

@ -20,6 +20,7 @@ class Kernel extends ConsoleKernel
* Define the application's command schedule. * Define the application's command schedule.
* *
* @param \Illuminate\Console\Scheduling\Schedule $schedule * @param \Illuminate\Console\Scheduling\Schedule $schedule
*
* @return void * @return void
*/ */
protected function schedule(Schedule $schedule) protected function schedule(Schedule $schedule)

View file

@ -10,6 +10,7 @@ class EmailVerification extends Model
{ {
$base = config('app.url'); $base = config('app.url');
$path = '/i/confirm-email/'.$this->user_token.'/'.$this->random_token; $path = '/i/confirm-email/'.$this->user_token.'/'.$this->random_token;
return "{$base}{$path}"; return "{$base}{$path}";
} }
} }

View file

@ -2,14 +2,11 @@
namespace App\Events; namespace App\Events;
use Illuminate\Broadcasting\Channel; use App\User;
use Illuminate\Queue\SerializesModels; use App\UserSetting;
use Illuminate\Broadcasting\PrivateChannel;
use Illuminate\Broadcasting\PresenceChannel;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Broadcasting\InteractsWithSockets; use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Contracts\Broadcasting\ShouldBroadcast; use Illuminate\Foundation\Events\Dispatchable;
use App\{User, UserSetting}; use Illuminate\Queue\SerializesModels;
class AuthLoginEvent class AuthLoginEvent
{ {
@ -28,7 +25,7 @@ class AuthLoginEvent
public function handle(User $user) public function handle(User $user)
{ {
if (empty($user->settings)) { if (empty($user->settings)) {
$settings = new UserSetting; $settings = new UserSetting();
$settings->user_id = $user->id; $settings->user_id = $user->id;
$settings->save(); $settings->save();
} }

View file

@ -30,6 +30,7 @@ class Handler extends ExceptionHandler
* Report or log an exception. * Report or log an exception.
* *
* @param \Exception $exception * @param \Exception $exception
*
* @return void * @return void
*/ */
public function report(Exception $exception) public function report(Exception $exception)
@ -42,6 +43,7 @@ class Handler extends ExceptionHandler
* *
* @param \Illuminate\Http\Request $request * @param \Illuminate\Http\Request $request
* @param \Exception $exception * @param \Exception $exception
*
* @return \Illuminate\Http\Response * @return \Illuminate\Http\Response
*/ */
public function render($request, Exception $exception) public function render($request, Exception $exception)

View file

@ -24,6 +24,7 @@ class Follower extends Model
public function toText() public function toText()
{ {
$actorName = $this->actor->username; $actorName = $this->actor->username;
return "{$actorName} ".__('notification.startedFollowingYou'); return "{$actorName} ".__('notification.startedFollowingYou');
} }
@ -31,6 +32,7 @@ class Follower extends Model
{ {
$actorName = $this->actor->username; $actorName = $this->actor->username;
$actorUrl = $this->actor->url(); $actorUrl = $this->actor->url();
return "<a href='{$actorUrl}' class='profile-link'>{$actorName}</a> ". return "<a href='{$actorUrl}' class='profile-link'>{$actorName}</a> ".
__('notification.startedFollowingYou'); __('notification.startedFollowingYou');
} }

View file

@ -24,5 +24,4 @@ class Hashtag extends Model
{ {
return config('routes.hashtag.base').$this->slug; return config('routes.hashtag.base').$this->slug;
} }
} }

View file

@ -2,23 +2,24 @@
namespace App\Http\Controllers; namespace App\Http\Controllers;
use Illuminate\Http\Request; use App\EmailVerification;
use Carbon\Carbon;
use App\Mail\ConfirmEmail; use App\Mail\ConfirmEmail;
use Auth, DB, Cache, Mail, Redis; use App\Notification;
use App\{ use App\Profile;
EmailVerification, use App\User;
Notification, use App\UserFilter;
Profile, use Auth;
User, use Cache;
UserFilter use Carbon\Carbon;
}; use Illuminate\Http\Request;
use Mail;
use Redis;
class AccountController extends Controller class AccountController extends Controller
{ {
protected $filters = [ protected $filters = [
'user.mute', 'user.mute',
'user.block' 'user.block',
]; ];
public function __construct() public function __construct()
@ -89,12 +90,11 @@ class AccountController extends Controller
EmailVerification::whereUserId(Auth::id())->delete(); EmailVerification::whereUserId(Auth::id())->delete();
} }
$user = User::whereNull('email_verified_at')->find(Auth::id()); $user = User::whereNull('email_verified_at')->find(Auth::id());
$utoken = hash('sha512', $user->id); $utoken = hash('sha512', $user->id);
$rtoken = str_random(40); $rtoken = str_random(40);
$verify = new EmailVerification; $verify = new EmailVerification();
$verify->user_id = $user->id; $verify->user_id = $user->id;
$verify->email = $user->email; $verify->email = $user->email;
$verify->user_token = $utoken; $verify->user_token = $utoken;
@ -116,6 +116,7 @@ class AccountController extends Controller
$user = User::find(Auth::id()); $user = User::find(Auth::id());
$user->email_verified_at = Carbon::now(); $user->email_verified_at = Carbon::now();
$user->save(); $user->save();
return redirect('/'); return redirect('/');
} }
} }
@ -142,6 +143,7 @@ class AccountController extends Controller
foreach ($keys as $key) { foreach ($keys as $key) {
$notifications->push(Cache::get("{$prefix}{$key}")); $notifications->push(Cache::get("{$prefix}{$key}"));
} }
return $notifications; return $notifications;
} }
@ -150,7 +152,6 @@ class AccountController extends Controller
return view('account.messages'); return view('account.messages');
} }
public function showMessage(Request $request, $id) public function showMessage(Request $request, $id)
{ {
return view('account.message'); return view('account.message');
@ -160,7 +161,7 @@ class AccountController extends Controller
{ {
$this->validate($request, [ $this->validate($request, [
'type' => 'required|string', 'type' => 'required|string',
'item' => 'required|integer|min:1' 'item' => 'required|integer|min:1',
]); ]);
$user = Auth::user()->profile; $user = Auth::user()->profile;
@ -184,7 +185,7 @@ class AccountController extends Controller
break; break;
default: default:
# code... // code...
break; break;
} }
@ -192,18 +193,17 @@ class AccountController extends Controller
'user_id' => $user->id, 'user_id' => $user->id,
'filterable_id' => $filterable['id'], 'filterable_id' => $filterable['id'],
'filterable_type' => $filterable['type'], 'filterable_type' => $filterable['type'],
'filter_type' => 'mute' 'filter_type' => 'mute',
]); ]);
return redirect()->back(); return redirect()->back();
} }
public function block(Request $request) public function block(Request $request)
{ {
$this->validate($request, [ $this->validate($request, [
'type' => 'required|string', 'type' => 'required|string',
'item' => 'required|integer|min:1' 'item' => 'required|integer|min:1',
]); ]);
$user = Auth::user()->profile; $user = Auth::user()->profile;
@ -223,7 +223,7 @@ class AccountController extends Controller
break; break;
default: default:
# code... // code...
break; break;
} }
@ -231,11 +231,9 @@ class AccountController extends Controller
'user_id' => $user->id, 'user_id' => $user->id,
'filterable_id' => $filterable['id'], 'filterable_id' => $filterable['id'],
'filterable_type' => $filterable['type'], 'filterable_type' => $filterable['type'],
'filter_type' => 'block' 'filter_type' => 'block',
]); ]);
return redirect()->back(); return redirect()->back();
} }
} }

View file

@ -2,17 +2,16 @@
namespace App\Http\Controllers\Admin; namespace App\Http\Controllers\Admin;
use Illuminate\Http\Request; use App\Report;
use Carbon\Carbon; use Carbon\Carbon;
use App\{Comment, Like, Media, Profile, Report, Status, User}; use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
trait AdminReportController trait AdminReportController
{ {
public function updateReport(Request $request, $id) public function updateReport(Request $request, $id)
{ {
$this->validate($request, [ $this->validate($request, [
'action' => 'required|string' 'action' => 'required|string',
]); ]);
$action = $request->input('action'); $action = $request->input('action');
@ -23,7 +22,7 @@ trait AdminReportController
'unlist', 'unlist',
'delete', 'delete',
'shadowban', 'shadowban',
'ban' 'ban',
]; ];
if (!in_array($action, $actions)) { if (!in_array($action, $actions)) {

View file

@ -2,8 +2,10 @@
namespace App\Http\Controllers; namespace App\Http\Controllers;
use App\Media;
use App\Status;
use App\User;
use Illuminate\Http\Request; use Illuminate\Http\Request;
use App\{Comment, Like, Media, Profile, Status, User};
class AdminController extends Controller class AdminController extends Controller
{ {
@ -20,25 +22,28 @@ class AdminController extends Controller
public function users(Request $request) public function users(Request $request)
{ {
$users = User::orderBy('id', 'desc')->paginate(10); $users = User::orderBy('id', 'desc')->paginate(10);
return view('admin.users.home', compact('users')); return view('admin.users.home', compact('users'));
} }
public function statuses(Request $request) public function statuses(Request $request)
{ {
$statuses = Status::orderBy('id', 'desc')->paginate(10); $statuses = Status::orderBy('id', 'desc')->paginate(10);
return view('admin.statuses.home', compact('statuses')); return view('admin.statuses.home', compact('statuses'));
} }
public function showStatus(Request $request, $id) public function showStatus(Request $request, $id)
{ {
$status = Status::findOrFail($id); $status = Status::findOrFail($id);
return view('admin.statuses.show', compact('status')); return view('admin.statuses.show', compact('status'));
} }
public function media(Request $request) public function media(Request $request)
{ {
$media = Status::whereHas('media')->orderby('id', 'desc')->paginate(12); $media = Status::whereHas('media')->orderby('id', 'desc')->paginate(12);
return view('admin.media.home', compact('media')); return view('admin.media.home', compact('media'));
} }
} }

View file

@ -2,23 +2,17 @@
namespace App\Http\Controllers\Api; namespace App\Http\Controllers\Api;
use Auth, Cache; use App\Avatar;
use App\{
Avatar,
Like,
Profile,
Status
};
use League\Fractal;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
use App\Http\Controllers\AvatarController; use App\Http\Controllers\AvatarController;
use App\Util\Webfinger\Webfinger; use App\Http\Controllers\Controller;
use App\Transformer\Api\{
AccountTransformer,
StatusTransformer
};
use App\Jobs\AvatarPipeline\AvatarOptimize; use App\Jobs\AvatarPipeline\AvatarOptimize;
use App\Profile;
use App\Transformer\Api\AccountTransformer;
use App\Transformer\Api\StatusTransformer;
use Auth;
use Cache;
use Illuminate\Http\Request;
use League\Fractal;
use League\Fractal\Serializer\ArraySerializer; use League\Fractal\Serializer\ArraySerializer;
class BaseApiController extends Controller class BaseApiController extends Controller
@ -35,8 +29,9 @@ class BaseApiController extends Controller
public function accounts(Request $request, $id) public function accounts(Request $request, $id)
{ {
$profile = Profile::findOrFail($id); $profile = Profile::findOrFail($id);
$resource = new Fractal\Resource\Item($profile, new AccountTransformer); $resource = new Fractal\Resource\Item($profile, new AccountTransformer());
$res = $this->fractal->createData($resource)->toArray(); $res = $this->fractal->createData($resource)->toArray();
return response()->json($res, 200, [], JSON_PRETTY_PRINT); return response()->json($res, 200, [], JSON_PRETTY_PRINT);
} }
@ -44,8 +39,9 @@ class BaseApiController extends Controller
{ {
$profile = Profile::findOrFail($id); $profile = Profile::findOrFail($id);
$followers = $profile->followers; $followers = $profile->followers;
$resource = new Fractal\Resource\Collection($followers, new AccountTransformer); $resource = new Fractal\Resource\Collection($followers, new AccountTransformer());
$res = $this->fractal->createData($resource)->toArray(); $res = $this->fractal->createData($resource)->toArray();
return response()->json($res, 200, [], JSON_PRETTY_PRINT); return response()->json($res, 200, [], JSON_PRETTY_PRINT);
} }
@ -53,8 +49,9 @@ class BaseApiController extends Controller
{ {
$profile = Profile::findOrFail($id); $profile = Profile::findOrFail($id);
$following = $profile->following; $following = $profile->following;
$resource = new Fractal\Resource\Collection($following, new AccountTransformer); $resource = new Fractal\Resource\Collection($following, new AccountTransformer());
$res = $this->fractal->createData($resource)->toArray(); $res = $this->fractal->createData($resource)->toArray();
return response()->json($res, 200, [], JSON_PRETTY_PRINT); return response()->json($res, 200, [], JSON_PRETTY_PRINT);
} }
@ -62,17 +59,18 @@ class BaseApiController extends Controller
{ {
$profile = Profile::findOrFail($id); $profile = Profile::findOrFail($id);
$statuses = $profile->statuses()->orderBy('id', 'desc')->paginate(20); $statuses = $profile->statuses()->orderBy('id', 'desc')->paginate(20);
$resource = new Fractal\Resource\Collection($statuses, new StatusTransformer); $resource = new Fractal\Resource\Collection($statuses, new StatusTransformer());
$res = $this->fractal->createData($resource)->toArray(); $res = $this->fractal->createData($resource)->toArray();
return response()->json($res, 200, [], JSON_PRETTY_PRINT); return response()->json($res, 200, [], JSON_PRETTY_PRINT);
} }
public function followSuggestions(Request $request) public function followSuggestions(Request $request)
{ {
$followers = Auth::user()->profile->recommendFollowers(); $followers = Auth::user()->profile->recommendFollowers();
$resource = new Fractal\Resource\Collection($followers, new AccountTransformer); $resource = new Fractal\Resource\Collection($followers, new AccountTransformer());
$res = $this->fractal->createData($resource)->toArray(); $res = $this->fractal->createData($resource)->toArray();
return response()->json($res); return response()->json($res);
} }
@ -81,6 +79,7 @@ class BaseApiController extends Controller
$this->validate($request, [ $this->validate($request, [
'upload' => 'required|mimes:jpeg,png,gif|max:2000', 'upload' => 'required|mimes:jpeg,png,gif|max:2000',
]); ]);
try { try {
$user = Auth::user(); $user = Auth::user();
$profile = $user->profile; $profile = $user->profile;
@ -107,7 +106,7 @@ class BaseApiController extends Controller
return response()->json([ return response()->json([
'code' => 200, 'code' => 200,
'msg' => 'Avatar successfully updated' 'msg' => 'Avatar successfully updated',
]); ]);
} }
} }

View file

@ -2,14 +2,14 @@
namespace App\Http\Controllers; namespace App\Http\Controllers;
use Auth, Cache;
use App\{Like, Status};
use Illuminate\Http\Request;
use App\Http\Controllers\Api\BaseApiController; use App\Http\Controllers\Api\BaseApiController;
use App\Like;
use Auth;
use Cache;
use Illuminate\Http\Request;
class ApiController extends BaseApiController class ApiController extends BaseApiController
{ {
public function hydrateLikes(Request $request) public function hydrateLikes(Request $request)
{ {
$this->validate($request, [ $this->validate($request, [
@ -30,6 +30,5 @@ class ApiController extends BaseApiController
public function loadMoreComments(Request $request) public function loadMoreComments(Request $request)
{ {
return;
} }
} }

View file

@ -2,8 +2,9 @@
namespace App\Http\Controllers\Auth; namespace App\Http\Controllers\Auth;
use App\{AccountLog, User}; use App\AccountLog;
use App\Http\Controllers\Controller; use App\Http\Controllers\Controller;
use App\User;
use Illuminate\Foundation\Auth\AuthenticatesUsers; use Illuminate\Foundation\Auth\AuthenticatesUsers;
class LoginController extends Controller class LoginController extends Controller
@ -42,6 +43,7 @@ class LoginController extends Controller
* Validate the user login request. * Validate the user login request.
* *
* @param \Illuminate\Http\Request $request * @param \Illuminate\Http\Request $request
*
* @return void * @return void
*/ */
public function validateLogin($request) public function validateLogin($request)
@ -63,11 +65,12 @@ class LoginController extends Controller
* *
* @param \Illuminate\Http\Request $request * @param \Illuminate\Http\Request $request
* @param mixed $user * @param mixed $user
*
* @return mixed * @return mixed
*/ */
protected function authenticated($request, $user) protected function authenticated($request, $user)
{ {
$log = new AccountLog; $log = new AccountLog();
$log->user_id = $user->id; $log->user_id = $user->id;
$log->item_id = $user->id; $log->item_id = $user->id;
$log->item_type = 'App\User'; $log->item_type = 'App\User';

View file

@ -2,12 +2,12 @@
namespace App\Http\Controllers\Auth; namespace App\Http\Controllers\Auth;
use App\Http\Controllers\Controller;
use App\User; use App\User;
use App\Util\Lexer\RestrictedNames; use App\Util\Lexer\RestrictedNames;
use App\Http\Controllers\Controller; use Illuminate\Foundation\Auth\RegistersUsers;
use Illuminate\Support\Facades\Hash; use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Validator; use Illuminate\Support\Facades\Validator;
use Illuminate\Foundation\Auth\RegistersUsers;
class RegisterController extends Controller class RegisterController extends Controller
{ {
@ -46,6 +46,7 @@ class RegisterController extends Controller
* Get a validator for an incoming registration request. * Get a validator for an incoming registration request.
* *
* @param array $data * @param array $data
*
* @return \Illuminate\Contracts\Validation\Validator * @return \Illuminate\Contracts\Validation\Validator
*/ */
protected function validator(array $data) protected function validator(array $data)
@ -61,7 +62,7 @@ class RegisterController extends Controller
if (!ctype_alpha($value[0])) { if (!ctype_alpha($value[0])) {
return $fail($attribute.' is invalid. Username must be alpha-numeric and start with a letter.'); return $fail($attribute.' is invalid. Username must be alpha-numeric and start with a letter.');
} }
} },
]; ];
$rules = [ $rules = [
@ -82,6 +83,7 @@ class RegisterController extends Controller
* Create a new user instance after a valid registration. * Create a new user instance after a valid registration.
* *
* @param array $data * @param array $data
*
* @return \App\User * @return \App\User
*/ */
protected function create(array $data) protected function create(array $data)

View file

@ -2,10 +2,12 @@
namespace App\Http\Controllers; namespace App\Http\Controllers;
use Illuminate\Http\Request;
use Auth, Cache, Log, Storage;
use App\Avatar; use App\Avatar;
use App\Jobs\AvatarPipeline\AvatarOptimize; use App\Jobs\AvatarPipeline\AvatarOptimize;
use Auth;
use Cache;
use Illuminate\Http\Request;
use Storage;
class AvatarController extends Controller class AvatarController extends Controller
{ {
@ -17,8 +19,9 @@ class AvatarController extends Controller
public function store(Request $request) public function store(Request $request)
{ {
$this->validate($request, [ $this->validate($request, [
'avatar' => 'required|mimes:jpeg,png|max:2000' 'avatar' => 'required|mimes:jpeg,png|max:2000',
]); ]);
try { try {
$user = Auth::user(); $user = Auth::user();
$profile = $user->profile; $profile = $user->profile;
@ -42,6 +45,7 @@ class AvatarController extends Controller
AvatarOptimize::dispatch($user->profile, $currentAvatar); AvatarOptimize::dispatch($user->profile, $currentAvatar);
} catch (Exception $e) { } catch (Exception $e) {
} }
return redirect()->back()->with('status', 'Avatar updated successfully. It may take a few minutes to update across the site.'); return redirect()->back()->with('status', 'Avatar updated successfully. It may take a few minutes to update across the site.');
} }
@ -90,6 +94,7 @@ class AvatarController extends Controller
$this->checkDir($prefix); $this->checkDir($prefix);
} }
} }
return $avatarpath; return $avatarpath;
} }
} }

View file

@ -2,8 +2,9 @@
namespace App\Http\Controllers; namespace App\Http\Controllers;
use App\Bookmark;
use App\Status;
use Auth; use Auth;
use App\{Bookmark, Profile, Status};
use Illuminate\Http\Request; use Illuminate\Http\Request;
class BookmarkController extends Controller class BookmarkController extends Controller
@ -16,7 +17,7 @@ class BookmarkController extends Controller
public function store(Request $request) public function store(Request $request)
{ {
$this->validate($request, [ $this->validate($request, [
'item' => 'required|integer|min:1' 'item' => 'required|integer|min:1',
]); ]);
$profile = Auth::user()->profile; $profile = Auth::user()->profile;
@ -38,5 +39,4 @@ class BookmarkController extends Controller
return $response; return $response;
} }
} }

View file

@ -2,19 +2,21 @@
namespace App\Http\Controllers; namespace App\Http\Controllers;
use Illuminate\Http\Request; use App\Comment;
use App\Jobs\CommentPipeline\CommentPipeline; use App\Jobs\CommentPipeline\CommentPipeline;
use App\Jobs\StatusPipeline\NewStatusPipeline; use App\Jobs\StatusPipeline\NewStatusPipeline;
use Auth, Hashids; use App\Profile;
use App\{Comment, Profile, Status}; use App\Status;
use Auth;
use Illuminate\Http\Request;
class CommentController extends Controller class CommentController extends Controller
{ {
public function show(Request $request, $username, int $id, int $cid) public function show(Request $request, $username, int $id, int $cid)
{ {
$user = Profile::whereUsername($username)->firstOrFail(); $user = Profile::whereUsername($username)->firstOrFail();
$status = Status::whereProfileId($user->id)->whereInReplyToId($id)->findOrFail($cid); $status = Status::whereProfileId($user->id)->whereInReplyToId($id)->findOrFail($cid);
return view('status.reply', compact('user', 'status')); return view('status.reply', compact('user', 'status'));
} }
@ -23,15 +25,18 @@ class CommentController extends Controller
$user = Profile::whereUsername($username)->firstOrFail(); $user = Profile::whereUsername($username)->firstOrFail();
$status = Status::whereProfileId($user->id)->findOrFail($id); $status = Status::whereProfileId($user->id)->findOrFail($id);
$replies = Status::whereInReplyToId($id)->paginate(40); $replies = Status::whereInReplyToId($id)->paginate(40);
return view('status.comments', compact('user', 'status', 'replies')); return view('status.comments', compact('user', 'status', 'replies'));
} }
public function store(Request $request) public function store(Request $request)
{ {
if(Auth::check() === false) { abort(403); } if (Auth::check() === false) {
abort(403);
}
$this->validate($request, [ $this->validate($request, [
'item' => 'required|integer', 'item' => 'required|integer',
'comment' => 'required|string|max:500' 'comment' => 'required|string|max:500',
]); ]);
$comment = $request->input('comment'); $comment = $request->input('comment');
$statusId = $request->item; $statusId = $request->item;

View file

@ -2,10 +2,10 @@
namespace App\Http\Controllers; namespace App\Http\Controllers;
use Illuminate\Foundation\Bus\DispatchesJobs;
use Illuminate\Routing\Controller as BaseController;
use Illuminate\Foundation\Validation\ValidatesRequests;
use Illuminate\Foundation\Auth\Access\AuthorizesRequests; use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
use Illuminate\Foundation\Bus\DispatchesJobs;
use Illuminate\Foundation\Validation\ValidatesRequests;
use Illuminate\Routing\Controller as BaseController;
class Controller extends BaseController class Controller extends BaseController
{ {

View file

@ -2,9 +2,12 @@
namespace App\Http\Controllers; namespace App\Http\Controllers;
use Illuminate\Http\Request; use App\Follower;
use App\{Hashtag, Follower, Profile, Status, StatusHashtag}; use App\Hashtag;
use App\Profile;
use App\Status;
use Auth; use Auth;
use Illuminate\Http\Request;
class DiscoverController extends Controller class DiscoverController extends Controller
{ {
@ -38,7 +41,7 @@ class DiscoverController extends Controller
public function showTags(Request $request, $hashtag) public function showTags(Request $request, $hashtag)
{ {
$this->validate($request, [ $this->validate($request, [
'page' => 'nullable|integer|min:1|max:10' 'page' => 'nullable|integer|min:1|max:10',
]); ]);
$tag = Hashtag::with('posts') $tag = Hashtag::with('posts')

View file

@ -2,19 +2,17 @@
namespace App\Http\Controllers; namespace App\Http\Controllers;
use Auth, Cache; use App\Jobs\InboxPipeline\InboxWorker;
use App\Jobs\RemoteFollowPipeline\RemoteFollowPipeline;
use App\Profile; use App\Profile;
use Carbon\Carbon; use App\Transformer\ActivityPub\ProfileOutbox;
use League\Fractal;
use Illuminate\Http\Request;
use App\Util\Lexer\Nickname; use App\Util\Lexer\Nickname;
use App\Util\Webfinger\Webfinger; use App\Util\Webfinger\Webfinger;
use App\Transformer\ActivityPub\{ use Auth;
ProfileOutbox, use Cache;
ProfileTransformer use Carbon\Carbon;
}; use Illuminate\Http\Request;
use App\Jobs\RemoteFollowPipeline\RemoteFollowPipeline; use League\Fractal;
use App\Jobs\InboxPipeline\InboxWorker;
class FederationController extends Controller class FederationController extends Controller
{ {
@ -29,16 +27,18 @@ class FederationController extends Controller
{ {
$this->authCheck(); $this->authCheck();
$this->validate($request, [ $this->validate($request, [
'acct' => 'required|string|min:3|max:255' 'acct' => 'required|string|min:3|max:255',
]); ]);
$acct = $request->input('acct'); $acct = $request->input('acct');
$nickname = Nickname::normalizeProfileUrl($acct); $nickname = Nickname::normalizeProfileUrl($acct);
return view('federation.authorizefollow', compact('acct', 'nickname')); return view('federation.authorizefollow', compact('acct', 'nickname'));
} }
public function remoteFollow() public function remoteFollow()
{ {
$this->authCheck(); $this->authCheck();
return view('federation.remotefollow'); return view('federation.remotefollow');
} }
@ -46,7 +46,7 @@ class FederationController extends Controller
{ {
$this->authCheck(); $this->authCheck();
$this->validate($request, [ $this->validate($request, [
'url' => 'required|string' 'url' => 'required|string',
]); ]);
if (config('pixelfed.remote_follow_enabled') !== true) { if (config('pixelfed.remote_follow_enabled') !== true) {
@ -67,10 +67,11 @@ class FederationController extends Controller
'links' => [ 'links' => [
[ [
'href' => config('pixelfed.nodeinfo.url'), 'href' => config('pixelfed.nodeinfo.url'),
'rel' => 'http://nodeinfo.diaspora.software/ns/schema/2.0' 'rel' => 'http://nodeinfo.diaspora.software/ns/schema/2.0',
] ],
] ],
]; ];
return response()->json($res); return response()->json($res);
} }
@ -83,20 +84,20 @@ class FederationController extends Controller
'software' => [ 'software' => [
'homepage' => 'https://pixelfed.org', 'homepage' => 'https://pixelfed.org',
'github' => 'https://github.com/pixelfed', 'github' => 'https://github.com/pixelfed',
'follow' => 'https://mastodon.social/@pixelfed' 'follow' => 'https://mastodon.social/@pixelfed',
], ],
], ],
'openRegistrations' => config('pixelfed.open_registration'), 'openRegistrations' => config('pixelfed.open_registration'),
'protocols' => [ 'protocols' => [
'activitypub' 'activitypub',
], ],
'services' => [ 'services' => [
'inbound' => [], 'inbound' => [],
'outbound' => [] 'outbound' => [],
], ],
'software' => [ 'software' => [
'name' => 'pixelfed', 'name' => 'pixelfed',
'version' => config('pixelfed.version') 'version' => config('pixelfed.version'),
], ],
'usage' => [ 'usage' => [
'localPosts' => \App\Status::whereLocal(true)->whereHas('media')->count(), 'localPosts' => \App\Status::whereLocal(true)->whereHas('media')->count(),
@ -105,15 +106,15 @@ class FederationController extends Controller
'total' => \App\User::count(), 'total' => \App\User::count(),
'activeHalfyear' => \App\User::where('updated_at', '>', Carbon::now()->subMonths(6)->toDateTimeString())->count(), 'activeHalfyear' => \App\User::where('updated_at', '>', Carbon::now()->subMonths(6)->toDateTimeString())->count(),
'activeMonth' => \App\User::where('updated_at', '>', Carbon::now()->subMonths(1)->toDateTimeString())->count(), 'activeMonth' => \App\User::where('updated_at', '>', Carbon::now()->subMonths(1)->toDateTimeString())->count(),
]
], ],
'version' => '2.0' ],
'version' => '2.0',
]; ];
}); });
return response()->json($res, 200, [], JSON_PRETTY_PRINT); return response()->json($res, 200, [], JSON_PRETTY_PRINT);
} }
public function webfinger(Request $request) public function webfinger(Request $request)
{ {
$this->validate($request, ['resource'=>'required|string|min:3|max:255']); $this->validate($request, ['resource'=>'required|string|min:3|max:255']);
@ -125,8 +126,10 @@ class FederationController extends Controller
$parsed = Nickname::normalizeProfileUrl($resource); $parsed = Nickname::normalizeProfileUrl($resource);
$username = $parsed['username']; $username = $parsed['username'];
$user = Profile::whereUsername($username)->firstOrFail(); $user = Profile::whereUsername($username)->firstOrFail();
return (new Webfinger($user))->generate(); return (new Webfinger($user))->generate();
}); });
return response()->json($webfinger, 200, [], JSON_PRETTY_PRINT); return response()->json($webfinger, 200, [], JSON_PRETTY_PRINT);
} }
@ -139,8 +142,9 @@ class FederationController extends Controller
$user = Profile::whereNull('remote_url')->whereUsername($username)->firstOrFail(); $user = Profile::whereNull('remote_url')->whereUsername($username)->firstOrFail();
$timeline = $user->statuses()->orderBy('created_at', 'desc')->paginate(10); $timeline = $user->statuses()->orderBy('created_at', 'desc')->paginate(10);
$fractal = new Fractal\Manager(); $fractal = new Fractal\Manager();
$resource = new Fractal\Resource\Item($user, new ProfileOutbox); $resource = new Fractal\Resource\Item($user, new ProfileOutbox());
$res = $fractal->createData($resource)->toArray(); $res = $fractal->createData($resource)->toArray();
return response(json_encode($res['data']))->header('Content-Type', 'application/activity+json'); return response(json_encode($res['data']))->header('Content-Type', 'application/activity+json');
} }
@ -151,7 +155,7 @@ class FederationController extends Controller
} }
$mimes = [ $mimes = [
'application/activity+json', 'application/activity+json',
'application/ld+json; profile="https://www.w3.org/ns/activitystreams"' 'application/ld+json; profile="https://www.w3.org/ns/activitystreams"',
]; ];
if (!in_array($request->header('Content-Type'), $mimes)) { if (!in_array($request->header('Content-Type'), $mimes)) {
abort(500, 'Invalid request'); abort(500, 'Invalid request');
@ -159,5 +163,4 @@ class FederationController extends Controller
$profile = Profile::whereUsername($username)->firstOrFail(); $profile = Profile::whereUsername($username)->firstOrFail();
InboxWorker::dispatch($request, $profile, $request->all()); InboxWorker::dispatch($request, $profile, $request->all());
} }
} }

View file

@ -2,10 +2,11 @@
namespace App\Http\Controllers; namespace App\Http\Controllers;
use Auth; use App\Follower;
use App\{Follower, Profile};
use Illuminate\Http\Request;
use App\Jobs\FollowPipeline\FollowPipeline; use App\Jobs\FollowPipeline\FollowPipeline;
use App\Profile;
use Auth;
use Illuminate\Http\Request;
class FollowerController extends Controller class FollowerController extends Controller
{ {
@ -26,7 +27,7 @@ class FollowerController extends Controller
$isFollowing = Follower::whereProfileId($user->id)->whereFollowingId($target->id)->count(); $isFollowing = Follower::whereProfileId($user->id)->whereFollowingId($target->id)->count();
if ($isFollowing == 0) { if ($isFollowing == 0) {
$follower = new Follower; $follower = new Follower();
$follower->profile_id = $user->id; $follower->profile_id = $user->id;
$follower->following_id = $target->id; $follower->following_id = $target->id;
$follower->save(); $follower->save();
@ -36,7 +37,6 @@ class FollowerController extends Controller
$follower->delete(); $follower->delete();
} }
return redirect()->back(); return redirect()->back();
} }
} }

View file

@ -2,8 +2,6 @@
namespace App\Http\Controllers; namespace App\Http\Controllers;
use Illuminate\Http\Request;
class HashtagController extends Controller class HashtagController extends Controller
{ {
// //

View file

@ -2,8 +2,6 @@
namespace App\Http\Controllers; namespace App\Http\Controllers;
use Illuminate\Http\Request;
class HomeController extends Controller class HomeController extends Controller
{ {
/** /**

View file

@ -2,10 +2,13 @@
namespace App\Http\Controllers; namespace App\Http\Controllers;
use Illuminate\Http\Request;
use Auth, Cache, Hashids;
use App\{Like, Profile, Status, User};
use App\Jobs\LikePipeline\LikePipeline; use App\Jobs\LikePipeline\LikePipeline;
use App\Like;
use App\Status;
use App\User;
use Auth;
use Cache;
use Illuminate\Http\Request;
class LikeController extends Controller class LikeController extends Controller
{ {
@ -30,7 +33,7 @@ class LikeController extends Controller
$like->forceDelete(); $like->forceDelete();
$count--; $count--;
} else { } else {
$like = new Like; $like = new Like();
$like->profile_id = $profile->id; $like->profile_id = $profile->id;
$like->status_id = $status->id; $like->status_id = $status->id;
$like->save(); $like->save();

View file

@ -2,8 +2,6 @@
namespace App\Http\Controllers; namespace App\Http\Controllers;
use Illuminate\Http\Request;
class MediaController extends Controller class MediaController extends Controller
{ {
// //

View file

@ -2,8 +2,6 @@
namespace App\Http\Controllers; namespace App\Http\Controllers;
use Illuminate\Http\Request;
class NotificationController extends Controller class NotificationController extends Controller
{ {
// //

View file

@ -2,16 +2,13 @@
namespace App\Http\Controllers; namespace App\Http\Controllers;
use App\Follower;
use App\Profile;
use App\Transformer\ActivityPub\ProfileTransformer;
use App\User;
use Auth;
use Illuminate\Http\Request; use Illuminate\Http\Request;
use Auth, Cache;
use App\{Follower, Profile, User};
use League\Fractal; use League\Fractal;
use App\Util\Lexer\Nickname;
use App\Util\Webfinger\Webfinger;
use App\Transformer\ActivityPub\{
ProfileOutbox,
ProfileTransformer
};
class ProfileController extends Controller class ProfileController extends Controller
{ {
@ -19,7 +16,7 @@ class ProfileController extends Controller
{ {
$user = Profile::whereUsername($username)->firstOrFail(); $user = Profile::whereUsername($username)->firstOrFail();
if ($user->remote_url) { if ($user->remote_url) {
$settings = new \StdClass; $settings = new \StdClass();
$settings->crawlable = false; $settings->crawlable = false;
} else { } else {
$settings = User::whereUsername($username)->firstOrFail()->settings; $settings = User::whereUsername($username)->firstOrFail()->settings;
@ -80,8 +77,9 @@ class ProfileController extends Controller
public function showActivityPub(Request $request, $user) public function showActivityPub(Request $request, $user)
{ {
$fractal = new Fractal\Manager(); $fractal = new Fractal\Manager();
$resource = new Fractal\Resource\Item($user, new ProfileTransformer); $resource = new Fractal\Resource\Item($user, new ProfileTransformer());
$res = $fractal->createData($resource)->toArray(); $res = $fractal->createData($resource)->toArray();
return response(json_encode($res['data']))->header('Content-Type', 'application/activity+json'); return response(json_encode($res['data']))->header('Content-Type', 'application/activity+json');
} }
@ -89,6 +87,7 @@ class ProfileController extends Controller
{ {
$profile = Profile::whereUsername($user)->firstOrFail(); $profile = Profile::whereUsername($user)->firstOrFail();
$items = $profile->statuses()->orderBy('created_at', 'desc')->take(10)->get(); $items = $profile->statuses()->orderBy('created_at', 'desc')->take(10)->get();
return response()->view('atom.user', compact('profile', 'items')) return response()->view('atom.user', compact('profile', 'items'))
->header('Content-Type', 'application/atom+xml'); ->header('Content-Type', 'application/atom+xml');
} }
@ -102,6 +101,7 @@ class ProfileController extends Controller
$is_following = ($owner == false && Auth::check()) ? $user->followedBy(Auth::user()->profile) : false; $is_following = ($owner == false && Auth::check()) ? $user->followedBy(Auth::user()->profile) : false;
$followers = $profile->followers()->orderBy('created_at', 'desc')->simplePaginate(12); $followers = $profile->followers()->orderBy('created_at', 'desc')->simplePaginate(12);
$is_admin = is_null($user->domain) ? $user->user->is_admin : false; $is_admin = is_null($user->domain) ? $user->user->is_admin : false;
return view('profile.followers', compact('user', 'profile', 'followers', 'owner', 'is_following', 'is_admin')); return view('profile.followers', compact('user', 'profile', 'followers', 'owner', 'is_following', 'is_admin'));
} }
@ -114,6 +114,7 @@ class ProfileController extends Controller
$is_following = ($owner == false && Auth::check()) ? $user->followedBy(Auth::user()->profile) : false; $is_following = ($owner == false && Auth::check()) ? $user->followedBy(Auth::user()->profile) : false;
$following = $profile->following()->orderBy('created_at', 'desc')->simplePaginate(12); $following = $profile->following()->orderBy('created_at', 'desc')->simplePaginate(12);
$is_admin = is_null($user->domain) ? $user->user->is_admin : false; $is_admin = is_null($user->domain) ? $user->user->is_admin : false;
return view('profile.following', compact('user', 'profile', 'following', 'owner', 'is_following', 'is_admin')); return view('profile.following', compact('user', 'profile', 'following', 'owner', 'is_following', 'is_admin'));
} }
@ -129,6 +130,7 @@ class ProfileController extends Controller
$timeline = $user->bookmarks()->withCount(['likes', 'comments'])->orderBy('created_at', 'desc')->simplePaginate(10); $timeline = $user->bookmarks()->withCount(['likes', 'comments'])->orderBy('created_at', 'desc')->simplePaginate(10);
$is_following = ($owner == false && Auth::check()) ? $user->followedBy(Auth::user()->profile) : false; $is_following = ($owner == false && Auth::check()) ? $user->followedBy(Auth::user()->profile) : false;
$is_admin = is_null($user->domain) ? $user->user->is_admin : false; $is_admin = is_null($user->domain) ? $user->user->is_admin : false;
return view('profile.show', compact('user', 'settings', 'owner', 'following', 'timeline', 'is_following', 'is_admin')); return view('profile.show', compact('user', 'settings', 'owner', 'following', 'timeline', 'is_following', 'is_admin'));
} }
} }

View file

@ -2,9 +2,12 @@
namespace App\Http\Controllers; namespace App\Http\Controllers;
use App\Profile;
use App\Report;
use App\Status;
use App\User;
use Auth; use Auth;
use Illuminate\Http\Request; use Illuminate\Http\Request;
use App\{Avatar, Profile, Report, Status, User};
class ReportController extends Controller class ReportController extends Controller
{ {
@ -19,8 +22,9 @@ class ReportController extends Controller
{ {
$this->validate($request, [ $this->validate($request, [
'type' => 'required|alpha_dash', 'type' => 'required|alpha_dash',
'id' => 'required|integer|min:1' 'id' => 'required|integer|min:1',
]); ]);
return view('report.form'); return view('report.form');
} }
@ -85,7 +89,7 @@ class ReportController extends Controller
'report' => 'required|alpha_dash', 'report' => 'required|alpha_dash',
'type' => 'required|alpha_dash', 'type' => 'required|alpha_dash',
'id' => 'required|integer|min:1', 'id' => 'required|integer|min:1',
'msg' => 'nullable|string|max:150' 'msg' => 'nullable|string|max:150',
]); ]);
$profile = Auth::user()->profile; $profile = Auth::user()->profile;
@ -123,7 +127,7 @@ class ReportController extends Controller
return redirect('/timeline')->with('error', 'You cannot report your own content!'); return redirect('/timeline')->with('error', 'You cannot report your own content!');
} }
$report = new Report; $report = new Report();
$report->profile_id = $profile->id; $report->profile_id = $profile->id;
$report->user_id = Auth::id(); $report->user_id = Auth::id();
$report->object_id = $object->id; $report->object_id = $object->id;
@ -135,5 +139,4 @@ class ReportController extends Controller
return redirect('/timeline')->with('status', 'Report successfully sent!'); return redirect('/timeline')->with('status', 'Report successfully sent!');
} }
} }

View file

@ -2,7 +2,8 @@
namespace App\Http\Controllers; namespace App\Http\Controllers;
use App\{Hashtag, Profile}; use App\Hashtag;
use App\Profile;
use Illuminate\Http\Request; use Illuminate\Http\Request;
use Illuminate\Support\Facades\Cache; use Illuminate\Support\Facades\Cache;
@ -19,7 +20,7 @@ class SearchController extends Controller
'type' => 'hashtag', 'type' => 'hashtag',
'value' => $item->name, 'value' => $item->name,
'tokens' => explode('-', $item->name), 'tokens' => explode('-', $item->name),
'name' => null 'name' => null,
]; ];
}); });
$res = Profile::where('username', 'like', '%'.$tag.'%')->get(); $res = Profile::where('username', 'like', '%'.$tag.'%')->get();
@ -30,10 +31,11 @@ class SearchController extends Controller
'type' => 'profile', 'type' => 'profile',
'value' => $item->username, 'value' => $item->username,
'tokens' => [$item->username], 'tokens' => [$item->username],
'name' => $item->name 'name' => $item->name,
]; ];
}); });
$tags = $tags->push($profiles[0]); $tags = $tags->push($profiles[0]);
return $tags; return $tags;
}); });

View file

@ -2,10 +2,15 @@
namespace App\Http\Controllers; namespace App\Http\Controllers;
use Illuminate\Http\Request; use App\AccountLog;
use App\{AccountLog, EmailVerification, Media, Profile, User}; use App\EmailVerification;
use Auth, DB; use App\Media;
use App\Profile;
use App\User;
use App\Util\Lexer\PrettyNumber; use App\Util\Lexer\PrettyNumber;
use Auth;
use DB;
use Illuminate\Http\Request;
class SettingsController extends Controller class SettingsController extends Controller
{ {
@ -24,6 +29,7 @@ class SettingsController extends Controller
$storage['percentUsed'] = ceil($storage['used'] / $storage['limit'] * 100); $storage['percentUsed'] = ceil($storage['used'] / $storage['limit'] * 100);
$storage['limitPretty'] = PrettyNumber::size($storage['limit']); $storage['limitPretty'] = PrettyNumber::size($storage['limit']);
$storage['usedPretty'] = PrettyNumber::size($storage['used']); $storage['usedPretty'] = PrettyNumber::size($storage['used']);
return view('settings.home', compact('storage')); return view('settings.home', compact('storage'));
} }
@ -33,7 +39,7 @@ class SettingsController extends Controller
'name' => 'required|string|max:'.config('pixelfed.max_name_length'), 'name' => 'required|string|max:'.config('pixelfed.max_name_length'),
'bio' => 'nullable|string|max:'.config('pixelfed.max_bio_length'), 'bio' => 'nullable|string|max:'.config('pixelfed.max_bio_length'),
'website' => 'nullable|url', 'website' => 'nullable|url',
'email' => 'nullable|email' 'email' => 'nullable|email',
]); ]);
$changes = false; $changes = false;
@ -79,6 +85,7 @@ class SettingsController extends Controller
if ($changes === true) { if ($changes === true) {
$user->save(); $user->save();
$profile->save(); $profile->save();
return redirect('/settings/home')->with('status', 'Profile successfully updated!'); return redirect('/settings/home')->with('status', 'Profile successfully updated!');
} }
@ -110,6 +117,7 @@ class SettingsController extends Controller
return redirect('/settings/home')->with('status', 'Password successfully updated!'); return redirect('/settings/home')->with('status', 'Password successfully updated!');
} }
return redirect('/settings/home')->with('error', 'There was an error with your request!'); return redirect('/settings/home')->with('error', 'There was an error with your request!');
} }
@ -126,6 +134,7 @@ class SettingsController extends Controller
public function accessibility() public function accessibility()
{ {
$settings = Auth::user()->settings; $settings = Auth::user()->settings;
return view('settings.accessibility', compact('settings')); return view('settings.accessibility', compact('settings'));
} }
@ -137,7 +146,7 @@ class SettingsController extends Controller
'reduce_motion', 'reduce_motion',
'optimize_screen_reader', 'optimize_screen_reader',
'high_contrast_mode', 'high_contrast_mode',
'video_autoplay' 'video_autoplay',
]; ];
foreach ($fields as $field) { foreach ($fields as $field) {
$form = $request->input($field); $form = $request->input($field);
@ -148,6 +157,7 @@ class SettingsController extends Controller
} }
$settings->save(); $settings->save();
} }
return redirect(route('settings.accessibility'))->with('status', 'Settings successfully updated!'); return redirect(route('settings.accessibility'))->with('status', 'Settings successfully updated!');
} }
@ -161,6 +171,7 @@ class SettingsController extends Controller
$settings = Auth::user()->settings; $settings = Auth::user()->settings;
$is_private = Auth::user()->profile->is_private; $is_private = Auth::user()->profile->is_private;
$settings['is_private'] = (bool) $is_private; $settings['is_private'] = (bool) $is_private;
return view('settings.privacy', compact('settings')); return view('settings.privacy', compact('settings'));
} }
@ -172,7 +183,7 @@ class SettingsController extends Controller
'is_private', 'is_private',
'crawlable', 'crawlable',
'show_profile_follower_count', 'show_profile_follower_count',
'show_profile_following_count' 'show_profile_following_count',
]; ];
foreach ($fields as $field) { foreach ($fields as $field) {
$form = $request->input($field); $form = $request->input($field);
@ -201,6 +212,7 @@ class SettingsController extends Controller
} }
$settings->save(); $settings->save();
} }
return redirect(route('settings.privacy'))->with('status', 'Settings successfully updated!'); return redirect(route('settings.privacy'))->with('status', 'Settings successfully updated!');
} }
@ -214,6 +226,7 @@ class SettingsController extends Controller
->orderBy('created_at', 'desc') ->orderBy('created_at', 'desc')
->limit(50) ->limit(50)
->get(); ->get();
return view('settings.security', compact('sessions', 'activity')); return view('settings.security', compact('sessions', 'activity'));
} }

View file

@ -2,14 +2,18 @@
namespace App\Http\Controllers; namespace App\Http\Controllers;
use App, Auth, Cache; use App;
use Illuminate\Http\Request; use App\Follower;
use App\{Follower, Profile, Status, User}; use App\Profile;
use App\Status;
use App\User;
use App\Util\Lexer\PrettyNumber; use App\Util\Lexer\PrettyNumber;
use Auth;
use Cache;
use Illuminate\Http\Request;
class SiteController extends Controller class SiteController extends Controller
{ {
public function home() public function home()
{ {
if (Auth::check()) { if (Auth::check()) {
@ -35,6 +39,7 @@ class SiteController extends Controller
->withCount(['comments', 'likes', 'shares']) ->withCount(['comments', 'likes', 'shares'])
->simplePaginate(20); ->simplePaginate(20);
$type = 'personal'; $type = 'personal';
return view('timeline.template', compact('timeline', 'type')); return view('timeline.template', compact('timeline', 'type'));
} }
@ -44,6 +49,7 @@ class SiteController extends Controller
return redirect()->back(); return redirect()->back();
} }
App::setLocale($locale); App::setLocale($locale);
return redirect()->back(); return redirect()->back();
} }
@ -58,8 +64,10 @@ class SiteController extends Controller
$userCount = PrettyNumber::convert(User::count()); $userCount = PrettyNumber::convert(User::count());
$remoteCount = PrettyNumber::convert(Profile::whereNotNull('remote_url')->count()); $remoteCount = PrettyNumber::convert(Profile::whereNotNull('remote_url')->count());
$adminContact = User::whereIsAdmin(true)->first(); $adminContact = User::whereIsAdmin(true)->first();
return view('site.about')->with(compact('statusCount', 'userCount', 'remoteCount', 'adminContact'))->render(); return view('site.about')->with(compact('statusCount', 'userCount', 'remoteCount', 'adminContact'))->render();
}); });
return $res; return $res;
} }
} }

View file

@ -2,14 +2,18 @@
namespace App\Http\Controllers; namespace App\Http\Controllers;
use Auth, Cache;
use League\Fractal;
use Illuminate\Http\Request;
use Vinkla\Hashids\Facades\Hashids;
use App\{Media, Profile, Status, User};
use App\Jobs\ImageOptimizePipeline\ImageOptimize; use App\Jobs\ImageOptimizePipeline\ImageOptimize;
use App\Jobs\StatusPipeline\NewStatusPipeline;
use App\Jobs\StatusPipeline\StatusDelete;
use App\Media;
use App\Profile;
use App\Status;
use App\Transformer\ActivityPub\StatusTransformer; use App\Transformer\ActivityPub\StatusTransformer;
use App\Jobs\StatusPipeline\{NewStatusPipeline, StatusDelete}; use App\User;
use Auth;
use Cache;
use Illuminate\Http\Request;
use League\Fractal;
class StatusController extends Controller class StatusController extends Controller
{ {
@ -45,14 +49,17 @@ class StatusController extends Controller
if ($status->viewType() == 'video') { if ($status->viewType() == 'video') {
$template = 'status.show.video'; $template = 'status.show.video';
} }
return $template; return $template;
}); });
return $template; return $template;
} }
public function compose() public function compose()
{ {
$this->authCheck(); $this->authCheck();
return view('status.compose'); return view('status.compose');
} }
@ -83,7 +90,7 @@ class StatusController extends Controller
$userHash = hash('sha1', $user->id.(string) $user->created_at); $userHash = hash('sha1', $user->id.(string) $user->created_at);
$profile = $user->profile; $profile = $user->profile;
$status = new Status; $status = new Status();
$status->profile_id = $profile->id; $status->profile_id = $profile->id;
$status->caption = strip_tags($request->caption); $status->caption = strip_tags($request->caption);
$status->is_nsfw = $cw; $status->is_nsfw = $cw;
@ -96,7 +103,7 @@ class StatusController extends Controller
$storagePath = "public/m/{$monthHash}/{$userHash}"; $storagePath = "public/m/{$monthHash}/{$userHash}";
$path = $v->store($storagePath); $path = $v->store($storagePath);
$hash = \hash_file('sha256', $v); $hash = \hash_file('sha256', $v);
$media = new Media; $media = new Media();
$media->status_id = $status->id; $media->status_id = $status->id;
$media->profile_id = $profile->id; $media->profile_id = $profile->id;
$media->user_id = $user->id; $media->user_id = $user->id;
@ -127,7 +134,7 @@ class StatusController extends Controller
$this->validate($request, [ $this->validate($request, [
'type' => 'required|string', 'type' => 'required|string',
'item' => 'required|integer|min:1' 'item' => 'required|integer|min:1',
]); ]);
$status = Status::findOrFail($request->input('item')); $status = Status::findOrFail($request->input('item'));
@ -162,7 +169,7 @@ class StatusController extends Controller
$count--; $count--;
} }
} else { } else {
$share = new Status; $share = new Status();
$share->profile_id = $profile->id; $share->profile_id = $profile->id;
$share->reblog_of_id = $status->id; $share->reblog_of_id = $status->id;
$share->save(); $share->save();
@ -181,8 +188,9 @@ class StatusController extends Controller
public function showActivityPub(Request $request, $status) public function showActivityPub(Request $request, $status)
{ {
$fractal = new Fractal\Manager(); $fractal = new Fractal\Manager();
$resource = new Fractal\Resource\Item($status, new StatusTransformer); $resource = new Fractal\Resource\Item($status, new StatusTransformer());
$res = $fractal->createData($resource)->toArray(); $res = $fractal->createData($resource)->toArray();
return response(json_encode($res['data']))->header('Content-Type', 'application/activity+json'); return response(json_encode($res['data']))->header('Content-Type', 'application/activity+json');
} }
@ -193,10 +201,10 @@ class StatusController extends Controller
$status = Status::whereProfileId($user->id) $status = Status::whereProfileId($user->id)
->with(['media']) ->with(['media'])
->findOrFail($id); ->findOrFail($id);
return view('status.edit', compact('user', 'status')); return view('status.edit', compact('user', 'status'));
} }
public function editStore(Request $request, $username, $id) public function editStore(Request $request, $username, $id)
{ {
$this->authCheck(); $this->authCheck();
@ -208,7 +216,7 @@ class StatusController extends Controller
$this->validate($request, [ $this->validate($request, [
'id' => 'required|integer|min:1', 'id' => 'required|integer|min:1',
'caption' => 'nullable', 'caption' => 'nullable',
'filter' => 'nullable|alpha_dash|max:30' 'filter' => 'nullable|alpha_dash|max:30',
]); ]);
$id = $request->input('id'); $id = $request->input('id');
@ -234,13 +242,13 @@ class StatusController extends Controller
if ($changed === true) { if ($changed === true) {
$media->save(); $media->save();
} }
return response()->json([], 200); return response()->json([], 200);
} }
protected function authCheck() protected function authCheck()
{ {
if(Auth::check() == false) if (Auth::check() == false) {
{
abort(403); abort(403);
} }
} }

View file

@ -2,10 +2,6 @@
namespace App\Http\Controllers; namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Profile;
class StoryController extends Controller class StoryController extends Controller
{ {
} }

View file

@ -2,9 +2,12 @@
namespace App\Http\Controllers; namespace App\Http\Controllers;
use Illuminate\Http\Request; use App\Follower;
use App\Profile;
use App\Status;
use App\User;
use App\UserFilter;
use Auth; use Auth;
use App\{Follower, Profile, Status, User, UserFilter};
class TimelineController extends Controller class TimelineController extends Controller
{ {
@ -29,6 +32,7 @@ class TimelineController extends Controller
->withCount(['comments', 'likes']) ->withCount(['comments', 'likes'])
->simplePaginate(20); ->simplePaginate(20);
$type = 'personal'; $type = 'personal';
return view('timeline.template', compact('timeline', 'type')); return view('timeline.template', compact('timeline', 'type'));
} }
@ -52,7 +56,7 @@ class TimelineController extends Controller
->orderBy('id', 'desc') ->orderBy('id', 'desc')
->simplePaginate(20); ->simplePaginate(20);
$type = 'local'; $type = 'local';
return view('timeline.template', compact('timeline', 'type')); return view('timeline.template', compact('timeline', 'type'));
} }
} }

View file

@ -2,7 +2,8 @@
namespace App\Http\Middleware; namespace App\Http\Middleware;
use Auth, Closure; use Auth;
use Closure;
class Admin class Admin
{ {
@ -11,6 +12,7 @@ class Admin
* *
* @param \Illuminate\Http\Request $request * @param \Illuminate\Http\Request $request
* @param \Closure $next * @param \Closure $next
*
* @return mixed * @return mixed
*/ */
public function handle($request, Closure $next) public function handle($request, Closure $next)

View file

@ -2,7 +2,7 @@
namespace App\Http\Middleware; namespace App\Http\Middleware;
use Auth, Closure; use Closure;
class EmailVerificationCheck class EmailVerificationCheck
{ {
@ -11,6 +11,7 @@ class EmailVerificationCheck
* *
* @param \Illuminate\Http\Request $request * @param \Illuminate\Http\Request $request
* @param \Closure $next * @param \Closure $next
*
* @return mixed * @return mixed
*/ */
public function handle($request, Closure $next) public function handle($request, Closure $next)
@ -22,6 +23,7 @@ class EmailVerificationCheck
) { ) {
return redirect('/i/verify-email'); return redirect('/i/verify-email');
} }
return $next($request); return $next($request);
} }
} }

View file

@ -13,6 +13,7 @@ class RedirectIfAuthenticated
* @param \Illuminate\Http\Request $request * @param \Illuminate\Http\Request $request
* @param \Closure $next * @param \Closure $next
* @param string|null $guard * @param string|null $guard
*
* @return mixed * @return mixed
*/ */
public function handle($request, Closure $next, $guard = null) public function handle($request, Closure $next, $guard = null)

View file

@ -2,8 +2,8 @@
namespace App\Http\Middleware; namespace App\Http\Middleware;
use Illuminate\Http\Request;
use Fideloper\Proxy\TrustProxies as Middleware; use Fideloper\Proxy\TrustProxies as Middleware;
use Illuminate\Http\Request;
class TrustProxies extends Middleware class TrustProxies extends Middleware
{ {

View file

@ -2,14 +2,15 @@
namespace App\Jobs\AvatarPipeline; namespace App\Jobs\AvatarPipeline;
use \Carbon\Carbon; use App\Avatar;
use Image as Intervention; use App\Profile;
use App\{Avatar, Profile}; use Carbon\Carbon;
use Illuminate\Bus\Queueable; use Illuminate\Bus\Queueable;
use Illuminate\Queue\SerializesModels;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Queue\ShouldQueue; use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable; use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
use Image as Intervention;
class AvatarOptimize implements ShouldQueue class AvatarOptimize implements ShouldQueue
{ {
@ -54,7 +55,6 @@ class AvatarOptimize implements ShouldQueue
$avatar->save(); $avatar->save();
$this->deleteOldAvatar($avatar->media_path, $this->current); $this->deleteOldAvatar($avatar->media_path, $this->current);
} catch (Exception $e) { } catch (Exception $e) {
} }
} }

View file

@ -2,23 +2,24 @@
namespace App\Jobs\AvatarPipeline; namespace App\Jobs\AvatarPipeline;
use App\{Avatar, Profile}; use App\Avatar;
use Illuminate\Bus\Queueable; use App\Profile;
use Illuminate\Queue\SerializesModels; use App\Util\Identicon\Preprocessor\HashPreprocessor;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Support\Str;
use Bitverse\Identicon\Identicon;
use Bitverse\Identicon\Color\Color; use Bitverse\Identicon\Color\Color;
use Bitverse\Identicon\Generator\RingsGenerator; use Bitverse\Identicon\Generator\RingsGenerator;
use App\Util\Identicon\Preprocessor\HashPreprocessor; use Bitverse\Identicon\Identicon;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
class CreateAvatar implements ShouldQueue class CreateAvatar implements ShouldQueue
{ {
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels; use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
protected $profile; protected $profile;
/** /**
* Create a new job instance. * Create a new job instance.
* *
@ -48,7 +49,6 @@ class CreateAvatar implements ShouldQueue
$icon = $identicon->getIcon($hash); $icon = $identicon->getIcon($hash);
try { try {
$baseDir = storage_path('app/public/avatars'); $baseDir = storage_path('app/public/avatars');
if (!is_dir($baseDir)) { if (!is_dir($baseDir)) {
mkdir($baseDir); mkdir($baseDir);
@ -94,16 +94,14 @@ class CreateAvatar implements ShouldQueue
$basePath = storage_path('app/'.$path); $basePath = storage_path('app/'.$path);
file_put_contents($basePath, $icon); file_put_contents($basePath, $icon);
} catch (Exception $e) { } catch (Exception $e) {
} }
$avatar = new Avatar; $avatar = new Avatar();
$avatar->profile_id = $profile->id; $avatar->profile_id = $profile->id;
$avatar->media_path = $path; $avatar->media_path = $path;
$avatar->thumb_path = $path; $avatar->thumb_path = $path;
$avatar->change_count = 0; $avatar->change_count = 0;
$avatar->last_processed_at = \Carbon\Carbon::now(); $avatar->last_processed_at = \Carbon\Carbon::now();
$avatar->save(); $avatar->save();
} }
} }

View file

@ -2,14 +2,16 @@
namespace App\Jobs\CommentPipeline; namespace App\Jobs\CommentPipeline;
use Cache, Log, Redis; use App\Notification;
use App\{Like, Notification, Status}; use App\Status;
use App\Util\Lexer\Hashtag as HashtagLexer; use Cache;
use Illuminate\Bus\Queueable; use Illuminate\Bus\Queueable;
use Illuminate\Queue\SerializesModels;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Queue\ShouldQueue; use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable; use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
use Log;
use Redis;
class CommentPipeline implements ShouldQueue class CommentPipeline implements ShouldQueue
{ {
@ -47,8 +49,7 @@ class CommentPipeline implements ShouldQueue
} }
try { try {
$notification = new Notification();
$notification = new Notification;
$notification->profile_id = $target->id; $notification->profile_id = $target->id;
$notification->actor_id = $actor->id; $notification->actor_id = $actor->id;
$notification->action = 'comment'; $notification->action = 'comment';
@ -64,10 +65,8 @@ class CommentPipeline implements ShouldQueue
$nkey = config('cache.prefix').':user.'.$target->id.'.notifications'; $nkey = config('cache.prefix').':user.'.$target->id.'.notifications';
$redis->lpush($nkey, $notification->id); $redis->lpush($nkey, $notification->id);
} catch (Exception $e) { } catch (Exception $e) {
Log::error($e); Log::error($e);
} }
} }
} }

View file

@ -2,14 +2,15 @@
namespace App\Jobs\FollowPipeline; namespace App\Jobs\FollowPipeline;
use Cache, Log, Redis; use App\Notification;
use App\{Like, Notification}; use Cache;
use Illuminate\Bus\Queueable; use Illuminate\Bus\Queueable;
use Illuminate\Queue\SerializesModels;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Queue\ShouldQueue; use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable; use Illuminate\Foundation\Bus\Dispatchable;
use App\Jobs\FollowPipeline\FollowDiscover; use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
use Log;
use Redis;
class FollowPipeline implements ShouldQueue class FollowPipeline implements ShouldQueue
{ {
@ -39,8 +40,7 @@ class FollowPipeline implements ShouldQueue
$target = $follower->target; $target = $follower->target;
try { try {
$notification = new Notification();
$notification = new Notification;
$notification->profile_id = $target->id; $notification->profile_id = $target->id;
$notification->actor_id = $actor->id; $notification->actor_id = $actor->id;
$notification->action = 'follow'; $notification->action = 'follow';
@ -56,7 +56,6 @@ class FollowPipeline implements ShouldQueue
$nkey = config('cache.prefix').':user.'.$target->id.'.notifications'; $nkey = config('cache.prefix').':user.'.$target->id.'.notifications';
$redis->lpush($nkey, $notification->id); $redis->lpush($nkey, $notification->id);
} catch (Exception $e) { } catch (Exception $e) {
Log::error($e); Log::error($e);
} }

View file

@ -2,14 +2,12 @@
namespace App\Jobs\ImageOptimizePipeline; namespace App\Jobs\ImageOptimizePipeline;
use Carbon\Carbon; use App\Media;
use ImageOptimizer;
use App\{Media, Status};
use Illuminate\Bus\Queueable; use Illuminate\Bus\Queueable;
use Illuminate\Queue\SerializesModels;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Queue\ShouldQueue; use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable; use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
class ImageOptimize implements ShouldQueue class ImageOptimize implements ShouldQueue
{ {

View file

@ -2,15 +2,13 @@
namespace App\Jobs\ImageOptimizePipeline; namespace App\Jobs\ImageOptimizePipeline;
use Carbon\Carbon; use App\Media;
use ImageOptimizer;
use App\{Media, Status};
use App\Util\Media\Image; use App\Util\Media\Image;
use Illuminate\Bus\Queueable; use Illuminate\Bus\Queueable;
use Illuminate\Queue\SerializesModels;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Queue\ShouldQueue; use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable; use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
class ImageResize implements ShouldQueue class ImageResize implements ShouldQueue
{ {
@ -42,10 +40,9 @@ class ImageResize implements ShouldQueue
} }
try { try {
$img = new Image; $img = new Image();
$img->resizeImage($media); $img->resizeImage($media);
} catch (Exception $e) { } catch (Exception $e) {
} }
ImageThumbnail::dispatch($media); ImageThumbnail::dispatch($media);

View file

@ -2,14 +2,14 @@
namespace App\Jobs\ImageOptimizePipeline; namespace App\Jobs\ImageOptimizePipeline;
use Carbon\Carbon; use App\Media;
use App\{Media, Status};
use App\Util\Media\Image; use App\Util\Media\Image;
use Carbon\Carbon;
use Illuminate\Bus\Queueable; use Illuminate\Bus\Queueable;
use Illuminate\Queue\SerializesModels;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Queue\ShouldQueue; use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable; use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
class ImageThumbnail implements ShouldQueue class ImageThumbnail implements ShouldQueue
{ {
@ -41,10 +41,9 @@ class ImageThumbnail implements ShouldQueue
} }
try { try {
$img = new Image; $img = new Image();
$img->resizeThumbnail($media); $img->resizeThumbnail($media);
} catch (Exception $e) { } catch (Exception $e) {
} }
$media->processed_at = Carbon::now(); $media->processed_at = Carbon::now();

View file

@ -2,13 +2,13 @@
namespace App\Jobs\ImageOptimizePipeline; namespace App\Jobs\ImageOptimizePipeline;
use ImageOptimizer; use App\Media;
use App\{Media, Status};
use Illuminate\Bus\Queueable; use Illuminate\Bus\Queueable;
use Illuminate\Queue\SerializesModels;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Queue\ShouldQueue; use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable; use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
use ImageOptimizer;
class ImageUpdate implements ShouldQueue class ImageUpdate implements ShouldQueue
{ {
@ -19,7 +19,7 @@ class ImageUpdate implements ShouldQueue
protected $protectedMimes = [ protected $protectedMimes = [
'image/gif', 'image/gif',
'image/bmp', 'image/bmp',
'video/mp4' 'video/mp4',
]; ];
/** /**
@ -42,9 +42,9 @@ class ImageUpdate implements ShouldQueue
$media = $this->media; $media = $this->media;
$path = storage_path('app/'.$media->media_path); $path = storage_path('app/'.$media->media_path);
$thumb = storage_path('app/'.$media->thumbnail_path); $thumb = storage_path('app/'.$media->thumbnail_path);
try { try {
if(!in_array($media->mime, $this->protectedMimes)) if (!in_array($media->mime, $this->protectedMimes)) {
{
ImageOptimizer::optimize($thumb); ImageOptimizer::optimize($thumb);
ImageOptimizer::optimize($path); ImageOptimizer::optimize($path);
} }

View file

@ -5,10 +5,10 @@ namespace App\Jobs\InboxPipeline;
use App\Profile; use App\Profile;
use App\Util\ActivityPub\Inbox; use App\Util\ActivityPub\Inbox;
use Illuminate\Bus\Queueable; use Illuminate\Bus\Queueable;
use Illuminate\Queue\SerializesModels;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Queue\ShouldQueue; use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable; use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
class InboxWorker implements ShouldQueue class InboxWorker implements ShouldQueue
{ {
@ -39,5 +39,4 @@ class InboxWorker implements ShouldQueue
{ {
(new Inbox($this->request, $this->profile, $this->payload))->handle(); (new Inbox($this->request, $this->profile, $this->payload))->handle();
} }
} }

View file

@ -2,13 +2,12 @@
namespace App\Jobs\InboxPipeline; namespace App\Jobs\InboxPipeline;
use App\Profile;
use App\Util\ActivityPub\Inbox; use App\Util\ActivityPub\Inbox;
use Illuminate\Bus\Queueable; use Illuminate\Bus\Queueable;
use Illuminate\Queue\SerializesModels;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Queue\ShouldQueue; use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable; use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
class SharedInboxWorker implements ShouldQueue class SharedInboxWorker implements ShouldQueue
{ {

View file

@ -2,19 +2,23 @@
namespace App\Jobs\LikePipeline; namespace App\Jobs\LikePipeline;
use Cache, Log, Redis; use App\Like;
use App\{Like, Notification}; use App\Notification;
use Cache;
use Illuminate\Bus\Queueable; use Illuminate\Bus\Queueable;
use Illuminate\Queue\SerializesModels;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Queue\ShouldQueue; use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable; use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
use Log;
use Redis;
class LikePipeline implements ShouldQueue class LikePipeline implements ShouldQueue
{ {
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels; use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
protected $like; protected $like;
/** /**
* Create a new job instance. * Create a new job instance.
* *
@ -54,8 +58,7 @@ class LikePipeline implements ShouldQueue
} }
try { try {
$notification = new Notification();
$notification = new Notification;
$notification->profile_id = $status->profile_id; $notification->profile_id = $status->profile_id;
$notification->actor_id = $actor->id; $notification->actor_id = $actor->id;
$notification->action = 'like'; $notification->action = 'like';
@ -70,7 +73,6 @@ class LikePipeline implements ShouldQueue
$redis = Redis::connection(); $redis = Redis::connection();
$key = config('cache.prefix').':user.'.$status->profile_id.'.notifications'; $key = config('cache.prefix').':user.'.$status->profile_id.'.notifications';
$redis->lpush($key, $notification->id); $redis->lpush($key, $notification->id);
} catch (Exception $e) { } catch (Exception $e) {
Log::error($e); Log::error($e);
} }

View file

@ -2,13 +2,14 @@
namespace App\Jobs\MentionPipeline; namespace App\Jobs\MentionPipeline;
use Cache, Log, Redis; use App\Mention;
use App\{Mention, Notification, Profile, Status}; use App\Notification;
use App\Status;
use Illuminate\Bus\Queueable; use Illuminate\Bus\Queueable;
use Illuminate\Queue\SerializesModels;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Queue\ShouldQueue; use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable; use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
class MentionPipeline implements ShouldQueue class MentionPipeline implements ShouldQueue
{ {
@ -35,7 +36,6 @@ class MentionPipeline implements ShouldQueue
*/ */
public function handle() public function handle()
{ {
$status = $this->status; $status = $this->status;
$mention = $this->mention; $mention = $this->mention;
$actor = $this->status->profile; $actor = $this->status->profile;
@ -53,8 +53,7 @@ class MentionPipeline implements ShouldQueue
} }
try { try {
$notification = new Notification();
$notification = new Notification;
$notification->profile_id = $target; $notification->profile_id = $target;
$notification->actor_id = $actor->id; $notification->actor_id = $actor->id;
$notification->action = 'mention'; $notification->action = 'mention';
@ -63,10 +62,7 @@ class MentionPipeline implements ShouldQueue
$notification->item_id = $status->id; $notification->item_id = $status->id;
$notification->item_type = "App\Status"; $notification->item_type = "App\Status";
$notification->save(); $notification->save();
} catch (Exception $e) { } catch (Exception $e) {
}
}
} }
} }

View file

@ -2,18 +2,20 @@
namespace App\Jobs\RemoteFollowPipeline; namespace App\Jobs\RemoteFollowPipeline;
use Zttp\Zttp; use App\Jobs\ImageOptimizePipeline\ImageThumbnail;
use Log, Storage; use App\Jobs\StatusPipeline\NewStatusPipeline;
use App\Media;
use App\Status;
use Carbon\Carbon; use Carbon\Carbon;
use Illuminate\Http\File;
use App\{Media, Profile, Status};
use Illuminate\Bus\Queueable; use Illuminate\Bus\Queueable;
use Illuminate\Queue\SerializesModels;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Queue\ShouldQueue; use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable; use Illuminate\Foundation\Bus\Dispatchable;
use App\Jobs\StatusPipeline\NewStatusPipeline; use Illuminate\Http\File;
use App\Jobs\ImageOptimizePipeline\ImageThumbnail; use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
use Log;
use Storage;
use Zttp\Zttp;
class RemoteFollowImportRecent implements ShouldQueue class RemoteFollowImportRecent implements ShouldQueue
{ {
@ -42,7 +44,7 @@ class RemoteFollowImportRecent implements ShouldQueue
'image/jpg', 'image/jpg',
'image/jpeg', 'image/jpeg',
'image/png', 'image/png',
'image/gif' 'image/gif',
]; ];
} }
@ -62,7 +64,7 @@ class RemoteFollowImportRecent implements ShouldQueue
$url = ($url == false) ? $this->actor['outbox'] : $url; $url = ($url == false) ? $this->actor['outbox'] : $url;
$response = Zttp::withHeaders([ $response = Zttp::withHeaders([
'User-Agent' => 'PixelFedBot v0.1 - https://pixelfed.org' 'User-Agent' => 'PixelFedBot v0.1 - https://pixelfed.org',
])->get($url); ])->get($url);
$this->outbox = $response->json(); $this->outbox = $response->json();
@ -76,6 +78,7 @@ class RemoteFollowImportRecent implements ShouldQueue
if (isset($outbox['totalItems']) && $outbox['totalItems'] < 1) { if (isset($outbox['totalItems']) && $outbox['totalItems'] < 1) {
// Skip remote fetch, not enough posts // Skip remote fetch, not enough posts
Log::info('not enough items'); Log::info('not enough items');
return; return;
} }
@ -102,6 +105,7 @@ class RemoteFollowImportRecent implements ShouldQueue
// Mastodon detected // Mastodon detected
Log::info('Mastodon detected...'); Log::info('Mastodon detected...');
$this->nextUrl = $outbox['first']; $this->nextUrl = $outbox['first'];
return $this->fetchOutbox($this->nextUrl); return $this->fetchOutbox($this->nextUrl);
} else { } else {
// Pleroma detected. // Pleroma detected.
@ -110,7 +114,6 @@ class RemoteFollowImportRecent implements ShouldQueue
$orderedItems = isset($outbox['orderedItems']) ? $outbox['orderedItems'] : $outbox['first']['orderedItems']; $orderedItems = isset($outbox['orderedItems']) ? $outbox['orderedItems'] : $outbox['first']['orderedItems'];
} }
foreach ($orderedItems as $item) { foreach ($orderedItems as $item) {
Log::info('Parsing items...'); Log::info('Parsing items...');
$parsed = $this->parseObject($item); $parsed = $this->parseObject($item);
@ -125,7 +128,6 @@ class RemoteFollowImportRecent implements ShouldQueue
$this->mediaCount++; $this->mediaCount++;
$this->fetchOutbox($this->nextUrl); $this->fetchOutbox($this->nextUrl);
} }
} }
public function parseObject($parsed) public function parseObject($parsed)
@ -165,7 +167,7 @@ class RemoteFollowImportRecent implements ShouldQueue
return true; return true;
} }
$status = new Status; $status = new Status();
$status->profile_id = $profile->id; $status->profile_id = $profile->id;
$status->url = $activity['id']; $status->url = $activity['id'];
$status->local = false; $status->local = false;
@ -202,6 +204,7 @@ class RemoteFollowImportRecent implements ShouldQueue
$monthHash = hash('sha1', date('Y').date('m')); $monthHash = hash('sha1', date('Y').date('m'));
$userHash = hash('sha1', $user->id.(string) $user->created_at); $userHash = hash('sha1', $user->id.(string) $user->created_at);
$storagePath = "public/m/{$monthHash}/{$userHash}"; $storagePath = "public/m/{$monthHash}/{$userHash}";
try { try {
$info = pathinfo($url); $info = pathinfo($url);
$img = file_get_contents($url); $img = file_get_contents($url);
@ -209,7 +212,7 @@ class RemoteFollowImportRecent implements ShouldQueue
file_put_contents($file, $img); file_put_contents($file, $img);
$path = Storage::putFile($storagePath, new File($file), 'public'); $path = Storage::putFile($storagePath, new File($file), 'public');
$media = new Media; $media = new Media();
$media->status_id = $status->id; $media->status_id = $status->id;
$media->profile_id = $status->profile_id; $media->profile_id = $status->profile_id;
$media->user_id = null; $media->user_id = null;
@ -225,5 +228,4 @@ class RemoteFollowImportRecent implements ShouldQueue
return false; return false;
} }
} }
} }

View file

@ -2,18 +2,17 @@
namespace App\Jobs\RemoteFollowPipeline; namespace App\Jobs\RemoteFollowPipeline;
use Zttp\Zttp; use App\Jobs\AvatarPipeline\CreateAvatar;
use App\{Profile}; use App\{Profile};
use GuzzleHttp\Client; use GuzzleHttp\Client;
use HttpSignatures\Context; use HttpSignatures\Context;
use HttpSignatures\GuzzleHttpSignatures; use HttpSignatures\GuzzleHttpSignatures;
use App\Jobs\RemoteFollowPipeline\RemoteFollowImportRecent;
use App\Jobs\AvatarPipeline\CreateAvatar;
use Illuminate\Bus\Queueable; use Illuminate\Bus\Queueable;
use Illuminate\Queue\SerializesModels;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Queue\ShouldQueue; use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable; use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
use Zttp\Zttp;
class RemoteFollowPipeline implements ShouldQueue class RemoteFollowPipeline implements ShouldQueue
{ {
@ -49,6 +48,7 @@ class RemoteFollowPipeline implements ShouldQueue
} }
$this->discover($url); $this->discover($url);
return true; return true;
} }
@ -64,7 +64,7 @@ class RemoteFollowPipeline implements ShouldQueue
$client = new Client(['handler' => $handlerStack]); $client = new Client(['handler' => $handlerStack]);
$response = Zttp::withHeaders([ $response = Zttp::withHeaders([
'Accept' => 'application/ld+json; profile="https://www.w3.org/ns/activitystreams"', 'Accept' => 'application/ld+json; profile="https://www.w3.org/ns/activitystreams"',
'User-Agent' => 'PixelFedBot v0.1 - https://pixelfed.org' 'User-Agent' => 'PixelFedBot v0.1 - https://pixelfed.org',
])->get($url); ])->get($url);
$this->response = $response->json(); $this->response = $response->json();
@ -78,7 +78,7 @@ class RemoteFollowPipeline implements ShouldQueue
$username = $res['preferredUsername']; $username = $res['preferredUsername'];
$remoteUsername = "@{$username}@{$domain}"; $remoteUsername = "@{$username}@{$domain}";
$profile = new Profile; $profile = new Profile();
$profile->user_id = null; $profile->user_id = null;
$profile->domain = $domain; $profile->domain = $domain;
$profile->username = $remoteUsername; $profile->username = $remoteUsername;
@ -99,7 +99,7 @@ class RemoteFollowPipeline implements ShouldQueue
$activity = Zttp::withHeaders(['Content-Type' => 'application/activity+json'])->post($url, [ $activity = Zttp::withHeaders(['Content-Type' => 'application/activity+json'])->post($url, [
'type' => 'Follow', 'type' => 'Follow',
'object' => $this->follower->url() 'object' => $this->follower->url(),
]); ]);
} }
} }

View file

@ -2,14 +2,14 @@
namespace App\Jobs\StatusPipeline; namespace App\Jobs\StatusPipeline;
use Cache, Redis; use App\Status;
use App\{Media, Status}; use Cache;
use App\Jobs\ImageOptimizePipeline\ImageOptimize;
use Illuminate\Bus\Queueable; use Illuminate\Bus\Queueable;
use Illuminate\Queue\SerializesModels;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Queue\ShouldQueue; use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable; use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
use Redis;
class NewStatusPipeline implements ShouldQueue class NewStatusPipeline implements ShouldQueue
{ {

View file

@ -2,18 +2,19 @@
namespace App\Jobs\StatusPipeline; namespace App\Jobs\StatusPipeline;
use App\{Media, Status}; use App\Status;
use Illuminate\Bus\Queueable; use Illuminate\Bus\Queueable;
use Illuminate\Queue\SerializesModels;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Queue\ShouldQueue; use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable; use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
class StatusActivityPubDeliver implements ShouldQueue class StatusActivityPubDeliver implements ShouldQueue
{ {
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels; use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
protected $status; protected $status;
/** /**
* Create a new job instance. * Create a new job instance.
* *

View file

@ -2,12 +2,14 @@
namespace App\Jobs\StatusPipeline; namespace App\Jobs\StatusPipeline;
use App\{Media, Notification, StatusHashtag, Status}; use App\Notification;
use App\Status;
use App\StatusHashtag;
use Illuminate\Bus\Queueable; use Illuminate\Bus\Queueable;
use Illuminate\Queue\SerializesModels;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Queue\ShouldQueue; use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable; use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
class StatusDelete implements ShouldQueue class StatusDelete implements ShouldQueue
{ {
@ -55,7 +57,6 @@ class StatusDelete implements ShouldQueue
} }
$media->delete(); $media->delete();
} catch (Exception $e) { } catch (Exception $e) {
} }
} }
$comments = Status::where('in_reply_to_id', $status->id)->get(); $comments = Status::where('in_reply_to_id', $status->id)->get();

View file

@ -2,23 +2,20 @@
namespace App\Jobs\StatusPipeline; namespace App\Jobs\StatusPipeline;
use DB, Cache; use App\Hashtag;
use App\{ use App\Jobs\MentionPipeline\MentionPipeline;
Hashtag, use App\Mention;
Media, use App\Profile;
Mention, use App\Status;
Profile, use App\StatusHashtag;
Status, use App\Util\Lexer\Autolink;
StatusHashtag use App\Util\Lexer\Extractor;
}; use DB;
use App\Util\Lexer\Hashtag as HashtagLexer;
use App\Util\Lexer\{Autolink, Extractor};
use Illuminate\Bus\Queueable; use Illuminate\Bus\Queueable;
use Illuminate\Queue\SerializesModels;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Queue\ShouldQueue; use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable; use Illuminate\Foundation\Bus\Dispatchable;
use App\Jobs\MentionPipeline\MentionPipeline; use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
class StatusEntityLexer implements ShouldQueue class StatusEntityLexer implements ShouldQueue
{ {
@ -109,7 +106,7 @@ class StatusEntityLexer implements ShouldQueue
} }
DB::transaction(function () use ($status, $mentioned) { DB::transaction(function () use ($status, $mentioned) {
$m = new Mention; $m = new Mention();
$m->status_id = $status->id; $m->status_id = $status->id;
$m->profile_id = $mentioned->id; $m->profile_id = $mentioned->id;
$m->save(); $m->save();
@ -118,5 +115,4 @@ class StatusEntityLexer implements ShouldQueue
}); });
} }
} }
} }

View file

@ -29,6 +29,7 @@ class Like extends Model
public function toText() public function toText()
{ {
$actorName = $this->actor->username; $actorName = $this->actor->username;
return "{$actorName} ".__('notification.likedPhoto'); return "{$actorName} ".__('notification.likedPhoto');
} }
@ -36,6 +37,7 @@ class Like extends Model
{ {
$actorName = $this->actor->username; $actorName = $this->actor->username;
$actorUrl = $this->actor->url(); $actorUrl = $this->actor->url();
return "<a href='{$actorUrl}' class='profile-link'>{$actorName}</a> ". return "<a href='{$actorUrl}' class='profile-link'>{$actorName}</a> ".
__('notification.likedPhoto'); __('notification.likedPhoto');
} }

View file

@ -6,7 +6,6 @@ use App\EmailVerification;
use Illuminate\Bus\Queueable; use Illuminate\Bus\Queueable;
use Illuminate\Mail\Mailable; use Illuminate\Mail\Mailable;
use Illuminate\Queue\SerializesModels; use Illuminate\Queue\SerializesModels;
use Illuminate\Contracts\Queue\ShouldQueue;
class ConfirmEmail extends Mailable class ConfirmEmail extends Mailable
{ {

View file

@ -2,9 +2,9 @@
namespace App; namespace App;
use Storage;
use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes; use Illuminate\Database\Eloquent\SoftDeletes;
use Storage;
class Media extends Model class Media extends Model
{ {
@ -21,6 +21,7 @@ class Media extends Model
{ {
$path = $this->media_path; $path = $this->media_path;
$url = Storage::url($path); $url = Storage::url($path);
return url($url); return url($url);
} }
@ -28,6 +29,7 @@ class Media extends Model
{ {
$path = $this->thumbnail_path; $path = $this->thumbnail_path;
$url = Storage::url($path); $url = Storage::url($path);
return url($url); return url($url);
} }
} }

View file

@ -29,6 +29,7 @@ class Mention extends Model
public function toText() public function toText()
{ {
$actorName = $this->status->profile->username; $actorName = $this->status->profile->username;
return "{$actorName} ".__('notification.mentionedYou'); return "{$actorName} ".__('notification.mentionedYou');
} }
@ -36,6 +37,7 @@ class Mention extends Model
{ {
$actorName = $this->status->profile->username; $actorName = $this->status->profile->username;
$actorUrl = $this->status->profile->url(); $actorUrl = $this->status->profile->url();
return "<a href='{$actorUrl}' class='profile-link'>{$actorName}</a> ". return "<a href='{$actorUrl}' class='profile-link'>{$actorName}</a> ".
__('notification.mentionedYou'); __('notification.mentionedYou');
} }

View file

@ -35,5 +35,4 @@ class Notification extends Model
{ {
return $this->belongsTo(Status::class, 'item_id', 'id'); return $this->belongsTo(Status::class, 'item_id', 'id');
} }
} }

View file

@ -2,8 +2,10 @@
namespace App\Observers; namespace App\Observers;
use App\{Profile, User, UserSetting};
use App\Jobs\AvatarPipeline\CreateAvatar; use App\Jobs\AvatarPipeline\CreateAvatar;
use App\Profile;
use App\User;
use App\UserSetting;
class UserObserver class UserObserver
{ {
@ -11,19 +13,20 @@ class UserObserver
* Listen to the User created event. * Listen to the User created event.
* *
* @param \App\User $user * @param \App\User $user
*
* @return void * @return void
*/ */
public function saved(User $user) public function saved(User $user)
{ {
if (empty($user->profile)) { if (empty($user->profile)) {
$profile = new Profile; $profile = new Profile();
$profile->user_id = $user->id; $profile->user_id = $user->id;
$profile->username = $user->username; $profile->username = $user->username;
$profile->name = $user->name; $profile->name = $user->name;
$pkiConfig = [ $pkiConfig = [
"digest_alg" => "sha512", 'digest_alg' => 'sha512',
"private_key_bits" => 2048, 'private_key_bits' => 2048,
"private_key_type" => OPENSSL_KEYTYPE_RSA, 'private_key_type' => OPENSSL_KEYTYPE_RSA,
]; ];
$pki = openssl_pkey_new($pkiConfig); $pki = openssl_pkey_new($pkiConfig);
openssl_pkey_export($pki, $pki_private); openssl_pkey_export($pki, $pki_private);
@ -38,10 +41,9 @@ class UserObserver
} }
if (empty($user->settings)) { if (empty($user->settings)) {
$settings = new UserSetting; $settings = new UserSetting();
$settings->user_id = $user->id; $settings->user_id = $user->id;
$settings->save(); $settings->save();
} }
} }
} }

View file

@ -2,10 +2,12 @@
namespace App; namespace App;
use Auth, Cache, Storage;
use App\Util\Lexer\PrettyNumber; use App\Util\Lexer\PrettyNumber;
use Auth;
use Cache;
use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes; use Illuminate\Database\Eloquent\SoftDeletes;
use Storage;
class Profile extends Model class Profile extends Model
{ {
@ -50,6 +52,7 @@ class Profile extends Model
public function emailUrl() public function emailUrl()
{ {
$domain = parse_url(config('app.url'), PHP_URL_HOST); $domain = parse_url(config('app.url'), PHP_URL_HOST);
return $this->username.'@'.$domain; return $this->username.'@'.$domain;
} }
@ -81,7 +84,7 @@ class Profile extends Model
public function following() public function following()
{ {
return $this->belongsToMany( return $this->belongsToMany(
Profile::class, self::class,
'followers', 'followers',
'profile_id', 'profile_id',
'following_id' 'following_id'
@ -91,7 +94,7 @@ class Profile extends Model
public function followers() public function followers()
{ {
return $this->belongsToMany( return $this->belongsToMany(
Profile::class, self::class,
'followers', 'followers',
'following_id', 'following_id',
'profile_id' 'profile_id'
@ -126,7 +129,7 @@ class Profile extends Model
public function avatar() public function avatar()
{ {
return $this->hasOne(Avatar::class)->withDefault([ return $this->hasOne(Avatar::class)->withDefault([
'media_path' => 'public/avatars/default.png' 'media_path' => 'public/avatars/default.png',
]); ]);
} }
@ -136,8 +139,10 @@ class Profile extends Model
$path = optional($this->avatar)->media_path; $path = optional($this->avatar)->media_path;
$version = hash('sha1', $this->avatar->created_at); $version = hash('sha1', $this->avatar->created_at);
$path = "{$path}?v={$version}"; $path = "{$path}?v={$version}";
return url(Storage::url($path)); return url(Storage::url($path));
}); });
return $url; return $url;
} }
@ -168,7 +173,7 @@ class Profile extends Model
->pluck('following_id'); ->pluck('following_id');
$recommended = []; $recommended = [];
foreach ($following as $follow) { foreach ($following as $follow) {
$recommended[] = Profile::findOrFail($follow); $recommended[] = self::findOrFail($follow);
} }
return $recommended; return $recommended;
@ -179,6 +184,7 @@ class Profile extends Model
if ($this->remote_url) { if ($this->remote_url) {
return; return;
} }
return $this->permalink('#main-key'); return $this->permalink('#main-key');
} }
} }

View file

@ -2,9 +2,10 @@
namespace App\Providers; namespace App\Providers;
use App\User;
use Auth, Horizon;
use App\Observers\UserObserver; use App\Observers\UserObserver;
use App\User;
use Auth;
use Horizon;
use Illuminate\Support\Facades\Blade; use Illuminate\Support\Facades\Blade;
use Illuminate\Support\Facades\Schema; use Illuminate\Support\Facades\Schema;
use Illuminate\Support\ServiceProvider; use Illuminate\Support\ServiceProvider;
@ -28,14 +29,16 @@ class AppServiceProvider extends ServiceProvider
Blade::directive('prettyNumber', function ($expression) { Blade::directive('prettyNumber', function ($expression) {
$num = $expression; $num = $expression;
$abbrevs = array(12 => "T", 9 => "B", 6 => "M", 3 => "K", 0 => ""); $abbrevs = [12 => 'T', 9 => 'B', 6 => 'M', 3 => 'K', 0 => ''];
foreach ($abbrevs as $exponent => $abbrev) { foreach ($abbrevs as $exponent => $abbrev) {
if ($expression >= pow(10, $exponent)) { if ($expression >= pow(10, $exponent)) {
$display_num = $expression / pow(10, $exponent); $display_num = $expression / pow(10, $exponent);
$num = number_format($display_num, 0).$abbrev; $num = number_format($display_num, 0).$abbrev;
return "<?php echo '$num'; ?>"; return "<?php echo '$num'; ?>";
} }
} }
return "<?php echo $num; ?>"; return "<?php echo $num; ?>";
}); });
@ -46,13 +49,16 @@ class AppServiceProvider extends ServiceProvider
$units = $short ? $units = $short ?
['B', 'k', 'M', 'G', 'T', 'P', 'E', 'Z', 'Y'] : ['B', 'k', 'M', 'G', 'T', 'P', 'E', 'Z', 'Y'] :
['B', 'kB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB']; ['B', 'kB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'];
for($i = 0; ($size / 1024) > 0.9; $i++, $size /= 1024) {} for ($i = 0; ($size / 1024) > 0.9; $i++, $size /= 1024) {
}
$res = round($size, $precision).$units[$i]; $res = round($size, $precision).$units[$i];
return "<?php echo '$res'; ?>"; return "<?php echo '$res'; ?>";
}); });
Blade::directive('maxFileSize', function () { Blade::directive('maxFileSize', function () {
$value = config('pixelfed.max_photo_size'); $value = config('pixelfed.max_photo_size');
return \App\Util\Lexer\PrettyNumber::size($value, true); return \App\Util\Lexer\PrettyNumber::size($value, true);
}); });
} }

View file

@ -2,7 +2,6 @@
namespace App\Providers; namespace App\Providers;
use Illuminate\Support\Facades\Gate;
use Illuminate\Foundation\Support\Providers\AuthServiceProvider as ServiceProvider; use Illuminate\Foundation\Support\Providers\AuthServiceProvider as ServiceProvider;
class AuthServiceProvider extends ServiceProvider class AuthServiceProvider extends ServiceProvider

View file

@ -2,8 +2,8 @@
namespace App\Providers; namespace App\Providers;
use Illuminate\Support\ServiceProvider;
use Illuminate\Support\Facades\Broadcast; use Illuminate\Support\Facades\Broadcast;
use Illuminate\Support\ServiceProvider;
class BroadcastServiceProvider extends ServiceProvider class BroadcastServiceProvider extends ServiceProvider
{ {

View file

@ -2,8 +2,8 @@
namespace App\Providers; namespace App\Providers;
use Illuminate\Support\Facades\Event;
use Illuminate\Foundation\Support\Providers\EventServiceProvider as ServiceProvider; use Illuminate\Foundation\Support\Providers\EventServiceProvider as ServiceProvider;
use Illuminate\Support\Facades\Event;
class EventServiceProvider extends ServiceProvider class EventServiceProvider extends ServiceProvider
{ {

View file

@ -2,8 +2,8 @@
namespace App\Providers; namespace App\Providers;
use Illuminate\Support\Facades\Route;
use Illuminate\Foundation\Support\Providers\RouteServiceProvider as ServiceProvider; use Illuminate\Foundation\Support\Providers\RouteServiceProvider as ServiceProvider;
use Illuminate\Support\Facades\Route;
class RouteServiceProvider extends ServiceProvider class RouteServiceProvider extends ServiceProvider
{ {

View file

@ -30,6 +30,7 @@ class Report extends Model
$column = 'id'; $column = 'id';
break; break;
} }
return (new $class())->where($column, $this->object_id)->firstOrFail(); return (new $class())->where($column, $this->object_id)->firstOrFail();
} }

View file

@ -2,9 +2,10 @@
namespace App; namespace App;
use Auth, Storage; use Auth;
use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes; use Illuminate\Database\Eloquent\SoftDeletes;
use Storage;
class Status extends Model class Status extends Model
{ {
@ -36,6 +37,7 @@ class Status extends Model
{ {
$media = $this->firstMedia(); $media = $this->firstMedia();
$type = explode('/', $media->mime); $type = explode('/', $media->mime);
return $type[0]; return $type[0];
} }
@ -44,8 +46,9 @@ class Status extends Model
$type = $this->viewType(); $type = $this->viewType();
$is_nsfw = !$showNsfw ? $this->is_nsfw : false; $is_nsfw = !$showNsfw ? $this->is_nsfw : false;
if ($this->media->count() == 0 || $is_nsfw || $type != 'image') { if ($this->media->count() == 0 || $is_nsfw || $type != 'image') {
return "data:image/gif;base64,R0lGODlhAQABAIAAAMLCwgAAACH5BAAAAAAALAAAAAABAAEAAAICRAEAOw=="; return 'data:image/gif;base64,R0lGODlhAQABAIAAAMLCwgAAACH5BAAAAAAALAAAAAABAAEAAAICRAEAOw==';
} }
return url(Storage::url($this->firstMedia()->thumbnail_path)); return url(Storage::url($this->firstMedia()->thumbnail_path));
} }
@ -58,6 +61,7 @@ class Status extends Model
$pid = $this->in_reply_to_id; $pid = $this->in_reply_to_id;
$path = config('app.url')."/p/{$username}/{$pid}/c/{$id}"; $path = config('app.url')."/p/{$username}/{$pid}/c/{$id}";
} }
return url($path); return url($path);
} }
@ -66,6 +70,7 @@ class Status extends Model
$id = $this->id; $id = $this->id;
$username = $this->profile->username; $username = $this->profile->username;
$path = config('app.url')."/p/{$username}/{$id}{$suffix}"; $path = config('app.url')."/p/{$username}/{$id}{$suffix}";
return url($path); return url($path);
} }
@ -80,6 +85,7 @@ class Status extends Model
$path = $media->media_path; $path = $media->media_path;
$hash = is_null($media->processed_at) ? md5('unprocessed') : md5($media->created_at); $hash = is_null($media->processed_at) ? md5('unprocessed') : md5($media->created_at);
$url = Storage::url($path)."?v={$hash}"; $url = Storage::url($path)."?v={$hash}";
return url($url); return url($url);
} }
@ -91,12 +97,13 @@ class Status extends Model
public function liked() : bool public function liked() : bool
{ {
$profile = Auth::user()->profile; $profile = Auth::user()->profile;
return Like::whereProfileId($profile->id)->whereStatusId($this->id)->count(); return Like::whereProfileId($profile->id)->whereStatusId($this->id)->count();
} }
public function comments() public function comments()
{ {
return $this->hasMany(Status::class, 'in_reply_to_id'); return $this->hasMany(self::class, 'in_reply_to_id');
} }
public function bookmarked() public function bookmarked()
@ -105,25 +112,27 @@ class Status extends Model
return 0; return 0;
} }
$profile = Auth::user()->profile; $profile = Auth::user()->profile;
return Bookmark::whereProfileId($profile->id)->whereStatusId($this->id)->count(); return Bookmark::whereProfileId($profile->id)->whereStatusId($this->id)->count();
} }
public function shares() public function shares()
{ {
return $this->hasMany(Status::class, 'reblog_of_id'); return $this->hasMany(self::class, 'reblog_of_id');
} }
public function shared() : bool public function shared() : bool
{ {
$profile = Auth::user()->profile; $profile = Auth::user()->profile;
return Status::whereProfileId($profile->id)->whereReblogOfId($this->id)->count();
return self::whereProfileId($profile->id)->whereReblogOfId($this->id)->count();
} }
public function parent() public function parent()
{ {
$parent = $this->in_reply_to_id ?? $this->reblog_of_id; $parent = $this->in_reply_to_id ?? $this->reblog_of_id;
if (!empty($parent)) { if (!empty($parent)) {
return Status::findOrFail($parent); return self::findOrFail($parent);
} }
} }
@ -167,23 +176,25 @@ class Status extends Model
$mediaCollection = []; $mediaCollection = [];
foreach ($media as $image) { foreach ($media as $image) {
$mediaCollection[] = [ $mediaCollection[] = [
"type" => "Link", 'type' => 'Link',
"href" => $image->url(), 'href' => $image->url(),
"mediaType" => $image->mime 'mediaType' => $image->mime,
]; ];
} }
$obj = [ $obj = [
"@context" => "https://www.w3.org/ns/activitystreams", '@context' => 'https://www.w3.org/ns/activitystreams',
"type" => "Image", 'type' => 'Image',
"name" => null, 'name' => null,
"url" => $mediaCollection 'url' => $mediaCollection,
]; ];
return $obj; return $obj;
} }
public function replyToText() public function replyToText()
{ {
$actorName = $this->profile->username; $actorName = $this->profile->username;
return "{$actorName} ".__('notification.commented'); return "{$actorName} ".__('notification.commented');
} }
@ -191,6 +202,7 @@ class Status extends Model
{ {
$actorName = $this->profile->username; $actorName = $this->profile->username;
$actorUrl = $this->profile->url(); $actorUrl = $this->profile->url();
return "<a href='{$actorUrl}' class='profile-link'>{$actorName}</a> ". return "<a href='{$actorUrl}' class='profile-link'>{$actorName}</a> ".
__('notification.commented'); __('notification.commented');
} }

View file

@ -7,7 +7,6 @@ use League\Fractal;
class ProfileOutbox extends Fractal\TransformerAbstract class ProfileOutbox extends Fractal\TransformerAbstract
{ {
public function transform(Profile $profile) public function transform(Profile $profile)
{ {
$count = $profile->statuses()->count(); $count = $profile->statuses()->count();
@ -19,7 +18,7 @@ class ProfileOutbox extends Fractal\TransformerAbstract
'actor' => $i->profile->url(), 'actor' => $i->profile->url(),
'published' => $i->created_at->toISO8601String(), 'published' => $i->created_at->toISO8601String(),
'to' => [ 'to' => [
'https://www.w3.org/ns/activitystreams#Public' 'https://www.w3.org/ns/activitystreams#Public',
], ],
'cc' => [ 'cc' => [
$i->profile->permalink('/followers'), $i->profile->permalink('/followers'),
@ -41,7 +40,7 @@ class ProfileOutbox extends Fractal\TransformerAbstract
'attributedTo' => $i->profile->permalink(), 'attributedTo' => $i->profile->permalink(),
'to' => [ 'to' => [
// TODO: handle proper scope // TODO: handle proper scope
'https://www.w3.org/ns/activitystreams#Public' 'https://www.w3.org/ns/activitystreams#Public',
], ],
'cc' => [ 'cc' => [
// TODO: add cc's // TODO: add cc's
@ -57,12 +56,13 @@ class ProfileOutbox extends Fractal\TransformerAbstract
'type' => 'Document', 'type' => 'Document',
'mediaType' => $i->firstMedia()->mime, 'mediaType' => $i->firstMedia()->mime,
'url' => $i->firstMedia()->url(), 'url' => $i->firstMedia()->url(),
'name' => null 'name' => null,
] ],
],
'tag' => [],
], ],
'tag' => []
]
]; ];
return $item; return $item;
}); });
@ -71,8 +71,7 @@ class ProfileOutbox extends Fractal\TransformerAbstract
'id' => $profile->permalink('/outbox'), 'id' => $profile->permalink('/outbox'),
'type' => 'OrderedCollection', 'type' => 'OrderedCollection',
'totalItems' => $count, 'totalItems' => $count,
'orderedItems' => $statuses 'orderedItems' => $statuses,
]; ];
} }
} }

View file

@ -7,7 +7,6 @@ use League\Fractal;
class ProfileTransformer extends Fractal\TransformerAbstract class ProfileTransformer extends Fractal\TransformerAbstract
{ {
public function transform(Profile $profile) public function transform(Profile $profile)
{ {
return [ return [
@ -15,11 +14,11 @@ class ProfileTransformer extends Fractal\TransformerAbstract
'https://www.w3.org/ns/activitystreams', 'https://www.w3.org/ns/activitystreams',
'https://w3id.org/security/v1', 'https://w3id.org/security/v1',
[ [
"manuallyApprovesFollowers" => "as:manuallyApprovesFollowers", 'manuallyApprovesFollowers' => 'as:manuallyApprovesFollowers',
"featured" => [ 'featured' => [
"https://pixelfed.org/ns#featured" => ["@type" => "@id"], 'https://pixelfed.org/ns#featured' => ['@type' => '@id'],
] ],
] ],
], ],
'id' => $profile->permalink(), 'id' => $profile->permalink(),
'type' => 'Person', 'type' => 'Person',
@ -38,17 +37,16 @@ class ProfileTransformer extends Fractal\TransformerAbstract
'publicKey' => [ 'publicKey' => [
'id' => $profile->permalink().'#main-key', 'id' => $profile->permalink().'#main-key',
'owner' => $profile->permalink(), 'owner' => $profile->permalink(),
'publicKeyPem' => $profile->public_key 'publicKeyPem' => $profile->public_key,
], ],
'endpoints' => [ 'endpoints' => [
'sharedInbox' => config('routes.api.sharedInbox') 'sharedInbox' => config('routes.api.sharedInbox'),
], ],
'icon' => [ 'icon' => [
'type' => 'Image', 'type' => 'Image',
'mediaType' => 'image/jpeg', 'mediaType' => 'image/jpeg',
'url' => $profile->avatarUrl() 'url' => $profile->avatarUrl(),
] ],
]; ];
} }
} }

View file

@ -2,12 +2,11 @@
namespace App\Transformer\ActivityPub; namespace App\Transformer\ActivityPub;
use App\{Profile, Status}; use App\Status;
use League\Fractal; use League\Fractal;
class StatusTransformer extends Fractal\TransformerAbstract class StatusTransformer extends Fractal\TransformerAbstract
{ {
public function transform(Status $status) public function transform(Status $status)
{ {
return [ return [
@ -15,11 +14,11 @@ class StatusTransformer extends Fractal\TransformerAbstract
'https://www.w3.org/ns/activitystreams', 'https://www.w3.org/ns/activitystreams',
'https://w3id.org/security/v1', 'https://w3id.org/security/v1',
[ [
"manuallyApprovesFollowers" => "as:manuallyApprovesFollowers", 'manuallyApprovesFollowers' => 'as:manuallyApprovesFollowers',
"featured" => [ 'featured' => [
"https://pixelfed.org/ns#featured" => ["@type" => "@id"], 'https://pixelfed.org/ns#featured' => ['@type' => '@id'],
] ],
] ],
], ],
'id' => $status->url(), 'id' => $status->url(),
@ -37,7 +36,7 @@ class StatusTransformer extends Fractal\TransformerAbstract
'attributedTo' => $status->profile->permalink(), 'attributedTo' => $status->profile->permalink(),
'to' => [ 'to' => [
// TODO: handle proper scope // TODO: handle proper scope
'https://www.w3.org/ns/activitystreams#Public' 'https://www.w3.org/ns/activitystreams#Public',
], ],
'cc' => [ 'cc' => [
// TODO: add cc's // TODO: add cc's
@ -51,11 +50,10 @@ class StatusTransformer extends Fractal\TransformerAbstract
'type' => 'Document', 'type' => 'Document',
'mediaType' => $media->mime, 'mediaType' => $media->mime,
'url' => $media->url(), 'url' => $media->url(),
'name' => null 'name' => null,
]; ];
}), }),
'tag' => [] 'tag' => [],
]; ];
} }
} }

View file

@ -27,7 +27,7 @@ class AccountTransformer extends Fractal\TransformerAbstract
'header_static' => '', 'header_static' => '',
'moved' => null, 'moved' => null,
'fields' => null, 'fields' => null,
'bot' => null 'bot' => null,
]; ];
} }
} }

View file

@ -10,7 +10,7 @@ class ApplicationTransformer extends Fractal\TransformerAbstract
{ {
return [ return [
'name' => '', 'name' => '',
'website' => null 'website' => null,
]; ];
} }
} }

View file

@ -4,7 +4,6 @@ namespace App\Transformer\Api;
use App\Hashtag; use App\Hashtag;
use League\Fractal; use League\Fractal;
use League\Fractal\Serializer\ArraySerializer;
class HashtagTransformer extends Fractal\TransformerAbstract class HashtagTransformer extends Fractal\TransformerAbstract
{ {

View file

@ -4,7 +4,6 @@ namespace App\Transformer\Api;
use App\Media; use App\Media;
use League\Fractal; use League\Fractal;
use League\Fractal\Serializer\ArraySerializer;
class MediaTransformer extends Fractal\TransformerAbstract class MediaTransformer extends Fractal\TransformerAbstract
{ {
@ -18,7 +17,7 @@ class MediaTransformer extends Fractal\TransformerAbstract
'preview_url' => $media->thumbnailUrl(), 'preview_url' => $media->thumbnailUrl(),
'text_url' => null, 'text_url' => null,
'meta' => null, 'meta' => null,
'description' => null 'description' => null,
]; ];
} }
} }

View file

@ -11,7 +11,7 @@ class StatusTransformer extends Fractal\TransformerAbstract
'account', 'account',
'mentions', 'mentions',
'media_attachments', 'media_attachments',
'tags' 'tags',
]; ];
public function transform(Status $status) public function transform(Status $status)
@ -39,31 +39,35 @@ class StatusTransformer extends Fractal\TransformerAbstract
'visibility' => $status->visibility, 'visibility' => $status->visibility,
'application' => null, 'application' => null,
'language' => null, 'language' => null,
'pinned' => null 'pinned' => null,
]; ];
} }
public function includeAccount(Status $status) public function includeAccount(Status $status)
{ {
$account = $status->profile; $account = $status->profile;
return $this->item($account, new AccountTransformer);
return $this->item($account, new AccountTransformer());
} }
public function includeMentions(Status $status) public function includeMentions(Status $status)
{ {
$mentions = $status->mentions; $mentions = $status->mentions;
return $this->collection($mentions, new MentionTransformer);
return $this->collection($mentions, new MentionTransformer());
} }
public function includeMediaAttachments(Status $status) public function includeMediaAttachments(Status $status)
{ {
$media = $status->media; $media = $status->media;
return $this->collection($media, new MediaTransformer);
return $this->collection($media, new MediaTransformer());
} }
public function includeTags(Status $status) public function includeTags(Status $status)
{ {
$tags = $status->hashtags; $tags = $status->hashtags;
return $this->collection($tags, new HashtagTransformer);
return $this->collection($tags, new HashtagTransformer());
} }
} }

View file

@ -2,9 +2,9 @@
namespace App; namespace App;
use Illuminate\Notifications\Notifiable;
use Illuminate\Database\Eloquent\SoftDeletes; use Illuminate\Database\Eloquent\SoftDeletes;
use Illuminate\Foundation\Auth\User as Authenticatable; use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
class User extends Authenticatable class User extends Authenticatable
{ {

View file

@ -10,6 +10,6 @@ class UserFilter extends Model
'user_id', 'user_id',
'filterable_id', 'filterable_id',
'filterable_type', 'filterable_type',
'filter_type' 'filter_type',
]; ];
} }

View file

@ -4,10 +4,10 @@ namespace App\Util\ActivityPub\Concern;
use Zttp\Zttp; use Zttp\Zttp;
class HTTPSignature { class HTTPSignature
{
protected $localhosts = [ protected $localhosts = [
'127.0.0.1', 'localhost', '::1' '127.0.0.1', 'localhost', '::1',
]; ];
public $profile; public $profile;
public $is_url; public $is_url;
@ -20,6 +20,7 @@ class HTTPSignature {
} }
$url = $this->profile; $url = $this->profile;
try { try {
$url = filter_var($url, FILTER_VALIDATE_URL); $url = filter_var($url, FILTER_VALIDATE_URL);
$parsed = parse_url($url, PHP_URL_HOST); $parsed = parse_url($url, PHP_URL_HOST);
@ -29,6 +30,7 @@ class HTTPSignature {
} catch (Exception $e) { } catch (Exception $e) {
return false; return false;
} }
return true; return true;
} }
@ -48,7 +50,7 @@ class HTTPSignature {
$url = $this->profile; $url = $this->profile;
$res = Zttp::timeout(30)->withHeaders([ $res = Zttp::timeout(30)->withHeaders([
'Accept' => 'application/ld+json; profile="https://www.w3.org/ns/activitystreams"', 'Accept' => 'application/ld+json; profile="https://www.w3.org/ns/activitystreams"',
'User-Agent' => 'PixelFedBot v0.1 - https://pixelfed.org' 'User-Agent' => 'PixelFedBot v0.1 - https://pixelfed.org',
])->get($url); ])->get($url);
$actor = json_decode($res->getBody(), true); $actor = json_decode($res->getBody(), true);
} catch (Exception $e) { } catch (Exception $e) {
@ -74,21 +76,19 @@ class HTTPSignature {
'Accept' => 'application/ld+json; profile="https://www.w3.org/ns/activitystreams"', 'Accept' => 'application/ld+json; profile="https://www.w3.org/ns/activitystreams"',
'Date' => date('D, d M Y h:i:s').' GMT', 'Date' => date('D, d M Y h:i:s').' GMT',
'Content-Type' => 'application/activity+json', 'Content-Type' => 'application/activity+json',
'User-Agent' => 'PixelFedBot - https://pixelfed.org' 'User-Agent' => 'PixelFedBot - https://pixelfed.org',
]; ];
$response = $client->post($url, [ $response = $client->post($url, [
'options' => [ 'options' => [
'allow_redirects' => false, 'allow_redirects' => false,
'verify' => true, 'verify' => true,
'timeout' => 30 'timeout' => 30,
], ],
'headers' => $headers, 'headers' => $headers,
'body' => $body 'body' => $body,
]); ]);
return $response->getBody(); return $response->getBody();
} }
} }

View file

@ -2,10 +2,10 @@
namespace App\Util\ActivityPub; namespace App\Util\ActivityPub;
use \Zttp\Zttp; use Zttp\Zttp;
class DiscoverActor {
class DiscoverActor
{
protected $url; protected $url;
protected $response; protected $response;
@ -18,9 +18,10 @@ class DiscoverActor {
{ {
$res = Zttp::withHeaders([ $res = Zttp::withHeaders([
'Accept' => 'application/ld+json; profile="https://www.w3.org/ns/activitystreams"', 'Accept' => 'application/ld+json; profile="https://www.w3.org/ns/activitystreams"',
'User-Agent' => 'PixelFedBot - https://pixelfed.org' 'User-Agent' => 'PixelFedBot - https://pixelfed.org',
])->get($this->url); ])->get($this->url);
$this->response = $res->body(); $this->response = $res->body();
return $this; return $this;
} }
@ -45,5 +46,4 @@ class DiscoverActor {
return $res; return $res;
} }
} }

View file

@ -2,11 +2,11 @@
namespace App\Util\ActivityPub; namespace App\Util\ActivityPub;
use App\Jobs\AvatarPipeline\CreateAvatar; use App\Like;
use App\{Follower, Like, Profile, Like, Status, User}; use App\Profile;
class Inbox {
class Inbox
{
protected $request; protected $request;
protected $profile; protected $profile;
protected $payload; protected $payload;
@ -58,7 +58,6 @@ class Inbox {
{ {
$actor = $this->payload['object']; $actor = $this->payload['object'];
$target = $this->profile; $target = $this->profile;
} }
public function actorFirstOrCreate($actorUrl) public function actorFirstOrCreate($actorUrl)
@ -73,7 +72,7 @@ class Inbox {
$username = $res['preferredUsername']; $username = $res['preferredUsername'];
$remoteUsername = "@{$username}@{$domain}"; $remoteUsername = "@{$username}@{$domain}";
$profile = new Profile; $profile = new Profile();
$profile->user_id = null; $profile->user_id = null;
$profile->domain = $domain; $profile->domain = $domain;
$profile->username = $remoteUsername; $profile->username = $remoteUsername;
@ -82,7 +81,5 @@ class Inbox {
$profile->sharedInbox = $res['endpoints']['sharedInbox']; $profile->sharedInbox = $res['endpoints']['sharedInbox'];
$profile->remote_url = $res['url']; $profile->remote_url = $res['url'];
$profile->save(); $profile->save();
} }
} }

View file

@ -12,7 +12,7 @@ class HashPreprocessor implements \Bitverse\Identicon\Preprocessor\PreprocessorI
} }
/** /**
* {@inheritDoc} * {@inheritdoc}
*/ */
public function process($string) public function process($string)
{ {

View file

@ -5,17 +5,12 @@
* @author Nick Pope <nick@nickpope.me.uk> * @author Nick Pope <nick@nickpope.me.uk>
* @copyright Copyright © 2010, Mike Cochrane, Nick Pope * @copyright Copyright © 2010, Mike Cochrane, Nick Pope
* @license http://www.apache.org/licenses/LICENSE-2.0 Apache License v2.0 * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License v2.0
* @package Twitter.Text
*/ */
namespace App\Util\Lexer; namespace App\Util\Lexer;
use App\Util\Lexer\Regex;
use App\Util\Lexer\Extractor;
use App\Util\Lexer\StringUtils;
/** /**
* Twitter Autolink Class * Twitter Autolink Class.
* *
* Parses tweets and generates HTML anchor tags around URLs, usernames, * Parses tweets and generates HTML anchor tags around URLs, usernames,
* username/list pairs and hashtags. * username/list pairs and hashtags.
@ -28,11 +23,9 @@ use App\Util\Lexer\StringUtils;
* @author Nick Pope <nick@nickpope.me.uk> * @author Nick Pope <nick@nickpope.me.uk>
* @copyright Copyright © 2010, Mike Cochrane, Nick Pope * @copyright Copyright © 2010, Mike Cochrane, Nick Pope
* @license http://www.apache.org/licenses/LICENSE-2.0 Apache License v2.0 * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License v2.0
* @package Twitter.Text
*/ */
class Autolink extends Regex class Autolink extends Regex
{ {
/** /**
* CSS class for auto-linked URLs. * CSS class for auto-linked URLs.
* *
@ -134,14 +127,13 @@ class Autolink extends Regex
protected $target = '_blank'; protected $target = '_blank';
/** /**
* attribute for invisible span tag * attribute for invisible span tag.
* *
* @var string * @var string
*/ */
protected $invisibleTagAttrs = "style='position:absolute;left:-9999px;'"; protected $invisibleTagAttrs = "style='position:absolute;left:-9999px;'";
/** /**
*
* @var Extractor * @var Extractor
*/ */
protected $extractor = null; protected $extractor = null;
@ -187,7 +179,7 @@ class Autolink extends Regex
$this->extractor = Extractor::create(); $this->extractor = Extractor::create();
$this->url_base_user = config('app.url').'/'; $this->url_base_user = config('app.url').'/';
$this->url_base_list = config('app.url').'/'; $this->url_base_list = config('app.url').'/';
$this->url_base_hash = config('app.url') . "/discover/tags/"; $this->url_base_hash = config('app.url').'/discover/tags/';
$this->url_base_cash = config('app.url').'/search?q=%24'; $this->url_base_cash = config('app.url').'/search?q=%24';
} }
@ -211,6 +203,7 @@ class Autolink extends Regex
public function setURLClass($v) public function setURLClass($v)
{ {
$this->class_url = trim($v); $this->class_url = trim($v);
return $this; return $this;
} }
@ -234,6 +227,7 @@ class Autolink extends Regex
public function setUsernameClass($v) public function setUsernameClass($v)
{ {
$this->class_user = trim($v); $this->class_user = trim($v);
return $this; return $this;
} }
@ -257,6 +251,7 @@ class Autolink extends Regex
public function setListClass($v) public function setListClass($v)
{ {
$this->class_list = trim($v); $this->class_list = trim($v);
return $this; return $this;
} }
@ -280,6 +275,7 @@ class Autolink extends Regex
public function setHashtagClass($v) public function setHashtagClass($v)
{ {
$this->class_hash = trim($v); $this->class_hash = trim($v);
return $this; return $this;
} }
@ -303,6 +299,7 @@ class Autolink extends Regex
public function setCashtagClass($v) public function setCashtagClass($v)
{ {
$this->class_cash = trim($v); $this->class_cash = trim($v);
return $this; return $this;
} }
@ -326,6 +323,7 @@ class Autolink extends Regex
public function setNoFollow($v) public function setNoFollow($v)
{ {
$this->nofollow = $v; $this->nofollow = $v;
return $this; return $this;
} }
@ -359,6 +357,7 @@ class Autolink extends Regex
public function setExternal($v) public function setExternal($v)
{ {
$this->external = $v; $this->external = $v;
return $this; return $this;
} }
@ -390,15 +389,18 @@ class Autolink extends Regex
public function setTarget($v) public function setTarget($v)
{ {
$this->target = trim($v); $this->target = trim($v);
return $this; return $this;
} }
/** /**
* Autolink with entities * Autolink with entities.
* *
* @param string $tweet * @param string $tweet
* @param array $entities * @param array $entities
*
* @return string * @return string
*
* @since 1.1.0 * @since 1.1.0
*/ */
public function autoLinkEntities($tweet = null, $entities = null) public function autoLinkEntities($tweet = null, $entities = null)
@ -428,6 +430,7 @@ class Autolink extends Regex
$beginIndex = $entity['indices'][1]; $beginIndex = $entity['indices'][1];
} }
$text .= StringUtils::substr($tweet, $beginIndex, StringUtils::strlen($tweet)); $text .= StringUtils::substr($tweet, $beginIndex, StringUtils::strlen($tweet));
return $text; return $text;
} }
@ -436,13 +439,15 @@ class Autolink extends Regex
* *
* @param string The tweet to be converted * @param string The tweet to be converted
* @param mixed The entities info * @param mixed The entities info
*
* @return string that auto-link HTML added * @return string that auto-link HTML added
*
* @since 1.1.0 * @since 1.1.0
*/ */
public function autoLinkWithJson($tweet = null, $json = null) public function autoLinkWithJson($tweet = null, $json = null)
{ {
// concatenate entities // concatenate entities
$entities = array(); $entities = [];
if (is_object($json)) { if (is_object($json)) {
$json = $this->object2array($json); $json = $this->object2array($json);
} }
@ -460,13 +465,15 @@ class Autolink extends Regex
} }
$entities = $this->extractor->removeOverlappingEntities($entities); $entities = $this->extractor->removeOverlappingEntities($entities);
return $this->autoLinkEntities($tweet, $entities); return $this->autoLinkEntities($tweet, $entities);
} }
/** /**
* convert Object to Array * convert Object to Array.
* *
* @param mixed $obj * @param mixed $obj
*
* @return array * @return array
*/ */
protected function object2array($obj) protected function object2array($obj)
@ -477,6 +484,7 @@ class Autolink extends Regex
$array[$key] = $this->object2array($var); $array[$key] = $this->object2array($var);
} }
} }
return $array; return $array;
} }
@ -484,7 +492,9 @@ class Autolink extends Regex
* Auto-link hashtags, URLs, usernames and lists. * Auto-link hashtags, URLs, usernames and lists.
* *
* @param string The tweet to be converted * @param string The tweet to be converted
*
* @return string that auto-link HTML added * @return string that auto-link HTML added
*
* @since 1.1.0 * @since 1.1.0
*/ */
public function autoLink($tweet = null) public function autoLink($tweet = null)
@ -493,6 +503,7 @@ class Autolink extends Regex
$tweet = $this->tweet; $tweet = $this->tweet;
} }
$entities = $this->extractor->extractURLWithoutProtocol(false)->extractEntitiesWithIndices($tweet); $entities = $this->extractor->extractURLWithoutProtocol(false)->extractEntitiesWithIndices($tweet);
return $this->autoLinkEntities($tweet, $entities); return $this->autoLinkEntities($tweet, $entities);
} }
@ -502,6 +513,7 @@ class Autolink extends Regex
* added. * added.
* *
* @return string that auto-link HTML added * @return string that auto-link HTML added
*
* @since 1.1.0 * @since 1.1.0
*/ */
public function autoLinkUsernamesAndLists($tweet = null) public function autoLinkUsernamesAndLists($tweet = null)
@ -510,6 +522,7 @@ class Autolink extends Regex
$tweet = $this->tweet; $tweet = $this->tweet;
} }
$entities = $this->extractor->extractMentionsOrListsWithIndices($tweet); $entities = $this->extractor->extractMentionsOrListsWithIndices($tweet);
return $this->autoLinkEntities($tweet, $entities); return $this->autoLinkEntities($tweet, $entities);
} }
@ -518,6 +531,7 @@ class Autolink extends Regex
* added. * added.
* *
* @return string that auto-link HTML added * @return string that auto-link HTML added
*
* @since 1.1.0 * @since 1.1.0
*/ */
public function autoLinkHashtags($tweet = null) public function autoLinkHashtags($tweet = null)
@ -526,6 +540,7 @@ class Autolink extends Regex
$tweet = $this->tweet; $tweet = $this->tweet;
} }
$entities = $this->extractor->extractHashtagsWithIndices($tweet); $entities = $this->extractor->extractHashtagsWithIndices($tweet);
return $this->autoLinkEntities($tweet, $entities); return $this->autoLinkEntities($tweet, $entities);
} }
@ -535,6 +550,7 @@ class Autolink extends Regex
* This only auto-links URLs with protocol. * This only auto-links URLs with protocol.
* *
* @return string that auto-link HTML added * @return string that auto-link HTML added
*
* @since 1.1.0 * @since 1.1.0
*/ */
public function autoLinkURLs($tweet = null) public function autoLinkURLs($tweet = null)
@ -543,6 +559,7 @@ class Autolink extends Regex
$tweet = $this->tweet; $tweet = $this->tweet;
} }
$entities = $this->extractor->extractURLWithoutProtocol(false)->extractURLsWithIndices($tweet); $entities = $this->extractor->extractURLWithoutProtocol(false)->extractURLsWithIndices($tweet);
return $this->autoLinkEntities($tweet, $entities); return $this->autoLinkEntities($tweet, $entities);
} }
@ -551,6 +568,7 @@ class Autolink extends Regex
* added. * added.
* *
* @return string that auto-link HTML added * @return string that auto-link HTML added
*
* @since 1.1.0 * @since 1.1.0
*/ */
public function autoLinkCashtags($tweet = null) public function autoLinkCashtags($tweet = null)
@ -559,6 +577,7 @@ class Autolink extends Regex
$tweet = $this->tweet; $tweet = $this->tweet;
} }
$entities = $this->extractor->extractCashtagsWithIndices($tweet); $entities = $this->extractor->extractCashtagsWithIndices($tweet);
return $this->autoLinkEntities($tweet, $entities); return $this->autoLinkEntities($tweet, $entities);
} }
@ -639,10 +658,11 @@ class Autolink extends Regex
} }
/** /**
*
* @param array $entity * @param array $entity
* @param string $tweet * @param string $tweet
*
* @return string * @return string
*
* @since 1.1.0 * @since 1.1.0
*/ */
public function linkToHashtag($entity, $tweet = null) public function linkToHashtag($entity, $tweet = null)
@ -651,8 +671,8 @@ class Autolink extends Regex
$tweet = $this->tweet; $tweet = $this->tweet;
} }
$this->target = false; $this->target = false;
$attributes = array(); $attributes = [];
$class = array(); $class = [];
$hash = StringUtils::substr($tweet, $entity['indices'][0], 1); $hash = StringUtils::substr($tweet, $entity['indices'][0], 1);
$linkText = $hash.$entity['hashtag']; $linkText = $hash.$entity['hashtag'];
@ -665,29 +685,30 @@ class Autolink extends Regex
$class[] = 'rtl'; $class[] = 'rtl';
} }
if (!empty($class)) { if (!empty($class)) {
$attributes['class'] = join(' ', $class); $attributes['class'] = implode(' ', $class);
} }
return $this->linkToText($entity, $linkText, $attributes); return $this->linkToText($entity, $linkText, $attributes);
} }
/** /**
*
* @param array $entity * @param array $entity
*
* @return string * @return string
*
* @since 1.1.0 * @since 1.1.0
*/ */
public function linkToMentionAndList($entity) public function linkToMentionAndList($entity)
{ {
$attributes = array(); $attributes = [];
if (!empty($entity['list_slug'])) { if (!empty($entity['list_slug'])) {
# Replace the list and username // Replace the list and username
$linkText = $entity['screen_name'].$entity['list_slug']; $linkText = $entity['screen_name'].$entity['list_slug'];
$class = $this->class_list; $class = $this->class_list;
$url = $this->url_base_list.$linkText; $url = $this->url_base_list.$linkText;
} else { } else {
# Replace the username // Replace the username
$linkText = $entity['screen_name']; $linkText = $entity['screen_name'];
$class = $this->class_user; $class = $this->class_user;
$url = $this->url_base_user.$linkText; $url = $this->url_base_user.$linkText;
@ -701,10 +722,11 @@ class Autolink extends Regex
} }
/** /**
*
* @param array $entity * @param array $entity
* @param string $tweet * @param string $tweet
*
* @return string * @return string
*
* @since 1.1.0 * @since 1.1.0
*/ */
public function linkToCashtag($entity, $tweet = null) public function linkToCashtag($entity, $tweet = null)
@ -712,7 +734,7 @@ class Autolink extends Regex
if (is_null($tweet)) { if (is_null($tweet)) {
$tweet = $this->tweet; $tweet = $this->tweet;
} }
$attributes = array(); $attributes = [];
$doller = StringUtils::substr($tweet, $entity['indices'][0], 1); $doller = StringUtils::substr($tweet, $entity['indices'][0], 1);
$linkText = $doller.$entity['cashtag']; $linkText = $doller.$entity['cashtag'];
$attributes['href'] = $this->url_base_cash.$entity['cashtag']; $attributes['href'] = $this->url_base_cash.$entity['cashtag'];
@ -725,16 +747,17 @@ class Autolink extends Regex
} }
/** /**
*
* @param array $entity * @param array $entity
* @param string $text * @param string $text
* @param array $attributes * @param array $attributes
*
* @return string * @return string
*
* @since 1.1.0 * @since 1.1.0
*/ */
public function linkToText(array $entity, $text, $attributes = array()) public function linkToText(array $entity, $text, $attributes = [])
{ {
$rel = array(); $rel = [];
if ($this->external) { if ($this->external) {
$rel[] = 'external'; $rel[] = 'external';
} }
@ -745,7 +768,7 @@ class Autolink extends Regex
$rel[] = 'noopener'; $rel[] = 'noopener';
} }
if (!empty($rel)) { if (!empty($rel)) {
$attributes['rel'] = join(' ', $rel); $attributes['rel'] = implode(' ', $rel);
} }
if ($this->target) { if ($this->target) {
$attributes['target'] = $this->target; $attributes['target'] = $this->target;
@ -755,13 +778,15 @@ class Autolink extends Regex
$link .= ' '.$key.'="'.$this->escapeHTML($val).'"'; $link .= ' '.$key.'="'.$this->escapeHTML($val).'"';
} }
$link .= '>'.$text.'</a>'; $link .= '>'.$text.'</a>';
return $link; return $link;
} }
/** /**
* html escape * html escape.
* *
* @param string $text * @param string $text
*
* @return string * @return string
*/ */
protected function escapeHTML($text) protected function escapeHTML($text)

View file

@ -5,16 +5,12 @@
* @author Nick Pope <nick@nickpope.me.uk> * @author Nick Pope <nick@nickpope.me.uk>
* @copyright Copyright © 2010, Mike Cochrane, Nick Pope * @copyright Copyright © 2010, Mike Cochrane, Nick Pope
* @license http://www.apache.org/licenses/LICENSE-2.0 Apache License v2.0 * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License v2.0
* @package Twitter.Text
*/ */
namespace App\Util\Lexer; namespace App\Util\Lexer;
use App\Util\Lexer\Regex;
use App\Util\Lexer\StringUtils;
/** /**
* Twitter Extractor Class * Twitter Extractor Class.
* *
* Parses tweets and extracts URLs, usernames, username/list pairs and * Parses tweets and extracts URLs, usernames, username/list pairs and
* hashtags. * hashtags.
@ -27,13 +23,11 @@ use App\Util\Lexer\StringUtils;
* @author Nick Pope <nick@nickpope.me.uk> * @author Nick Pope <nick@nickpope.me.uk>
* @copyright Copyright © 2010, Mike Cochrane, Nick Pope * @copyright Copyright © 2010, Mike Cochrane, Nick Pope
* @license http://www.apache.org/licenses/LICENSE-2.0 Apache License v2.0 * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License v2.0
* @package Twitter.Text
*/ */
class Extractor extends Regex class Extractor extends Regex
{ {
/** /**
* @var boolean * @var bool
*/ */
protected $extractURLWithoutProtocol = true; protected $extractURLWithoutProtocol = true;
@ -68,6 +62,7 @@ class Extractor extends Regex
* the extracted elements. * the extracted elements.
* *
* @param string $tweet The tweet to extract. * @param string $tweet The tweet to extract.
*
* @return array The elements in the tweet. * @return array The elements in the tweet.
*/ */
public function extract($tweet = null) public function extract($tweet = null)
@ -75,7 +70,8 @@ class Extractor extends Regex
if (is_null($tweet)) { if (is_null($tweet)) {
$tweet = $this->tweet; $tweet = $this->tweet;
} }
return array(
return [
'hashtags' => $this->extractHashtags($tweet), 'hashtags' => $this->extractHashtags($tweet),
'urls' => $this->extractURLs($tweet), 'urls' => $this->extractURLs($tweet),
'mentions' => $this->extractMentionedUsernames($tweet), 'mentions' => $this->extractMentionedUsernames($tweet),
@ -83,13 +79,14 @@ class Extractor extends Regex
'hashtags_with_indices' => $this->extractHashtagsWithIndices($tweet), 'hashtags_with_indices' => $this->extractHashtagsWithIndices($tweet),
'urls_with_indices' => $this->extractURLsWithIndices($tweet), 'urls_with_indices' => $this->extractURLsWithIndices($tweet),
'mentions_with_indices' => $this->extractMentionedUsernamesWithIndices($tweet), 'mentions_with_indices' => $this->extractMentionedUsernamesWithIndices($tweet),
); ];
} }
/** /**
* Extract URLs, @mentions, lists and #hashtag from a given text/tweet. * Extract URLs, @mentions, lists and #hashtag from a given text/tweet.
* *
* @param string $tweet The tweet to extract. * @param string $tweet The tweet to extract.
*
* @return array list of extracted entities * @return array list of extracted entities
*/ */
public function extractEntitiesWithIndices($tweet = null) public function extractEntitiesWithIndices($tweet = null)
@ -97,12 +94,13 @@ class Extractor extends Regex
if (is_null($tweet)) { if (is_null($tweet)) {
$tweet = $this->tweet; $tweet = $this->tweet;
} }
$entities = array(); $entities = [];
$entities = array_merge($entities, $this->extractURLsWithIndices($tweet)); $entities = array_merge($entities, $this->extractURLsWithIndices($tweet));
$entities = array_merge($entities, $this->extractHashtagsWithIndices($tweet, false)); $entities = array_merge($entities, $this->extractHashtagsWithIndices($tweet, false));
$entities = array_merge($entities, $this->extractMentionsOrListsWithIndices($tweet)); $entities = array_merge($entities, $this->extractMentionsOrListsWithIndices($tweet));
$entities = array_merge($entities, $this->extractCashtagsWithIndices($tweet)); $entities = array_merge($entities, $this->extractCashtagsWithIndices($tweet));
$entities = $this->removeOverlappingEntities($entities); $entities = $this->removeOverlappingEntities($entities);
return $entities; return $entities;
} }
@ -110,16 +108,18 @@ class Extractor extends Regex
* Extracts all the hashtags from the tweet. * Extracts all the hashtags from the tweet.
* *
* @param string $tweet The tweet to extract. * @param string $tweet The tweet to extract.
*
* @return array The hashtag elements in the tweet. * @return array The hashtag elements in the tweet.
*/ */
public function extractHashtags($tweet = null) public function extractHashtags($tweet = null)
{ {
$hashtagsOnly = array(); $hashtagsOnly = [];
$hashtagsWithIndices = $this->extractHashtagsWithIndices($tweet); $hashtagsWithIndices = $this->extractHashtagsWithIndices($tweet);
foreach ($hashtagsWithIndices as $hashtagWithIndex) { foreach ($hashtagsWithIndices as $hashtagWithIndex) {
$hashtagsOnly[] = $hashtagWithIndex['hashtag']; $hashtagsOnly[] = $hashtagWithIndex['hashtag'];
} }
return $hashtagsOnly; return $hashtagsOnly;
} }
@ -127,16 +127,18 @@ class Extractor extends Regex
* Extracts all the cashtags from the tweet. * Extracts all the cashtags from the tweet.
* *
* @param string $tweet The tweet to extract. * @param string $tweet The tweet to extract.
*
* @return array The cashtag elements in the tweet. * @return array The cashtag elements in the tweet.
*/ */
public function extractCashtags($tweet = null) public function extractCashtags($tweet = null)
{ {
$cashtagsOnly = array(); $cashtagsOnly = [];
$cashtagsWithIndices = $this->extractCashtagsWithIndices($tweet); $cashtagsWithIndices = $this->extractCashtagsWithIndices($tweet);
foreach ($cashtagsWithIndices as $cashtagWithIndex) { foreach ($cashtagsWithIndices as $cashtagWithIndex) {
$cashtagsOnly[] = $cashtagWithIndex['cashtag']; $cashtagsOnly[] = $cashtagWithIndex['cashtag'];
} }
return $cashtagsOnly; return $cashtagsOnly;
} }
@ -144,16 +146,18 @@ class Extractor extends Regex
* Extracts all the URLs from the tweet. * Extracts all the URLs from the tweet.
* *
* @param string $tweet The tweet to extract. * @param string $tweet The tweet to extract.
*
* @return array The URL elements in the tweet. * @return array The URL elements in the tweet.
*/ */
public function extractURLs($tweet = null) public function extractURLs($tweet = null)
{ {
$urlsOnly = array(); $urlsOnly = [];
$urlsWithIndices = $this->extractURLsWithIndices($tweet); $urlsWithIndices = $this->extractURLsWithIndices($tweet);
foreach ($urlsWithIndices as $urlWithIndex) { foreach ($urlsWithIndices as $urlWithIndex) {
$urlsOnly[] = $urlWithIndex['url']; $urlsOnly[] = $urlWithIndex['url'];
} }
return $urlsOnly; return $urlsOnly;
} }
@ -163,20 +167,22 @@ class Extractor extends Regex
* A mention is an occurrence of a username anywhere in a tweet. * A mention is an occurrence of a username anywhere in a tweet.
* *
* @param string $tweet The tweet to extract. * @param string $tweet The tweet to extract.
*
* @return array The usernames elements in the tweet. * @return array The usernames elements in the tweet.
*/ */
public function extractMentionedScreennames($tweet = null) public function extractMentionedScreennames($tweet = null)
{ {
$usernamesOnly = array(); $usernamesOnly = [];
$mentionsWithIndices = $this->extractMentionsOrListsWithIndices($tweet); $mentionsWithIndices = $this->extractMentionsOrListsWithIndices($tweet);
foreach ($mentionsWithIndices as $mentionWithIndex) { foreach ($mentionsWithIndices as $mentionWithIndex) {
$screen_name = mb_strtolower($mentionWithIndex['screen_name']); $screen_name = mb_strtolower($mentionWithIndex['screen_name']);
if (empty($screen_name) OR in_array($screen_name, $usernamesOnly)) { if (empty($screen_name) or in_array($screen_name, $usernamesOnly)) {
continue; continue;
} }
$usernamesOnly[] = $screen_name; $usernamesOnly[] = $screen_name;
} }
return $usernamesOnly; return $usernamesOnly;
} }
@ -186,11 +192,13 @@ class Extractor extends Regex
* A mention is an occurrence of a username anywhere in a tweet. * A mention is an occurrence of a username anywhere in a tweet.
* *
* @return array The usernames elements in the tweet. * @return array The usernames elements in the tweet.
*
* @deprecated since version 1.1.0 * @deprecated since version 1.1.0
*/ */
public function extractMentionedUsernames($tweet) public function extractMentionedUsernames($tweet)
{ {
$this->tweet = $tweet; $this->tweet = $tweet;
return $this->extractMentionedScreennames($tweet); return $this->extractMentionedScreennames($tweet);
} }
@ -200,6 +208,7 @@ class Extractor extends Regex
* A reply is an occurrence of a username at the beginning of a tweet. * A reply is an occurrence of a username at the beginning of a tweet.
* *
* @param string $tweet The tweet to extract. * @param string $tweet The tweet to extract.
*
* @return array The usernames replied to in a tweet. * @return array The usernames replied to in a tweet.
*/ */
public function extractReplyScreenname($tweet = null) public function extractReplyScreenname($tweet = null)
@ -208,10 +217,11 @@ class Extractor extends Regex
$tweet = $this->tweet; $tweet = $this->tweet;
} }
$matched = preg_match(self::$patterns['valid_reply'], $tweet, $matches); $matched = preg_match(self::$patterns['valid_reply'], $tweet, $matches);
# Check username ending in // Check username ending in
if ($matched && preg_match(self::$patterns['end_mention_match'], $matches[2])) { if ($matched && preg_match(self::$patterns['end_mention_match'], $matches[2])) {
$matched = false; $matched = false;
} }
return $matched ? $matches[1] : null; return $matched ? $matches[1] : null;
} }
@ -221,6 +231,7 @@ class Extractor extends Regex
* A reply is an occurrence of a username at the beginning of a tweet. * A reply is an occurrence of a username at the beginning of a tweet.
* *
* @return array The usernames replied to in a tweet. * @return array The usernames replied to in a tweet.
*
* @deprecated since version 1.1.0 * @deprecated since version 1.1.0
*/ */
public function extractRepliedUsernames() public function extractRepliedUsernames()
@ -232,7 +243,8 @@ class Extractor extends Regex
* Extracts all the hashtags and the indices they occur at from the tweet. * Extracts all the hashtags and the indices they occur at from the tweet.
* *
* @param string $tweet The tweet to extract. * @param string $tweet The tweet to extract.
* @param boolean $checkUrlOverlap if true, check if extracted hashtags overlap URLs and remove overlapping ones * @param bool $checkUrlOverlap if true, check if extracted hashtags overlap URLs and remove overlapping ones
*
* @return array The hashtag elements in the tweet. * @return array The hashtag elements in the tweet.
*/ */
public function extractHashtagsWithIndices($tweet = null, $checkUrlOverlap = true) public function extractHashtagsWithIndices($tweet = null, $checkUrlOverlap = true)
@ -242,14 +254,14 @@ class Extractor extends Regex
} }
if (!preg_match('/[#]/iu', $tweet)) { if (!preg_match('/[#]/iu', $tweet)) {
return array(); return [];
} }
preg_match_all(self::$patterns['valid_hashtag'], $tweet, $matches, PREG_SET_ORDER | PREG_OFFSET_CAPTURE); preg_match_all(self::$patterns['valid_hashtag'], $tweet, $matches, PREG_SET_ORDER | PREG_OFFSET_CAPTURE);
$tags = array(); $tags = [];
foreach ($matches as $match) { foreach ($matches as $match) {
list($all, $before, $hash, $hashtag, $outer) = array_pad($match, 3, array('', 0)); list($all, $before, $hash, $hashtag, $outer) = array_pad($match, 3, ['', 0]);
$start_position = $hash[1] > 0 ? StringUtils::strlen(substr($tweet, 0, $hash[1])) : $hash[1]; $start_position = $hash[1] > 0 ? StringUtils::strlen(substr($tweet, 0, $hash[1])) : $hash[1];
$end_position = $start_position + StringUtils::strlen($hash[0].$hashtag[0]); $end_position = $start_position + StringUtils::strlen($hash[0].$hashtag[0]);
@ -257,21 +269,21 @@ class Extractor extends Regex
continue; continue;
} }
$tags[] = array( $tags[] = [
'hashtag' => $hashtag[0], 'hashtag' => $hashtag[0],
'indices' => array($start_position, $end_position) 'indices' => [$start_position, $end_position],
); ];
} }
if (!$checkUrlOverlap) { if (!$checkUrlOverlap) {
return $tags; return $tags;
} }
# check url overlap // check url overlap
$urls = $this->extractURLsWithIndices($tweet); $urls = $this->extractURLsWithIndices($tweet);
$entities = $this->removeOverlappingEntities(array_merge($tags, $urls)); $entities = $this->removeOverlappingEntities(array_merge($tags, $urls));
$validTags = array(); $validTags = [];
foreach ($entities as $entity) { foreach ($entities as $entity) {
if (empty($entity['hashtag'])) { if (empty($entity['hashtag'])) {
continue; continue;
@ -286,6 +298,7 @@ class Extractor extends Regex
* Extracts all the cashtags and the indices they occur at from the tweet. * Extracts all the cashtags and the indices they occur at from the tweet.
* *
* @param string $tweet The tweet to extract. * @param string $tweet The tweet to extract.
*
* @return array The cashtag elements in the tweet. * @return array The cashtag elements in the tweet.
*/ */
public function extractCashtagsWithIndices($tweet = null) public function extractCashtagsWithIndices($tweet = null)
@ -295,14 +308,14 @@ class Extractor extends Regex
} }
if (!preg_match('/\$/iu', $tweet)) { if (!preg_match('/\$/iu', $tweet)) {
return array(); return [];
} }
preg_match_all(self::$patterns['valid_cashtag'], $tweet, $matches, PREG_SET_ORDER | PREG_OFFSET_CAPTURE); preg_match_all(self::$patterns['valid_cashtag'], $tweet, $matches, PREG_SET_ORDER | PREG_OFFSET_CAPTURE);
$tags = array(); $tags = [];
foreach ($matches as $match) { foreach ($matches as $match) {
list($all, $before, $dollar, $cash_text, $outer) = array_pad($match, 3, array('', 0)); list($all, $before, $dollar, $cash_text, $outer) = array_pad($match, 3, ['', 0]);
$start_position = $dollar[1] > 0 ? StringUtils::strlen(substr($tweet, 0, $dollar[1])) : $dollar[1]; $start_position = $dollar[1] > 0 ? StringUtils::strlen(substr($tweet, 0, $dollar[1])) : $dollar[1];
$end_position = $start_position + StringUtils::strlen($dollar[0].$cash_text[0]); $end_position = $start_position + StringUtils::strlen($dollar[0].$cash_text[0]);
@ -310,10 +323,10 @@ class Extractor extends Regex
continue; continue;
} }
$tags[] = array( $tags[] = [
'cashtag' => $cash_text[0], 'cashtag' => $cash_text[0],
'indices' => array($start_position, $end_position) 'indices' => [$start_position, $end_position],
); ];
} }
return $tags; return $tags;
@ -323,6 +336,7 @@ class Extractor extends Regex
* Extracts all the URLs and the indices they occur at from the tweet. * Extracts all the URLs and the indices they occur at from the tweet.
* *
* @param string $tweet The tweet to extract. * @param string $tweet The tweet to extract.
*
* @return array The URLs elements in the tweet. * @return array The URLs elements in the tweet.
*/ */
public function extractURLsWithIndices($tweet = null) public function extractURLsWithIndices($tweet = null)
@ -333,14 +347,14 @@ class Extractor extends Regex
$needle = $this->extractURLWithoutProtocol() ? '.' : ':'; $needle = $this->extractURLWithoutProtocol() ? '.' : ':';
if (strpos($tweet, $needle) === false) { if (strpos($tweet, $needle) === false) {
return array(); return [];
} }
$urls = array(); $urls = [];
preg_match_all(self::$patterns['valid_url'], $tweet, $matches, PREG_SET_ORDER | PREG_OFFSET_CAPTURE); preg_match_all(self::$patterns['valid_url'], $tweet, $matches, PREG_SET_ORDER | PREG_OFFSET_CAPTURE);
foreach ($matches as $match) { foreach ($matches as $match) {
list($all, $before, $url, $protocol, $domain, $port, $path, $query) = array_pad($match, 8, array('')); list($all, $before, $url, $protocol, $domain, $port, $path, $query) = array_pad($match, 8, ['']);
$start_position = $url[1] > 0 ? StringUtils::strlen(substr($tweet, 0, $url[1])) : $url[1]; $start_position = $url[1] > 0 ? StringUtils::strlen(substr($tweet, 0, $url[1])) : $url[1];
$end_position = $start_position + StringUtils::strlen($url[0]); $end_position = $start_position + StringUtils::strlen($url[0]);
@ -367,10 +381,10 @@ class Extractor extends Regex
$asciiDomain[0] = preg_replace('/'.preg_quote($domain, '/').'/u', $asciiDomain[0], $url); $asciiDomain[0] = preg_replace('/'.preg_quote($domain, '/').'/u', $asciiDomain[0], $url);
$ascii_start_position = StringUtils::strpos($domain, $asciiDomain[0], $ascii_end_position); $ascii_start_position = StringUtils::strpos($domain, $asciiDomain[0], $ascii_end_position);
$ascii_end_position = $ascii_start_position + StringUtils::strlen($asciiDomain[0]); $ascii_end_position = $ascii_start_position + StringUtils::strlen($asciiDomain[0]);
$last_url = array( $last_url = [
'url' => $asciiDomain[0], 'url' => $asciiDomain[0],
'indices' => array($start_position + $ascii_start_position, $start_position + $ascii_end_position), 'indices' => [$start_position + $ascii_start_position, $start_position + $ascii_end_position],
); ];
if (!empty($path) if (!empty($path)
|| preg_match(self::$patterns['valid_special_short_domain'], $asciiDomain[0]) || preg_match(self::$patterns['valid_special_short_domain'], $asciiDomain[0])
|| !preg_match(self::$patterns['invalid_short_domain'], $asciiDomain[0])) { || !preg_match(self::$patterns['invalid_short_domain'], $asciiDomain[0])) {
@ -395,10 +409,10 @@ class Extractor extends Regex
$url = $tcoUrlMatches[0]; $url = $tcoUrlMatches[0];
$end_position = $start_position + StringUtils::strlen($url); $end_position = $start_position + StringUtils::strlen($url);
} }
$urls[] = array( $urls[] = [
'url' => $url, 'url' => $url,
'indices' => array($start_position, $end_position), 'indices' => [$start_position, $end_position],
); ];
} }
} }
@ -409,6 +423,7 @@ class Extractor extends Regex
* Extracts all the usernames and the indices they occur at from the tweet. * Extracts all the usernames and the indices they occur at from the tweet.
* *
* @param string $tweet The tweet to extract. * @param string $tweet The tweet to extract.
*
* @return array The username elements in the tweet. * @return array The username elements in the tweet.
*/ */
public function extractMentionedScreennamesWithIndices($tweet = null) public function extractMentionedScreennamesWithIndices($tweet = null)
@ -417,7 +432,7 @@ class Extractor extends Regex
$tweet = $this->tweet; $tweet = $this->tweet;
} }
$usernamesOnly = array(); $usernamesOnly = [];
$mentions = $this->extractMentionsOrListsWithIndices($tweet); $mentions = $this->extractMentionsOrListsWithIndices($tweet);
foreach ($mentions as $mention) { foreach ($mentions as $mention) {
if (isset($mention['list_slug'])) { if (isset($mention['list_slug'])) {
@ -425,6 +440,7 @@ class Extractor extends Regex
} }
$usernamesOnly[] = $mention; $usernamesOnly[] = $mention;
} }
return $usernamesOnly; return $usernamesOnly;
} }
@ -432,6 +448,7 @@ class Extractor extends Regex
* Extracts all the usernames and the indices they occur at from the tweet. * Extracts all the usernames and the indices they occur at from the tweet.
* *
* @return array The username elements in the tweet. * @return array The username elements in the tweet.
*
* @deprecated since version 1.1.0 * @deprecated since version 1.1.0
*/ */
public function extractMentionedUsernamesWithIndices() public function extractMentionedUsernamesWithIndices()
@ -443,6 +460,7 @@ class Extractor extends Regex
* Extracts all the usernames and the indices they occur at from the tweet. * Extracts all the usernames and the indices they occur at from the tweet.
* *
* @param string $tweet The tweet to extract. * @param string $tweet The tweet to extract.
*
* @return array The username elements in the tweet. * @return array The username elements in the tweet.
*/ */
public function extractMentionsOrListsWithIndices($tweet = null) public function extractMentionsOrListsWithIndices($tweet = null)
@ -452,21 +470,21 @@ class Extractor extends Regex
} }
if (!preg_match('/[@]/iu', $tweet)) { if (!preg_match('/[@]/iu', $tweet)) {
return array(); return [];
} }
preg_match_all(self::$patterns['valid_mentions_or_lists'], $tweet, $matches, PREG_SET_ORDER | PREG_OFFSET_CAPTURE); preg_match_all(self::$patterns['valid_mentions_or_lists'], $tweet, $matches, PREG_SET_ORDER | PREG_OFFSET_CAPTURE);
$results = array(); $results = [];
foreach ($matches as $match) { foreach ($matches as $match) {
list($all, $before, $at, $username, $list_slug, $outer) = array_pad($match, 6, array('', 0)); list($all, $before, $at, $username, $list_slug, $outer) = array_pad($match, 6, ['', 0]);
$start_position = $at[1] > 0 ? StringUtils::strlen(substr($tweet, 0, $at[1])) : $at[1]; $start_position = $at[1] > 0 ? StringUtils::strlen(substr($tweet, 0, $at[1])) : $at[1];
$end_position = $start_position + StringUtils::strlen($at[0]) + StringUtils::strlen($username[0]); $end_position = $start_position + StringUtils::strlen($at[0]) + StringUtils::strlen($username[0]);
$entity = array( $entity = [
'screen_name' => $username[0], 'screen_name' => $username[0],
'list_slug' => $list_slug[0], 'list_slug' => $list_slug[0],
'indices' => array($start_position, $end_position), 'indices' => [$start_position, $end_position],
); ];
if (preg_match(self::$patterns['end_mention_match'], $outer[0])) { if (preg_match(self::$patterns['end_mention_match'], $outer[0])) {
continue; continue;
@ -486,6 +504,7 @@ class Extractor extends Regex
* Extracts all the usernames and the indices they occur at from the tweet. * Extracts all the usernames and the indices they occur at from the tweet.
* *
* @return array The username elements in the tweet. * @return array The username elements in the tweet.
*
* @deprecated since version 1.1.0 * @deprecated since version 1.1.0
*/ */
public function extractMentionedUsernamesOrListsWithIndices() public function extractMentionedUsernamesOrListsWithIndices()
@ -494,9 +513,10 @@ class Extractor extends Regex
} }
/** /**
* setter/getter for extractURLWithoutProtocol * setter/getter for extractURLWithoutProtocol.
*
* @param bool $flag
* *
* @param boolean $flag
* @return Extractor * @return Extractor
*/ */
public function extractURLWithoutProtocol($flag = null) public function extractURLWithoutProtocol($flag = null)
@ -505,6 +525,7 @@ class Extractor extends Regex
return $this->extractURLWithoutProtocol; return $this->extractURLWithoutProtocol;
} }
$this->extractURLWithoutProtocol = (bool) $flag; $this->extractURLWithoutProtocol = (bool) $flag;
return $this; return $this;
} }
@ -513,12 +534,13 @@ class Extractor extends Regex
* This returns a new array with no overlapping entities. * This returns a new array with no overlapping entities.
* *
* @param array $entities * @param array $entities
*
* @return array * @return array
*/ */
public function removeOverlappingEntities($entities) public function removeOverlappingEntities($entities)
{ {
$result = array(); $result = [];
usort($entities, array($this, 'sortEntites')); usort($entities, [$this, 'sortEntites']);
$prev = null; $prev = null;
foreach ($entities as $entity) { foreach ($entities as $entity) {
@ -528,14 +550,16 @@ class Extractor extends Regex
$prev = $entity; $prev = $entity;
$result[] = $entity; $result[] = $entity;
} }
return $result; return $result;
} }
/** /**
* sort by entity start index * sort by entity start index.
* *
* @param array $a * @param array $a
* @param array $b * @param array $b
*
* @return int * @return int
*/ */
protected function sortEntites($a, $b) protected function sortEntites($a, $b)
@ -543,6 +567,7 @@ class Extractor extends Regex
if ($a['indices'][0] == $b['indices'][0]) { if ($a['indices'][0] == $b['indices'][0]) {
return 0; return 0;
} }
return ($a['indices'][0] < $b['indices'][0]) ? -1 : 1; return ($a['indices'][0] < $b['indices'][0]) ? -1 : 1;
} }
} }

View file

@ -2,8 +2,8 @@
namespace App\Util\Lexer; namespace App\Util\Lexer;
class Hashtag { class Hashtag
{
public static function getHashtags($status) public static function getHashtags($status)
{ {
$hashtags = false; $hashtags = false;
@ -12,13 +12,16 @@ class Hashtag {
$res = array_count_values($matches[0]); $res = array_count_values($matches[0]);
$hashtags = array_keys($res); $hashtags = array_keys($res);
} }
return $hashtags; return $hashtags;
} }
public static function replaceHashtagsWithLinks($status) public static function replaceHashtagsWithLinks($status)
{ {
$hashtags = self::getHashtags($status); $hashtags = self::getHashtags($status);
if(!$hashtags) { return false; } if (!$hashtags) {
return false;
}
$rendered = $status; $rendered = $status;
@ -30,7 +33,5 @@ class Hashtag {
} }
return $rendered; return $rendered;
} }
} }

View file

@ -4,16 +4,12 @@
* @author Nick Pope <nick@nickpope.me.uk> * @author Nick Pope <nick@nickpope.me.uk>
* @copyright Copyright © 2010, Nick Pope * @copyright Copyright © 2010, Nick Pope
* @license http://www.apache.org/licenses/LICENSE-2.0 Apache License v2.0 * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License v2.0
* @package Twitter.Text
*/ */
namespace App\Util\Lexer; namespace App\Util\Lexer;
use App\Util\Lexer\Regex;
use App\Util\Lexer\StringUtils;
/** /**
* Twitter HitHighlighter Class * Twitter HitHighlighter Class.
* *
* Performs "hit highlighting" on tweets that have been auto-linked already. * Performs "hit highlighting" on tweets that have been auto-linked already.
* Useful with the results returned from the search API. * Useful with the results returned from the search API.
@ -25,11 +21,9 @@ use App\Util\Lexer\StringUtils;
* @author Nick Pope <nick@nickpope.me.uk> * @author Nick Pope <nick@nickpope.me.uk>
* @copyright Copyright © 2010, Nick Pope * @copyright Copyright © 2010, Nick Pope
* @license http://www.apache.org/licenses/LICENSE-2.0 Apache License v2.0 * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License v2.0
* @package Twitter.Text
*/ */
class HitHighlighter extends Regex class HitHighlighter extends Regex
{ {
/** /**
* The tag to surround hits with. * The tag to surround hits with.
* *
@ -96,6 +90,7 @@ class HitHighlighter extends Regex
public function setTag($v) public function setTag($v)
{ {
$this->tag = $v; $this->tag = $v;
return $this; return $this;
} }
@ -119,8 +114,8 @@ class HitHighlighter extends Regex
return $tweet; return $tweet;
} }
$highlightTweet = ''; $highlightTweet = '';
$tags = array('<' . $this->tag . '>', '</' . $this->tag . '>'); $tags = ['<'.$this->tag.'>', '</'.$this->tag.'>'];
# Check whether we can simply replace or whether we need to chunk... // Check whether we can simply replace or whether we need to chunk...
if (strpos($tweet, '<') === false) { if (strpos($tweet, '<') === false) {
$ti = 0; // tag increment (for added tags) $ti = 0; // tag increment (for added tags)
$highlightTweet = $tweet; $highlightTweet = $tweet;
@ -137,12 +132,12 @@ class HitHighlighter extends Regex
$chunk_cursor = 0; $chunk_cursor = 0;
$offset = 0; $offset = 0;
$start_in_chunk = false; $start_in_chunk = false;
# Flatten the multidimensional hits array: // Flatten the multidimensional hits array:
$hits_flat = array(); $hits_flat = [];
foreach ($hits as $hit) { foreach ($hits as $hit) {
$hits_flat = array_merge($hits_flat, $hit); $hits_flat = array_merge($hits_flat, $hit);
} }
# Loop over the hit indices: // Loop over the hit indices:
for ($index = 0; $index < count($hits_flat); $index++) { for ($index = 0; $index < count($hits_flat); $index++) {
$hit = $hits_flat[$index]; $hit = $hits_flat[$index];
$tag = $tags[$index % 2]; $tag = $tags[$index % 2];
@ -169,7 +164,7 @@ class HitHighlighter extends Regex
$start_in_chunk = ($index % 2 === 0); $start_in_chunk = ($index % 2 === 0);
$placed = true; $placed = true;
} }
# Ultimate fallback - hits that run off the end get a closing tag: // Ultimate fallback - hits that run off the end get a closing tag:
if (!$placed) { if (!$placed) {
$highlightTweet .= $tag; $highlightTweet .= $tag;
} }
@ -183,6 +178,7 @@ class HitHighlighter extends Regex
} }
} }
} }
return $highlightTweet; return $highlightTweet;
} }
@ -193,6 +189,7 @@ class HitHighlighter extends Regex
* for the highlighting. * for the highlighting.
* *
* @return string The hit highlighted tweet. * @return string The hit highlighted tweet.
*
* @deprecated since version 1.1.0 * @deprecated since version 1.1.0
*/ */
public function addHitHighlighting(array $hits) public function addHitHighlighting(array $hits)

View file

@ -6,15 +6,12 @@
* @author Takashi Nojima * @author Takashi Nojima
* @copyright Copyright 2014 Mike Cochrane, Nick Pope, Takashi Nojima * @copyright Copyright 2014 Mike Cochrane, Nick Pope, Takashi Nojima
* @license http://www.apache.org/licenses/LICENSE-2.0 Apache License v2.0 * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License v2.0
* @package Twitter.Text
*/ */
namespace App\Util\Lexer; namespace App\Util\Lexer;
use App\Util\Lexer\Autolink;
/** /**
* Twitter LooseAutolink Class * Twitter LooseAutolink Class.
* *
* Parses tweets and generates HTML anchor tags around URLs, usernames, * Parses tweets and generates HTML anchor tags around URLs, usernames,
* username/list pairs and hashtags. * username/list pairs and hashtags.
@ -28,18 +25,19 @@ use App\Util\Lexer\Autolink;
* @author Takashi Nojima * @author Takashi Nojima
* @copyright Copyright 2014 Mike Cochrane, Nick Pope, Takashi Nojima * @copyright Copyright 2014 Mike Cochrane, Nick Pope, Takashi Nojima
* @license http://www.apache.org/licenses/LICENSE-2.0 Apache License v2.0 * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License v2.0
* @package Twitter.Text *
* @since 1.8.0 * @since 1.8.0
* @deprecated since version 1.9.0 * @deprecated since version 1.9.0
*/ */
class LooseAutolink extends Autolink class LooseAutolink extends Autolink
{ {
/** /**
* Auto-link hashtags, URLs, usernames and lists. * Auto-link hashtags, URLs, usernames and lists.
* *
* @param string The tweet to be converted * @param string The tweet to be converted
*
* @return string that auto-link HTML added * @return string that auto-link HTML added
*
* @deprecated since version 1.9.0 * @deprecated since version 1.9.0
*/ */
public function autoLink($tweet = null) public function autoLink($tweet = null)
@ -47,6 +45,7 @@ class LooseAutolink extends Autolink
if (!is_null($tweet)) { if (!is_null($tweet)) {
$this->tweet = $tweet; $this->tweet = $tweet;
} }
return $this->addLinks(); return $this->addLinks();
} }
@ -62,6 +61,7 @@ class LooseAutolink extends Autolink
if (!is_null($tweet)) { if (!is_null($tweet)) {
$this->tweet = $tweet; $this->tweet = $tweet;
} }
return $this->addLinksToUsernamesAndLists(); return $this->addLinksToUsernamesAndLists();
} }
@ -76,6 +76,7 @@ class LooseAutolink extends Autolink
if (!is_null($tweet)) { if (!is_null($tweet)) {
$this->tweet = $tweet; $this->tweet = $tweet;
} }
return $this->addLinksToHashtags(); return $this->addLinksToHashtags();
} }
@ -91,6 +92,7 @@ class LooseAutolink extends Autolink
if (!is_null($tweet)) { if (!is_null($tweet)) {
$this->tweet = $tweet; $this->tweet = $tweet;
} }
return $this->addLinksToURLs(); return $this->addLinksToURLs();
} }
@ -105,6 +107,7 @@ class LooseAutolink extends Autolink
if (!is_null($tweet)) { if (!is_null($tweet)) {
$this->tweet = $tweet; $this->tweet = $tweet;
} }
return $this->addLinksToCashtags(); return $this->addLinksToCashtags();
} }
@ -112,6 +115,7 @@ class LooseAutolink extends Autolink
* Adds links to all elements in the tweet. * Adds links to all elements in the tweet.
* *
* @return string The modified tweet. * @return string The modified tweet.
*
* @deprecated since version 1.9.0 * @deprecated since version 1.9.0
*/ */
public function addLinks() public function addLinks()
@ -123,6 +127,7 @@ class LooseAutolink extends Autolink
$this->tweet = $this->addLinksToUsernamesAndLists(); $this->tweet = $this->addLinksToUsernamesAndLists();
$modified = $this->tweet; $modified = $this->tweet;
$this->tweet = $original; $this->tweet = $original;
return $modified; return $modified;
} }
@ -135,7 +140,7 @@ class LooseAutolink extends Autolink
{ {
return preg_replace_callback( return preg_replace_callback(
self::$patterns['valid_hashtag'], self::$patterns['valid_hashtag'],
array($this, '_addLinksToHashtags'), [$this, '_addLinksToHashtags'],
$this->tweet $this->tweet
); );
} }
@ -149,7 +154,7 @@ class LooseAutolink extends Autolink
{ {
return preg_replace_callback( return preg_replace_callback(
self::$patterns['valid_cashtag'], self::$patterns['valid_cashtag'],
array($this, '_addLinksToCashtags'), [$this, '_addLinksToCashtags'],
$this->tweet $this->tweet
); );
} }
@ -161,7 +166,7 @@ class LooseAutolink extends Autolink
*/ */
public function addLinksToURLs() public function addLinksToURLs()
{ {
return preg_replace_callback(self::$patterns['valid_url'], array($this, '_addLinksToURLs'), $this->tweet); return preg_replace_callback(self::$patterns['valid_url'], [$this, '_addLinksToURLs'], $this->tweet);
} }
/** /**
@ -173,7 +178,7 @@ class LooseAutolink extends Autolink
{ {
return preg_replace_callback( return preg_replace_callback(
self::$patterns['valid_mentions_or_lists'], self::$patterns['valid_mentions_or_lists'],
array($this, '_addLinksToUsernamesAndLists'), [$this, '_addLinksToUsernamesAndLists'],
$this->tweet $this->tweet
); );
} }
@ -188,6 +193,7 @@ class LooseAutolink extends Autolink
* @param string $element The tweet element to wrap. * @param string $element The tweet element to wrap.
* *
* @return string The tweet element with a link applied. * @return string The tweet element with a link applied.
*
* @deprecated since version 1.1.0 * @deprecated since version 1.1.0
*/ */
protected function wrap($url, $class, $element) protected function wrap($url, $class, $element)
@ -197,7 +203,7 @@ class LooseAutolink extends Autolink
$link .= ' class="'.$class.'"'; $link .= ' class="'.$class.'"';
} }
$link .= ' href="'.$url.'"'; $link .= ' href="'.$url.'"';
$rel = array(); $rel = [];
if ($this->external) { if ($this->external) {
$rel[] = 'external'; $rel[] = 'external';
} }
@ -211,6 +217,7 @@ class LooseAutolink extends Autolink
$link .= ' target="'.$this->target.'"'; $link .= ' target="'.$this->target.'"';
} }
$link .= '>'.$element.'</a>'; $link .= '>'.$element.'</a>';
return $link; return $link;
} }
@ -234,7 +241,7 @@ class LooseAutolink extends Autolink
if ($class) { if ($class) {
$link .= ' class="'.$class.'"'; $link .= ' class="'.$class.'"';
} }
$rel = array(); $rel = [];
if ($this->external) { if ($this->external) {
$rel[] = 'external'; $rel[] = 'external';
} }
@ -248,6 +255,7 @@ class LooseAutolink extends Autolink
$link .= ' target="'.$this->target.'"'; $link .= ' target="'.$this->target.'"';
} }
$link .= '>'.$element.'</a>'; $link .= '>'.$element.'</a>';
return $link; return $link;
} }
@ -255,7 +263,9 @@ class LooseAutolink extends Autolink
* Callback used by the method that adds links to hashtags. * Callback used by the method that adds links to hashtags.
* *
* @see addLinksToHashtags() * @see addLinksToHashtags()
*
* @param array $matches The regular expression matches. * @param array $matches The regular expression matches.
*
* @return string The link-wrapped hashtag. * @return string The link-wrapped hashtag.
*/ */
protected function _addLinksToHashtags($matches) protected function _addLinksToHashtags($matches)
@ -273,6 +283,7 @@ class LooseAutolink extends Autolink
$class_hash .= ' rtl'; $class_hash .= ' rtl';
} }
$replacement .= $this->wrapHash($url, $class_hash, $element); $replacement .= $this->wrapHash($url, $class_hash, $element);
return $replacement; return $replacement;
} }
@ -280,7 +291,9 @@ class LooseAutolink extends Autolink
* Callback used by the method that adds links to cashtags. * Callback used by the method that adds links to cashtags.
* *
* @see addLinksToCashtags() * @see addLinksToCashtags()
*
* @param array $matches The regular expression matches. * @param array $matches The regular expression matches.
*
* @return string The link-wrapped cashtag. * @return string The link-wrapped cashtag.
*/ */
protected function _addLinksToCashtags($matches) protected function _addLinksToCashtags($matches)
@ -294,6 +307,7 @@ class LooseAutolink extends Autolink
$element = $cash.$tag; $element = $cash.$tag;
$url = $this->url_base_cash.$tag; $url = $this->url_base_cash.$tag;
$replacement .= $this->wrapHash($url, $this->class_cash, $element); $replacement .= $this->wrapHash($url, $this->class_cash, $element);
return $replacement; return $replacement;
} }
@ -301,7 +315,9 @@ class LooseAutolink extends Autolink
* Callback used by the method that adds links to URLs. * Callback used by the method that adds links to URLs.
* *
* @see addLinksToURLs() * @see addLinksToURLs()
*
* @param array $matches The regular expression matches. * @param array $matches The regular expression matches.
*
* @return string The link-wrapped URL. * @return string The link-wrapped URL.
*/ */
protected function _addLinksToURLs($matches) protected function _addLinksToURLs($matches)
@ -311,6 +327,7 @@ class LooseAutolink extends Autolink
if (!$protocol) { if (!$protocol) {
return $all; return $all;
} }
return $before.$this->wrap($url, $this->class_url, $url); return $before.$this->wrap($url, $this->class_url, $url);
} }
@ -318,15 +335,17 @@ class LooseAutolink extends Autolink
* Callback used by the method that adds links to username/list pairs. * Callback used by the method that adds links to username/list pairs.
* *
* @see addLinksToUsernamesAndLists() * @see addLinksToUsernamesAndLists()
*
* @param array $matches The regular expression matches. * @param array $matches The regular expression matches.
*
* @return string The link-wrapped username/list pair. * @return string The link-wrapped username/list pair.
*/ */
protected function _addLinksToUsernamesAndLists($matches) protected function _addLinksToUsernamesAndLists($matches)
{ {
list($all, $before, $at, $username, $slash_listname, $after) = array_pad($matches, 6, ''); list($all, $before, $at, $username, $slash_listname, $after) = array_pad($matches, 6, '');
# If $after is not empty, there is an invalid character. // If $after is not empty, there is an invalid character.
if (!empty($slash_listname)) { if (!empty($slash_listname)) {
# Replace the list and username // Replace the list and username
$element = $username.$slash_listname; $element = $username.$slash_listname;
$class = $this->class_list; $class = $this->class_list;
$url = $this->url_base_list.$element; $url = $this->url_base_list.$element;
@ -334,15 +353,15 @@ class LooseAutolink extends Autolink
if (preg_match(self::$patterns['end_mention_match'], $after)) { if (preg_match(self::$patterns['end_mention_match'], $after)) {
return $all; return $all;
} }
# Replace the username // Replace the username
$element = $username; $element = $username;
$class = $this->class_user; $class = $this->class_user;
$url = $this->url_base_user.$element; $url = $this->url_base_user.$element;
} }
# XXX: Due to use of preg_replace_callback() for multiple replacements in a // XXX: Due to use of preg_replace_callback() for multiple replacements in a
# single tweet and also as only the match is replaced and we have to // single tweet and also as only the match is replaced and we have to
# use a look-ahead for $after because there is no equivalent for the // use a look-ahead for $after because there is no equivalent for the
# $' (dollar apostrophe) global from Ruby, we MUST NOT append $after. // $' (dollar apostrophe) global from Ruby, we MUST NOT append $after.
return $before.$at.$this->wrap($url, $class, $element); return $before.$at.$this->wrap($url, $class, $element);
} }
} }

View file

@ -2,8 +2,8 @@
namespace App\Util\Lexer; namespace App\Util\Lexer;
class Nickname { class Nickname
{
public static function normalizeProfileUrl($url) public static function normalizeProfileUrl($url)
{ {
if (starts_with($url, 'acct:')) { if (starts_with($url, 'acct:')) {
@ -13,6 +13,7 @@ class Nickname {
if (!str_contains($url, '@') && filter_var($url, FILTER_VALIDATE_URL)) { if (!str_contains($url, '@') && filter_var($url, FILTER_VALIDATE_URL)) {
$parsed = parse_url($url); $parsed = parse_url($url);
$username = str_replace(['/', '\\', '@'], '', $parsed['path']); $username = str_replace(['/', '\\', '@'], '', $parsed['path']);
return ['domain' => $parsed['host'], 'username' => $username]; return ['domain' => $parsed['host'], 'username' => $username];
} }
$parts = explode('@', $url); $parts = explode('@', $url);
@ -34,9 +35,8 @@ class Nickname {
} else { } else {
$username = $part; $username = $part;
} }
} }
return ['domain' => $domain, 'username' => $username]; return ['domain' => $domain, 'username' => $username];
} }
} }

View file

@ -2,18 +2,20 @@
namespace App\Util\Lexer; namespace App\Util\Lexer;
class PrettyNumber { class PrettyNumber
{
public static function convert($expression) public static function convert($expression)
{ {
$abbrevs = array(12 => "T", 9 => "B", 6 => "M", 3 => "K", 0 => ""); $abbrevs = [12 => 'T', 9 => 'B', 6 => 'M', 3 => 'K', 0 => ''];
foreach ($abbrevs as $exponent => $abbrev) { foreach ($abbrevs as $exponent => $abbrev) {
if ($expression >= pow(10, $exponent)) { if ($expression >= pow(10, $exponent)) {
$display_num = $expression / pow(10, $exponent); $display_num = $expression / pow(10, $exponent);
$num = number_format($display_num, 0).$abbrev; $num = number_format($display_num, 0).$abbrev;
return $num; return $num;
} }
} }
return $expression; return $expression;
} }
@ -28,9 +30,10 @@ class PrettyNumber {
$units = $short ? $units = $short ?
['B', 'k', 'M', 'G', 'T', 'P', 'E', 'Z', 'Y'] : ['B', 'k', 'M', 'G', 'T', 'P', 'E', 'Z', 'Y'] :
['B', 'kB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB']; ['B', 'kB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'];
for($i = 0; ($size / 1024) > 0.9; $i++, $size /= 1024) {} for ($i = 0; ($size / 1024) > 0.9; $i++, $size /= 1024) {
}
$res = round($size, $precision).$units[$i]; $res = round($size, $precision).$units[$i];
return $res; return $res;
} }
} }

View file

@ -5,13 +5,12 @@
* @author Nick Pope <nick@nickpope.me.uk> * @author Nick Pope <nick@nickpope.me.uk>
* @copyright Copyright © 2010, Mike Cochrane, Nick Pope * @copyright Copyright © 2010, Mike Cochrane, Nick Pope
* @license http://www.apache.org/licenses/LICENSE-2.0 Apache License v2.0 * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License v2.0
* @package Twitter.Text
*/ */
namespace App\Util\Lexer; namespace App\Util\Lexer;
/** /**
* Twitter Regex Abstract Class * Twitter Regex Abstract Class.
* *
* Used by subclasses that need to parse tweets. * Used by subclasses that need to parse tweets.
* *
@ -23,17 +22,15 @@ namespace App\Util\Lexer;
* @author Nick Pope <nick@nickpope.me.uk> * @author Nick Pope <nick@nickpope.me.uk>
* @copyright Copyright © 2010, Mike Cochrane, Nick Pope * @copyright Copyright © 2010, Mike Cochrane, Nick Pope
* @license http://www.apache.org/licenses/LICENSE-2.0 Apache License v2.0 * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License v2.0
* @package Twitter
*/ */
abstract class Regex abstract class Regex
{ {
/** /**
* Contains all generated regular expressions. * Contains all generated regular expressions.
* *
* @var string The regex patterns. * @var string The regex patterns.
*/ */
protected static $patterns = array(); protected static $patterns = [];
/** /**
* The tweet to be used in parsing. This should be populated by the * The tweet to be used in parsing. This should be populated by the
@ -58,99 +55,99 @@ abstract class Regex
*/ */
public static function __static() public static function __static()
{ {
# Check whether we have initialized the regular expressions: // Check whether we have initialized the regular expressions:
static $initialized = false; static $initialized = false;
if ($initialized) { if ($initialized) {
return; return;
} }
# Get a shorter reference to the regular expression array: // Get a shorter reference to the regular expression array:
$re = &self::$patterns; $re = &self::$patterns;
# Initialise local storage arrays: // Initialise local storage arrays:
$tmp = array(); $tmp = [];
# Expression to match whitespace characters. // Expression to match whitespace characters.
# //
# 0x0009-0x000D Cc # <control-0009>..<control-000D> // 0x0009-0x000D Cc # <control-0009>..<control-000D>
# 0x0020 Zs # SPACE // 0x0020 Zs # SPACE
# 0x0085 Cc # <control-0085> // 0x0085 Cc # <control-0085>
# 0x00A0 Zs # NO-BREAK SPACE // 0x00A0 Zs # NO-BREAK SPACE
# 0x1680 Zs # OGHAM SPACE MARK // 0x1680 Zs # OGHAM SPACE MARK
# 0x180E Zs # MONGOLIAN VOWEL SEPARATOR // 0x180E Zs # MONGOLIAN VOWEL SEPARATOR
# 0x2000-0x200A Zs # EN QUAD..HAIR SPACE // 0x2000-0x200A Zs # EN QUAD..HAIR SPACE
# 0x2028 Zl # LINE SEPARATOR // 0x2028 Zl # LINE SEPARATOR
# 0x2029 Zp # PARAGRAPH SEPARATOR // 0x2029 Zp # PARAGRAPH SEPARATOR
# 0x202F Zs # NARROW NO-BREAK SPACE // 0x202F Zs # NARROW NO-BREAK SPACE
# 0x205F Zs # MEDIUM MATHEMATICAL SPACE // 0x205F Zs # MEDIUM MATHEMATICAL SPACE
# 0x3000 Zs # IDEOGRAPHIC SPACE // 0x3000 Zs # IDEOGRAPHIC SPACE
$tmp['spaces'] = '\x{0009}-\x{000D}\x{0020}\x{0085}\x{00a0}\x{1680}\x{180E}\x{2000}-\x{200a}\x{2028}\x{2029}\x{202f}\x{205f}\x{3000}'; $tmp['spaces'] = '\x{0009}-\x{000D}\x{0020}\x{0085}\x{00a0}\x{1680}\x{180E}\x{2000}-\x{200a}\x{2028}\x{2029}\x{202f}\x{205f}\x{3000}';
# Invalid Characters: // Invalid Characters:
# 0xFFFE,0xFEFF # BOM // 0xFFFE,0xFEFF # BOM
# 0xFFFF # Special // 0xFFFF # Special
# 0x202A-0x202E # Directional change // 0x202A-0x202E # Directional change
$tmp['invalid_characters'] = '\x{202a}-\x{202e}\x{feff}\x{fffe}\x{ffff}'; $tmp['invalid_characters'] = '\x{202a}-\x{202e}\x{feff}\x{fffe}\x{ffff}';
# Expression to match at and hash sign characters: // Expression to match at and hash sign characters:
$tmp['at_signs'] = '@'; $tmp['at_signs'] = '@';
$tmp['hash_signs'] = '#'; $tmp['hash_signs'] = '#';
# Expression to match latin accented characters. // Expression to match latin accented characters.
# //
# 0x00C0-0x00D6 // 0x00C0-0x00D6
# 0x00D8-0x00F6 // 0x00D8-0x00F6
# 0x00F8-0x00FF // 0x00F8-0x00FF
# 0x0100-0x024f // 0x0100-0x024f
# 0x0253-0x0254 // 0x0253-0x0254
# 0x0256-0x0257 // 0x0256-0x0257
# 0x0259 // 0x0259
# 0x025b // 0x025b
# 0x0263 // 0x0263
# 0x0268 // 0x0268
# 0x026f // 0x026f
# 0x0272 // 0x0272
# 0x0289 // 0x0289
# 0x028b // 0x028b
# 0x02bb // 0x02bb
# 0x0300-0x036f // 0x0300-0x036f
# 0x1e00-0x1eff // 0x1e00-0x1eff
# //
# Excludes 0x00D7 - multiplication sign (confusable with 'x'). // Excludes 0x00D7 - multiplication sign (confusable with 'x').
# Excludes 0x00F7 - division sign. // Excludes 0x00F7 - division sign.
$tmp['latin_accents'] = '\x{00c0}-\x{00d6}\x{00d8}-\x{00f6}\x{00f8}-\x{00ff}'; $tmp['latin_accents'] = '\x{00c0}-\x{00d6}\x{00d8}-\x{00f6}\x{00f8}-\x{00ff}';
$tmp['latin_accents'] .= '\x{0100}-\x{024f}\x{0253}-\x{0254}\x{0256}-\x{0257}'; $tmp['latin_accents'] .= '\x{0100}-\x{024f}\x{0253}-\x{0254}\x{0256}-\x{0257}';
$tmp['latin_accents'] .= '\x{0259}\x{025b}\x{0263}\x{0268}\x{026f}\x{0272}\x{0289}\x{028b}\x{02bb}\x{0300}-\x{036f}\x{1e00}-\x{1eff}'; $tmp['latin_accents'] .= '\x{0259}\x{025b}\x{0263}\x{0268}\x{026f}\x{0272}\x{0289}\x{028b}\x{02bb}\x{0300}-\x{036f}\x{1e00}-\x{1eff}';
# Expression to match RTL characters. // Expression to match RTL characters.
# //
# 0x0600-0x06FF Arabic // 0x0600-0x06FF Arabic
# 0x0750-0x077F Arabic Supplement // 0x0750-0x077F Arabic Supplement
# 0x08A0-0x08FF Arabic Extended-A // 0x08A0-0x08FF Arabic Extended-A
# 0x0590-0x05FF Hebrew // 0x0590-0x05FF Hebrew
# 0xFB50-0xFDFF Arabic Presentation Forms-A // 0xFB50-0xFDFF Arabic Presentation Forms-A
# 0xFE70-0xFEFF Arabic Presentation Forms-B // 0xFE70-0xFEFF Arabic Presentation Forms-B
$tmp['rtl_chars'] = '\x{0600}-\x{06ff}\x{0750}-\x{077f}\x{08a0}-\x{08ff}\x{0590}-\x{05ff}\x{fb50}-\x{fdff}\x{fe70}-\x{feff}'; $tmp['rtl_chars'] = '\x{0600}-\x{06ff}\x{0750}-\x{077f}\x{08a0}-\x{08ff}\x{0590}-\x{05ff}\x{fb50}-\x{fdff}\x{fe70}-\x{feff}';
$tmp['hashtag_letters'] = '\p{L}\p{M}'; $tmp['hashtag_letters'] = '\p{L}\p{M}';
$tmp['hashtag_numerals'] = '\p{Nd}'; $tmp['hashtag_numerals'] = '\p{Nd}';
# Hashtag special chars // Hashtag special chars
# //
# _ underscore // _ underscore
# 0x200c ZERO WIDTH NON-JOINER (ZWNJ) // 0x200c ZERO WIDTH NON-JOINER (ZWNJ)
# 0x200d ZERO WIDTH JOINER (ZWJ) // 0x200d ZERO WIDTH JOINER (ZWJ)
# 0xa67e CYRILLIC KAVYKA // 0xa67e CYRILLIC KAVYKA
# 0x05be HEBREW PUNCTUATION MAQAF // 0x05be HEBREW PUNCTUATION MAQAF
# 0x05f3 HEBREW PUNCTUATION GERESH // 0x05f3 HEBREW PUNCTUATION GERESH
# 0x05f4 HEBREW PUNCTUATION GERSHAYIM // 0x05f4 HEBREW PUNCTUATION GERSHAYIM
# 0xff5e FULLWIDTH TILDE // 0xff5e FULLWIDTH TILDE
# 0x301c WAVE DASH // 0x301c WAVE DASH
# 0x309b KATAKANA-HIRAGANA VOICED SOUND MARK // 0x309b KATAKANA-HIRAGANA VOICED SOUND MARK
# 0x309c KATAKANA-HIRAGANA SEMI-VOICED SOUND MARK // 0x309c KATAKANA-HIRAGANA SEMI-VOICED SOUND MARK
# 0x30a0 KATAKANA-HIRAGANA DOUBLE HYPHEN // 0x30a0 KATAKANA-HIRAGANA DOUBLE HYPHEN
# 0x30fb KATAKANA MIDDLE DOT // 0x30fb KATAKANA MIDDLE DOT
# 0x3003 DITTO MARK // 0x3003 DITTO MARK
# 0x0f0b TIBETAN MARK INTERSYLLABIC TSHEG // 0x0f0b TIBETAN MARK INTERSYLLABIC TSHEG
# 0x0f0c TIBETAN MARK DELIMITER TSHEG BSTAR // 0x0f0c TIBETAN MARK DELIMITER TSHEG BSTAR
# 0x00b7 MIDDLE DOT // 0x00b7 MIDDLE DOT
$tmp['hashtag_special_chars'] = '_\x{200c}\x{200d}\x{a67e}\x{05be}\x{05f3}\x{05f4}\x{ff5e}\x{301c}\x{309b}\x{309c}\x{30a0}\x{30fb}\x{3003}\x{0f0b}\x{0f0c}\x{00b7}'; $tmp['hashtag_special_chars'] = '_\x{200c}\x{200d}\x{a67e}\x{05be}\x{05f3}\x{05f4}\x{ff5e}\x{301c}\x{309b}\x{309c}\x{30a0}\x{30fb}\x{3003}\x{0f0b}\x{0f0c}\x{00b7}';
$tmp['hashtag_letters_numerals_set'] = '['.$tmp['hashtag_letters'].$tmp['hashtag_numerals'].$tmp['hashtag_special_chars'].']'; $tmp['hashtag_letters_numerals_set'] = '['.$tmp['hashtag_letters'].$tmp['hashtag_numerals'].$tmp['hashtag_special_chars'].']';
$tmp['hashtag_letters_set'] = '['.$tmp['hashtag_letters'].']'; $tmp['hashtag_letters_set'] = '['.$tmp['hashtag_letters'].']';
@ -160,15 +157,15 @@ abstract class Regex
$re['valid_hashtag'] = '/'.$tmp['hashtag'].'(?=(.*|$))/iu'; $re['valid_hashtag'] = '/'.$tmp['hashtag'].'(?=(.*|$))/iu';
$re['end_hashtag_match'] = '/\A(?:['.$tmp['hash_signs'].']|:\/\/)/u'; $re['end_hashtag_match'] = '/\A(?:['.$tmp['hash_signs'].']|:\/\/)/u';
# XXX: PHP doesn't have Ruby's $' (dollar apostrophe) so we have to capture // XXX: PHP doesn't have Ruby's $' (dollar apostrophe) so we have to capture
# $after in the following regular expression. Note that we only use a // $after in the following regular expression. Note that we only use a
# look-ahead capture here and don't append $after when we return. // look-ahead capture here and don't append $after when we return.
$tmp['valid_mention_preceding_chars'] = '([^a-zA-Z0-9_!#\$%&*@\/]|^|(?:^|[^a-z0-9_+~.-])RT:?)'; $tmp['valid_mention_preceding_chars'] = '([^a-zA-Z0-9_!#\$%&*@\/]|^|(?:^|[^a-z0-9_+~.-])RT:?)';
$re['valid_mentions_or_lists'] = '/'.$tmp['valid_mention_preceding_chars'].'(['.$tmp['at_signs'].'])([a-z0-9_]{1,20})(\/[a-z][a-z0-9_\-]{0,24})?(?=(.*|$))/iu'; $re['valid_mentions_or_lists'] = '/'.$tmp['valid_mention_preceding_chars'].'(['.$tmp['at_signs'].'])([a-z0-9_]{1,20})(\/[a-z][a-z0-9_\-]{0,24})?(?=(.*|$))/iu';
$re['valid_reply'] = '/^(?:['.$tmp['spaces'].'])*['.$tmp['at_signs'].']([a-z0-9_]{1,20})(?=(.*|$))/iu'; $re['valid_reply'] = '/^(?:['.$tmp['spaces'].'])*['.$tmp['at_signs'].']([a-z0-9_]{1,20})(?=(.*|$))/iu';
$re['end_mention_match'] = '/\A(?:['.$tmp['at_signs'].']|['.$tmp['latin_accents'].']|:\/\/)/iu'; $re['end_mention_match'] = '/\A(?:['.$tmp['at_signs'].']|['.$tmp['latin_accents'].']|:\/\/)/iu';
# URL related hash regex collection // URL related hash regex collection
$tmp['valid_url_preceding_chars'] = '(?:[^A-Z0-9_@\$#\.'.$tmp['invalid_characters'].']|^)'; $tmp['valid_url_preceding_chars'] = '(?:[^A-Z0-9_@\$#\.'.$tmp['invalid_characters'].']|^)';
@ -204,13 +201,13 @@ abstract class Regex
.'|(?:' // domain + ccTLD + '/' .'|(?:' // domain + ccTLD + '/'
.$tmp['valid_domain_name'].$tmp['valid_ccTLD'].'(?=\/)' // e.g. t.co/ .$tmp['valid_domain_name'].$tmp['valid_ccTLD'].'(?=\/)' // e.g. t.co/
.')'; .')';
# Used by the extractor: // Used by the extractor:
$re['valid_ascii_domain'] = '/'.$tmp['valid_subdomain'].'*'.$tmp['valid_domain_name'].'(?:'.$tmp['valid_gTLD'].'|'.$tmp['valid_ccTLD'].'|'.$tmp['valid_punycode'].')/iu'; $re['valid_ascii_domain'] = '/'.$tmp['valid_subdomain'].'*'.$tmp['valid_domain_name'].'(?:'.$tmp['valid_gTLD'].'|'.$tmp['valid_ccTLD'].'|'.$tmp['valid_punycode'].')/iu';
# Used by the extractor for stricter t.co URL extraction: // Used by the extractor for stricter t.co URL extraction:
$re['valid_tco_url'] = '/^https?:\/\/t\.co\/[a-z0-9]+/iu'; $re['valid_tco_url'] = '/^https?:\/\/t\.co\/[a-z0-9]+/iu';
# Used by the extractor to filter out unwanted URLs: // Used by the extractor to filter out unwanted URLs:
$re['invalid_short_domain'] = '/\A'.$tmp['valid_domain_name'].$tmp['valid_ccTLD'].'\Z/iu'; $re['invalid_short_domain'] = '/\A'.$tmp['valid_domain_name'].$tmp['valid_ccTLD'].'\Z/iu';
$re['valid_special_short_domain'] = '/\A'.$tmp['valid_domain_name'].$tmp['valid_special_ccTLD'].'\Z/iu'; $re['valid_special_short_domain'] = '/\A'.$tmp['valid_domain_name'].$tmp['valid_special_ccTLD'].'\Z/iu';
$re['invalid_url_without_protocol_preceding_chars'] = '/[\-_.\/]\z/iu'; $re['invalid_url_without_protocol_preceding_chars'] = '/[\-_.\/]\z/iu';
@ -218,10 +215,10 @@ abstract class Regex
$tmp['valid_port_number'] = '[0-9]+'; $tmp['valid_port_number'] = '[0-9]+';
$tmp['valid_general_url_path_chars'] = '[a-z\p{Cyrillic}0-9!\*;:=\+\,\.\$\/%#\[\]\-_~&|@'.$tmp['latin_accents'].']'; $tmp['valid_general_url_path_chars'] = '[a-z\p{Cyrillic}0-9!\*;:=\+\,\.\$\/%#\[\]\-_~&|@'.$tmp['latin_accents'].']';
# Allow URL paths to contain up to two nested levels of balanced parentheses: // Allow URL paths to contain up to two nested levels of balanced parentheses:
# 1. Used in Wikipedia URLs, e.g. /Primer_(film) // 1. Used in Wikipedia URLs, e.g. /Primer_(film)
# 2. Used in IIS sessions, e.g. /S(dfd346)/ // 2. Used in IIS sessions, e.g. /S(dfd346)/
# 3. Used in Rdio URLs like /track/We_Up_(Album_Version_(Edited))/ // 3. Used in Rdio URLs like /track/We_Up_(Album_Version_(Edited))/
$tmp['valid_url_balanced_parens'] = '(?:\(' $tmp['valid_url_balanced_parens'] = '(?:\('
.'(?:'.$tmp['valid_general_url_path_chars'].'+' .'(?:'.$tmp['valid_general_url_path_chars'].'+'
.'|' .'|'
@ -233,8 +230,8 @@ abstract class Regex
.')' .')'
.')' .')'
.'\))'; .'\))';
# Valid end-of-path characters (so /foo. does not gobble the period). // Valid end-of-path characters (so /foo. does not gobble the period).
# 1. Allow =&# for empty URL parameters and other URL-join artifacts. // 1. Allow =&# for empty URL parameters and other URL-join artifacts.
$tmp['valid_url_path_ending_chars'] = '[a-z\p{Cyrillic}0-9=_#\/\+\-'.$tmp['latin_accents'].']|(?:'.$tmp['valid_url_balanced_parens'].')'; $tmp['valid_url_path_ending_chars'] = '[a-z\p{Cyrillic}0-9=_#\/\+\-'.$tmp['latin_accents'].']|(?:'.$tmp['valid_url_balanced_parens'].')';
$tmp['valid_url_path'] = '(?:(?:' $tmp['valid_url_path'] = '(?:(?:'
.$tmp['valid_general_url_path_chars'].'*(?:' .$tmp['valid_general_url_path_chars'].'*(?:'
@ -246,14 +243,14 @@ abstract class Regex
$tmp['valid_url_query_chars'] = '[a-z0-9!?\*\'\(\);:&=\+\$\/%#\[\]\-_\.,~|@]'; $tmp['valid_url_query_chars'] = '[a-z0-9!?\*\'\(\);:&=\+\$\/%#\[\]\-_\.,~|@]';
$tmp['valid_url_query_ending_chars'] = '[a-z0-9_&=#\/\-]'; $tmp['valid_url_query_ending_chars'] = '[a-z0-9_&=#\/\-]';
$re['valid_url'] = '/(?:' # $1 Complete match (preg_match() already matches everything.) $re['valid_url'] = '/(?:' // $1 Complete match (preg_match() already matches everything.)
. '(' . $tmp['valid_url_preceding_chars'] . ')' # $2 Preceding characters .'('.$tmp['valid_url_preceding_chars'].')' // $2 Preceding characters
. '(' # $3 Complete URL .'(' // $3 Complete URL
. '(https?:\/\/)?' # $4 Protocol (optional) .'(https?:\/\/)?' // $4 Protocol (optional)
. '(' . $tmp['valid_domain'] . ')' # $5 Domain(s) .'('.$tmp['valid_domain'].')' // $5 Domain(s)
. '(?::(' . $tmp['valid_port_number'] . '))?' # $6 Port number (optional) .'(?::('.$tmp['valid_port_number'].'))?' // $6 Port number (optional)
. '(\/' . $tmp['valid_url_path'] . '*)?' # $7 URL Path .'(\/'.$tmp['valid_url_path'].'*)?' // $7 URL Path
. '(\?' . $tmp['valid_url_query_chars'] . '*' . $tmp['valid_url_query_ending_chars'] . ')?' # $8 Query String .'(\?'.$tmp['valid_url_query_chars'].'*'.$tmp['valid_url_query_ending_chars'].')?' // $8 Query String
.')' .')'
.')/iux'; .')/iux';
@ -262,47 +259,47 @@ abstract class Regex
$re['valid_cashtag'] = '/(^|['.$tmp['spaces'].'])(['.$tmp['cash_signs'].'])('.$tmp['cashtag'].')(?=($|\s|[[:punct:]]))/iu'; $re['valid_cashtag'] = '/(^|['.$tmp['spaces'].'])(['.$tmp['cash_signs'].'])('.$tmp['cashtag'].')(?=($|\s|[[:punct:]]))/iu';
$re['end_cashtag_match'] = '/\A(?:['.$tmp['cash_signs'].']|:\/\/)/u'; $re['end_cashtag_match'] = '/\A(?:['.$tmp['cash_signs'].']|:\/\/)/u';
# These URL validation pattern strings are based on the ABNF from RFC 3986 // These URL validation pattern strings are based on the ABNF from RFC 3986
$tmp['validate_url_unreserved'] = '[a-z\p{Cyrillic}0-9\-._~]'; $tmp['validate_url_unreserved'] = '[a-z\p{Cyrillic}0-9\-._~]';
$tmp['validate_url_pct_encoded'] = '(?:%[0-9a-f]{2})'; $tmp['validate_url_pct_encoded'] = '(?:%[0-9a-f]{2})';
$tmp['validate_url_sub_delims'] = '[!$&\'()*+,;=]'; $tmp['validate_url_sub_delims'] = '[!$&\'()*+,;=]';
$tmp['validate_url_pchar'] = '(?:' . $tmp['validate_url_unreserved'] . '|' . $tmp['validate_url_pct_encoded'] . '|' . $tmp['validate_url_sub_delims'] . '|[:\|@])'; #/iox $tmp['validate_url_pchar'] = '(?:'.$tmp['validate_url_unreserved'].'|'.$tmp['validate_url_pct_encoded'].'|'.$tmp['validate_url_sub_delims'].'|[:\|@])'; ///iox
$tmp['validate_url_userinfo'] = '(?:' . $tmp['validate_url_unreserved'] . '|' . $tmp['validate_url_pct_encoded'] . '|' . $tmp['validate_url_sub_delims'] . '|:)*'; #/iox $tmp['validate_url_userinfo'] = '(?:'.$tmp['validate_url_unreserved'].'|'.$tmp['validate_url_pct_encoded'].'|'.$tmp['validate_url_sub_delims'].'|:)*'; ///iox
$tmp['validate_url_dec_octet'] = '(?:[0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])'; #/i $tmp['validate_url_dec_octet'] = '(?:[0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])'; ///i
$tmp['validate_url_ipv4'] = '(?:' . $tmp['validate_url_dec_octet'] . '(?:\.' . $tmp['validate_url_dec_octet'] . '){3})'; #/iox $tmp['validate_url_ipv4'] = '(?:'.$tmp['validate_url_dec_octet'].'(?:\.'.$tmp['validate_url_dec_octet'].'){3})'; ///iox
# Punting on real IPv6 validation for now // Punting on real IPv6 validation for now
$tmp['validate_url_ipv6'] = '(?:\[[a-f0-9:\.]+\])'; #/i $tmp['validate_url_ipv6'] = '(?:\[[a-f0-9:\.]+\])'; ///i
# Also punting on IPvFuture for now // Also punting on IPvFuture for now
$tmp['validate_url_ip'] = '(?:' . $tmp['validate_url_ipv4'] . '|' . $tmp['validate_url_ipv6'] . ')'; #/iox $tmp['validate_url_ip'] = '(?:'.$tmp['validate_url_ipv4'].'|'.$tmp['validate_url_ipv6'].')'; ///iox
# This is more strict than the rfc specifies // This is more strict than the rfc specifies
$tmp['validate_url_subdomain_segment'] = '(?:[a-z0-9](?:[a-z0-9_\-]*[a-z0-9])?)'; #/i $tmp['validate_url_subdomain_segment'] = '(?:[a-z0-9](?:[a-z0-9_\-]*[a-z0-9])?)'; ///i
$tmp['validate_url_domain_segment'] = '(?:[a-z0-9](?:[a-z0-9\-]*[a-z0-9])?)'; #/i $tmp['validate_url_domain_segment'] = '(?:[a-z0-9](?:[a-z0-9\-]*[a-z0-9])?)'; ///i
$tmp['validate_url_domain_tld'] = '(?:[a-z](?:[a-z0-9\-]*[a-z0-9])?)'; #/i $tmp['validate_url_domain_tld'] = '(?:[a-z](?:[a-z0-9\-]*[a-z0-9])?)'; ///i
$tmp['validate_url_domain'] = '(?:(?:' . $tmp['validate_url_subdomain_segment'] . '\.)*(?:' . $tmp['validate_url_domain_segment'] . '\.)' . $tmp['validate_url_domain_tld'] . ')'; #/iox $tmp['validate_url_domain'] = '(?:(?:'.$tmp['validate_url_subdomain_segment'].'\.)*(?:'.$tmp['validate_url_domain_segment'].'\.)'.$tmp['validate_url_domain_tld'].')'; ///iox
$tmp['validate_url_host'] = '(?:' . $tmp['validate_url_ip'] . '|' . $tmp['validate_url_domain'] . ')'; #/iox $tmp['validate_url_host'] = '(?:'.$tmp['validate_url_ip'].'|'.$tmp['validate_url_domain'].')'; ///iox
# Unencoded internationalized domains - this doesn't check for invalid UTF-8 sequences // Unencoded internationalized domains - this doesn't check for invalid UTF-8 sequences
$tmp['validate_url_unicode_subdomain_segment'] = '(?:(?:[a-z0-9]|[^\x00-\x7f])(?:(?:[a-z0-9_\-]|[^\x00-\x7f])*(?:[a-z0-9]|[^\x00-\x7f]))?)'; #/ix $tmp['validate_url_unicode_subdomain_segment'] = '(?:(?:[a-z0-9]|[^\x00-\x7f])(?:(?:[a-z0-9_\-]|[^\x00-\x7f])*(?:[a-z0-9]|[^\x00-\x7f]))?)'; ///ix
$tmp['validate_url_unicode_domain_segment'] = '(?:(?:[a-z0-9]|[^\x00-\x7f])(?:(?:[a-z0-9\-]|[^\x00-\x7f])*(?:[a-z0-9]|[^\x00-\x7f]))?)'; #/ix $tmp['validate_url_unicode_domain_segment'] = '(?:(?:[a-z0-9]|[^\x00-\x7f])(?:(?:[a-z0-9\-]|[^\x00-\x7f])*(?:[a-z0-9]|[^\x00-\x7f]))?)'; ///ix
$tmp['validate_url_unicode_domain_tld'] = '(?:(?:[a-z]|[^\x00-\x7f])(?:(?:[a-z0-9\-]|[^\x00-\x7f])*(?:[a-z0-9]|[^\x00-\x7f]))?)'; #/ix $tmp['validate_url_unicode_domain_tld'] = '(?:(?:[a-z]|[^\x00-\x7f])(?:(?:[a-z0-9\-]|[^\x00-\x7f])*(?:[a-z0-9]|[^\x00-\x7f]))?)'; ///ix
$tmp['validate_url_unicode_domain'] = '(?:(?:' . $tmp['validate_url_unicode_subdomain_segment'] . '\.)*(?:' . $tmp['validate_url_unicode_domain_segment'] . '\.)' . $tmp['validate_url_unicode_domain_tld'] . ')'; #/iox $tmp['validate_url_unicode_domain'] = '(?:(?:'.$tmp['validate_url_unicode_subdomain_segment'].'\.)*(?:'.$tmp['validate_url_unicode_domain_segment'].'\.)'.$tmp['validate_url_unicode_domain_tld'].')'; ///iox
$tmp['validate_url_unicode_host'] = '(?:' . $tmp['validate_url_ip'] . '|' . $tmp['validate_url_unicode_domain'] . ')'; #/iox $tmp['validate_url_unicode_host'] = '(?:'.$tmp['validate_url_ip'].'|'.$tmp['validate_url_unicode_domain'].')'; ///iox
$tmp['validate_url_port'] = '[0-9]{1,5}'; $tmp['validate_url_port'] = '[0-9]{1,5}';
$re['validate_url_unicode_authority'] = '/' $re['validate_url_unicode_authority'] = '/'
. '(?:(' . $tmp['validate_url_userinfo'] . ')@)?' # $1 userinfo .'(?:('.$tmp['validate_url_userinfo'].')@)?' // $1 userinfo
. '(' . $tmp['validate_url_unicode_host'] . ')' # $2 host .'('.$tmp['validate_url_unicode_host'].')' // $2 host
. '(?::(' . $tmp['validate_url_port'] . '))?' # $3 port .'(?::('.$tmp['validate_url_port'].'))?' // $3 port
.'/iux'; .'/iux';
$re['validate_url_authority'] = '/' $re['validate_url_authority'] = '/'
. '(?:(' . $tmp['validate_url_userinfo'] . ')@)?' # $1 userinfo .'(?:('.$tmp['validate_url_userinfo'].')@)?' // $1 userinfo
. '(' . $tmp['validate_url_host'] . ')' # $2 host .'('.$tmp['validate_url_host'].')' // $2 host
. '(?::(' . $tmp['validate_url_port'] . '))?' # $3 port .'(?::('.$tmp['validate_url_port'].'))?' // $3 port
.'/ix'; .'/ix';
$re['validate_url_scheme'] = '/(?:[a-z][a-z0-9+\-.]*)/i'; $re['validate_url_scheme'] = '/(?:[a-z][a-z0-9+\-.]*)/i';
@ -310,28 +307,28 @@ abstract class Regex
$re['validate_url_query'] = '/('.$tmp['validate_url_pchar'].'|\/|\?)*/iu'; $re['validate_url_query'] = '/('.$tmp['validate_url_pchar'].'|\/|\?)*/iu';
$re['validate_url_fragment'] = '/('.$tmp['validate_url_pchar'].'|\/|\?)*/iu'; $re['validate_url_fragment'] = '/('.$tmp['validate_url_pchar'].'|\/|\?)*/iu';
# Modified version of RFC 3986 Appendix B // Modified version of RFC 3986 Appendix B
$re['validate_url_unencoded'] = '/^' # Full URL $re['validate_url_unencoded'] = '/^' // Full URL
.'(?:' .'(?:'
. '([^:\/?#]+):\/\/' # $1 Scheme .'([^:\/?#]+):\/\/' // $1 Scheme
.')?' .')?'
. '([^\/?#]*)' # $2 Authority .'([^\/?#]*)' // $2 Authority
. '([^?#]*)' # $3 Path .'([^?#]*)' // $3 Path
.'(?:' .'(?:'
. '\?([^#]*)' # $4 Query .'\?([^#]*)' // $4 Query
.')?' .')?'
.'(?:' .'(?:'
. '\#(.*)' # $5 Fragment .'\#(.*)' // $5 Fragment
.')?$/iux'; .')?$/iux';
$re['invalid_characters'] = '/['.$tmp['invalid_characters'].']/u'; $re['invalid_characters'] = '/['.$tmp['invalid_characters'].']/u';
$re['rtl_chars'] = '/['.$tmp['rtl_chars'].']/iu'; $re['rtl_chars'] = '/['.$tmp['rtl_chars'].']/iu';
# Flag that initialization is complete: // Flag that initialization is complete:
$initialized = true; $initialized = true;
} }
} }
# Cause regular expressions to be initialized as soon as this file is loaded: // Cause regular expressions to be initialized as soon as this file is loaded:
Regex::__static(); Regex::__static();

View file

@ -2,170 +2,169 @@
namespace App\Util\Lexer; namespace App\Util\Lexer;
class RestrictedNames { class RestrictedNames
{
static $blacklist = [ public static $blacklist = [
"about", 'about',
"abuse", 'abuse',
"administrator", 'administrator',
"app", 'app',
"autoconfig", 'autoconfig',
"blog", 'blog',
"broadcasthost", 'broadcasthost',
"community", 'community',
"contact", 'contact',
"contact-us", 'contact-us',
"contact_us", 'contact_us',
"copyright", 'copyright',
"d", 'd',
"dashboard", 'dashboard',
"dev", 'dev',
"developer", 'developer',
"developers", 'developers',
"discover", 'discover',
"discovers", 'discovers',
"doc", 'doc',
"docs", 'docs',
"download", 'download',
"domainadmin", 'domainadmin',
"domainadministrator", 'domainadministrator',
"email", 'email',
"errors", 'errors',
"events", 'events',
"example", 'example',
"faq", 'faq',
"faqs", 'faqs',
"features", 'features',
"ftp", 'ftp',
"guest", 'guest',
"guests", 'guests',
"help", 'help',
"hostmaster", 'hostmaster',
"hostmaster", 'hostmaster',
"image", 'image',
"images", 'images',
"imap", 'imap',
"img", 'img',
"info", 'info',
"info", 'info',
"is", 'is',
"isatap", 'isatap',
"it", 'it',
"localdomain", 'localdomain',
"localhost", 'localhost',
"mail", 'mail',
"mailer-daemon", 'mailer-daemon',
"mailerdaemon", 'mailerdaemon',
"marketing", 'marketing',
"me", 'me',
"media", 'media',
"mis", 'mis',
"mx", 'mx',
"new", 'new',
"news", 'news',
"news", 'news',
"no-reply", 'no-reply',
"nobody", 'nobody',
"noc", 'noc',
"noreply", 'noreply',
"ns0", 'ns0',
"ns1", 'ns1',
"ns2", 'ns2',
"ns3", 'ns3',
"ns4", 'ns4',
"ns5", 'ns5',
"ns6", 'ns6',
"ns7", 'ns7',
"ns8", 'ns8',
"ns9", 'ns9',
"owner", 'owner',
"pop", 'pop',
"pop3", 'pop3',
"postmaster", 'postmaster',
"pricing", 'pricing',
"privacy", 'privacy',
"root", 'root',
"sales", 'sales',
"security", 'security',
"signin", 'signin',
"signout", 'signout',
"smtp", 'smtp',
"src", 'src',
"ssladmin", 'ssladmin',
"ssladministrator", 'ssladministrator',
"sslwebmaster", 'sslwebmaster',
"status", 'status',
"support", 'support',
"support", 'support',
"sys", 'sys',
"sysadmin", 'sysadmin',
"system", 'system',
"terms", 'terms',
"tutorial", 'tutorial',
"tutorials", 'tutorials',
"usenet", 'usenet',
"uucp", 'uucp',
"webmaster", 'webmaster',
"wpad", 'wpad',
"www" 'www',
]; ];
static $reserved = [ public static $reserved = [
// Reserved for instance admin // Reserved for instance admin
"admin", 'admin',
// Static Assets // Static Assets
"assets", 'assets',
"storage", 'storage',
// Laravel Horizon // Laravel Horizon
"horizon", 'horizon',
// Reserved routes // Reserved routes
"account", 'account',
"api", 'api',
"auth", 'auth',
"css", 'css',
"c", 'c',
"i", 'i',
"dashboard", 'dashboard',
"deck", 'deck',
"discover", 'discover',
"docs", 'docs',
"fonts", 'fonts',
"home", 'home',
"img", 'img',
"js", 'js',
"login", 'login',
"logout", 'logout',
"media", 'media',
"p", 'p',
"password", 'password',
"report", 'report',
"reports", 'reports',
"search", 'search',
"settings", 'settings',
"statuses", 'statuses',
"site", 'site',
"sites", 'sites',
"timeline", 'timeline',
"timelines", 'timelines',
"tour", 'tour',
"user", 'user',
"users", 'users',
"vendor", 'vendor',
"400", '400',
"401", '401',
"403", '403',
"404", '404',
"500", '500',
"503", '503',
"504", '504',
]; ];
public static function get() public static function get()
{ {
$reserved = $blacklist = []; $reserved = $blacklist = [];
if (true == config('pixelfed.restricted_names.use_blacklist')) { if (true == config('pixelfed.restricted_names.use_blacklist')) {
@ -175,7 +174,7 @@ class RestrictedNames {
if (true == config('pixelfed.restricted_names.reserved_routes')) { if (true == config('pixelfed.restricted_names.reserved_routes')) {
$reserved = self::$reserved; $reserved = self::$reserved;
} }
return array_merge($blacklist, $reserved); return array_merge($blacklist, $reserved);
} }
} }

View file

@ -4,29 +4,27 @@
* @author Takashi Nojima * @author Takashi Nojima
* @copyright Copyright 2014, Takashi Nojima * @copyright Copyright 2014, Takashi Nojima
* @license http://www.apache.org/licenses/LICENSE-2.0 Apache License v2.0 * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License v2.0
* @package Twitter.Text
*/ */
namespace App\Util\Lexer; namespace App\Util\Lexer;
/** /**
* String utility * String utility.
* *
* @author Takashi Nojima * @author Takashi Nojima
* @copyright Copyright 2014, Takashi Nojima * @copyright Copyright 2014, Takashi Nojima
* @license http://www.apache.org/licenses/LICENSE-2.0 Apache License v2.0 * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License v2.0
* @package Twitter
*/ */
class StringUtils class StringUtils
{ {
/** /**
* alias of mb_substr * alias of mb_substr.
* *
* @param string $str * @param string $str
* @param integer $start * @param int $start
* @param integer $length * @param int $length
* @param string $encoding * @param string $encoding
*
* @return string * @return string
*/ */
public static function substr($str, $start, $length = null, $encoding = 'UTF-8') public static function substr($str, $start, $length = null, $encoding = 'UTF-8')
@ -35,15 +33,17 @@ class StringUtils
// for PHP <= 5.4.7 // for PHP <= 5.4.7
$length = mb_strlen($str, $encoding); $length = mb_strlen($str, $encoding);
} }
return mb_substr($str, $start, $length, $encoding); return mb_substr($str, $start, $length, $encoding);
} }
/** /**
* alias of mb_strlen * alias of mb_strlen.
* *
* @param string $str * @param string $str
* @param string $encoding * @param string $encoding
* @return integer *
* @return int
*/ */
public static function strlen($str, $encoding = 'UTF-8') public static function strlen($str, $encoding = 'UTF-8')
{ {
@ -51,13 +51,14 @@ class StringUtils
} }
/** /**
* alias of mb_strpos * alias of mb_strpos.
* *
* @param string $haystack * @param string $haystack
* @param string $needle * @param string $needle
* @param integer $offset * @param int $offset
* @param string $encoding * @param string $encoding
* @return integer *
* @return int
*/ */
public static function strpos($haystack, $needle, $offset = 0, $encoding = 'UTF-8') public static function strpos($haystack, $needle, $offset = 0, $encoding = 'UTF-8')
{ {
@ -97,8 +98,10 @@ class StringUtils
$suffixOffset = $start + $length; $suffixOffset = $start + $length;
$suffixLength = $string_length - $start - $length; $suffixLength = $string_length - $start - $length;
return static::substr($string, 0, $start, $encoding).$replacement.static::substr($string, $suffixOffset, $suffixLength, $encoding); return static::substr($string, 0, $start, $encoding).$replacement.static::substr($string, $suffixOffset, $suffixLength, $encoding);
} }
return (is_null($length) === true) ? substr_replace($string, $replacement, $start) : substr_replace($string, $replacement, $start, $length); return (is_null($length) === true) ? substr_replace($string, $replacement, $start) : substr_replace($string, $replacement, $start, $length);
} }
} }

View file

@ -4,17 +4,12 @@
* @author Nick Pope <nick@nickpope.me.uk> * @author Nick Pope <nick@nickpope.me.uk>
* @copyright Copyright © 2010, Nick Pope * @copyright Copyright © 2010, Nick Pope
* @license http://www.apache.org/licenses/LICENSE-2.0 Apache License v2.0 * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License v2.0
* @package Twitter.Text
*/ */
namespace App\Util\Lexer; namespace App\Util\Lexer;
use App\Util\Lexer\Regex;
use App\Util\Lexer\Extractor;
use App\Util\Lexer\StringUtils;
/** /**
* Twitter Validator Class * Twitter Validator Class.
* *
* Performs "validation" on tweets. * Performs "validation" on tweets.
* *
@ -25,11 +20,9 @@ use App\Util\Lexer\StringUtils;
* @author Nick Pope <nick@nickpope.me.uk> * @author Nick Pope <nick@nickpope.me.uk>
* @copyright Copyright © 2010, Nick Pope * @copyright Copyright © 2010, Nick Pope
* @license http://www.apache.org/licenses/LICENSE-2.0 Apache License v2.0 * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License v2.0
* @package Twitter.Text
*/ */
class Validator extends Regex class Validator extends Regex
{ {
/** /**
* The maximum length of a tweet. * The maximum length of a tweet.
* *
@ -38,21 +31,20 @@ class Validator extends Regex
const MAX_LENGTH = 140; const MAX_LENGTH = 140;
/** /**
* The length of a short URL beginning with http: * The length of a short URL beginning with http:.
* *
* @var int * @var int
*/ */
protected $short_url_length = 23; protected $short_url_length = 23;
/** /**
* The length of a short URL beginning with http: * The length of a short URL beginning with http:.
* *
* @var int * @var int
*/ */
protected $short_url_length_https = 23; protected $short_url_length_https = 23;
/** /**
*
* @var Extractor * @var Extractor
*/ */
protected $extractor = null; protected $extractor = null;
@ -87,10 +79,12 @@ class Validator extends Regex
} }
/** /**
* Setup short URL length from Twitter API /help/configuration response * Setup short URL length from Twitter API /help/configuration response.
* *
* @param mixed $config * @param mixed $config
*
* @return Validator * @return Validator
*
* @link https://dev.twitter.com/docs/api/1/get/help/configuration * @link https://dev.twitter.com/docs/api/1/get/help/configuration
*/ */
public function setConfiguration($config) public function setConfiguration($config)
@ -117,19 +111,21 @@ class Validator extends Regex
} }
/** /**
* Set the length of a short URL beginning with http: * Set the length of a short URL beginning with http:.
* *
* @param mixed $length * @param mixed $length
*
* @return Validator * @return Validator
*/ */
public function setShortUrlLength($length) public function setShortUrlLength($length)
{ {
$this->short_url_length = intval($length); $this->short_url_length = intval($length);
return $this; return $this;
} }
/** /**
* Get the length of a short URL beginning with http: * Get the length of a short URL beginning with http:.
* *
* @return int * @return int
*/ */
@ -139,19 +135,21 @@ class Validator extends Regex
} }
/** /**
* Set the length of a short URL beginning with https: * Set the length of a short URL beginning with https:.
* *
* @param mixed $length * @param mixed $length
*
* @return Validator * @return Validator
*/ */
public function setShortUrlLengthHttps($length) public function setShortUrlLengthHttps($length)
{ {
$this->short_url_length_https = intval($length); $this->short_url_length_https = intval($length);
return $this; return $this;
} }
/** /**
* Get the length of a short URL beginning with https: * Get the length of a short URL beginning with https:.
* *
* @return int * @return int
*/ */
@ -164,7 +162,8 @@ class Validator extends Regex
* Check whether a tweet is valid. * Check whether a tweet is valid.
* *
* @param string $tweet The tweet to validate. * @param string $tweet The tweet to validate.
* @return boolean Whether the tweet is valid. *
* @return bool Whether the tweet is valid.
*/ */
public function isValidTweetText($tweet = null) public function isValidTweetText($tweet = null)
{ {
@ -181,13 +180,15 @@ class Validator extends Regex
if (preg_match(self::$patterns['invalid_characters'], $tweet)) { if (preg_match(self::$patterns['invalid_characters'], $tweet)) {
return false; return false;
} }
return true; return true;
} }
/** /**
* Check whether a tweet is valid. * Check whether a tweet is valid.
* *
* @return boolean Whether the tweet is valid. * @return bool Whether the tweet is valid.
*
* @deprecated since version 1.1.0 * @deprecated since version 1.1.0
*/ */
public function validateTweet() public function validateTweet()
@ -199,7 +200,8 @@ class Validator extends Regex
* Check whether a username is valid. * Check whether a username is valid.
* *
* @param string $username The username to validate. * @param string $username The username to validate.
* @return boolean Whether the username is valid. *
* @return bool Whether the username is valid.
*/ */
public function isValidUsername($username = null) public function isValidUsername($username = null)
{ {
@ -211,13 +213,15 @@ class Validator extends Regex
return false; return false;
} }
$extracted = $this->extractor->extractMentionedScreennames($username); $extracted = $this->extractor->extractMentionedScreennames($username);
return count($extracted) === 1 && $extracted[0] === substr($username, 1); return count($extracted) === 1 && $extracted[0] === substr($username, 1);
} }
/** /**
* Check whether a username is valid. * Check whether a username is valid.
* *
* @return boolean Whether the username is valid. * @return bool Whether the username is valid.
*
* @deprecated since version 1.1.0 * @deprecated since version 1.1.0
*/ */
public function validateUsername() public function validateUsername()
@ -229,7 +233,8 @@ class Validator extends Regex
* Check whether a list is valid. * Check whether a list is valid.
* *
* @param string $list The list name to validate. * @param string $list The list name to validate.
* @return boolean Whether the list is valid. *
* @return bool Whether the list is valid.
*/ */
public function isValidList($list = null) public function isValidList($list = null)
{ {
@ -242,13 +247,15 @@ class Validator extends Regex
} }
preg_match(self::$patterns['valid_mentions_or_lists'], $list, $matches); preg_match(self::$patterns['valid_mentions_or_lists'], $list, $matches);
$matches = array_pad($matches, 5, ''); $matches = array_pad($matches, 5, '');
return isset($matches) && $matches[1] === '' && $matches[4] && !empty($matches[4]) && $matches[5] === ''; return isset($matches) && $matches[1] === '' && $matches[4] && !empty($matches[4]) && $matches[5] === '';
} }
/** /**
* Check whether a list is valid. * Check whether a list is valid.
* *
* @return boolean Whether the list is valid. * @return bool Whether the list is valid.
*
* @deprecated since version 1.1.0 * @deprecated since version 1.1.0
*/ */
public function validateList() public function validateList()
@ -260,7 +267,8 @@ class Validator extends Regex
* Check whether a hashtag is valid. * Check whether a hashtag is valid.
* *
* @param string $hashtag The hashtag to validate. * @param string $hashtag The hashtag to validate.
* @return boolean Whether the hashtag is valid. *
* @return bool Whether the hashtag is valid.
*/ */
public function isValidHashtag($hashtag = null) public function isValidHashtag($hashtag = null)
{ {
@ -272,13 +280,15 @@ class Validator extends Regex
return false; return false;
} }
$extracted = $this->extractor->extractHashtags($hashtag); $extracted = $this->extractor->extractHashtags($hashtag);
return count($extracted) === 1 && $extracted[0] === substr($hashtag, 1); return count($extracted) === 1 && $extracted[0] === substr($hashtag, 1);
} }
/** /**
* Check whether a hashtag is valid. * Check whether a hashtag is valid.
* *
* @return boolean Whether the hashtag is valid. * @return bool Whether the hashtag is valid.
*
* @deprecated since version 1.1.0 * @deprecated since version 1.1.0
*/ */
public function validateHashtag() public function validateHashtag()
@ -290,10 +300,10 @@ class Validator extends Regex
* Check whether a URL is valid. * Check whether a URL is valid.
* *
* @param string $url The url to validate. * @param string $url The url to validate.
* @param boolean $unicode_domains Consider the domain to be unicode. * @param bool $unicode_domains Consider the domain to be unicode.
* @param boolean $require_protocol Require a protocol for valid domain? * @param bool $require_protocol Require a protocol for valid domain?
* *
* @return boolean Whether the URL is valid. * @return bool Whether the URL is valid.
*/ */
public function isValidURL($url = null, $unicode_domains = true, $require_protocol = true) public function isValidURL($url = null, $unicode_domains = true, $require_protocol = true)
{ {
@ -310,25 +320,27 @@ class Validator extends Regex
return false; return false;
} }
list($scheme, $authority, $path, $query, $fragment) = array_pad($matches, 5, ''); list($scheme, $authority, $path, $query, $fragment) = array_pad($matches, 5, '');
# Check scheme, path, query, fragment: // Check scheme, path, query, fragment:
if (($require_protocol && !( if (($require_protocol && !(
self::isValidMatch($scheme, self::$patterns['validate_url_scheme']) && preg_match('/^https?$/i', $scheme)) self::isValidMatch($scheme, self::$patterns['validate_url_scheme']) && preg_match('/^https?$/i', $scheme))
) || !self::isValidMatch($path, self::$patterns['validate_url_path']) || !self::isValidMatch($query, self::$patterns['validate_url_query'], true) ) || !self::isValidMatch($path, self::$patterns['validate_url_path']) || !self::isValidMatch($query, self::$patterns['validate_url_query'], true)
|| !self::isValidMatch($fragment, self::$patterns['validate_url_fragment'], true)) { || !self::isValidMatch($fragment, self::$patterns['validate_url_fragment'], true)) {
return false; return false;
} }
# Check authority: // Check authority:
$authority_pattern = $unicode_domains ? 'validate_url_unicode_authority' : 'validate_url_authority'; $authority_pattern = $unicode_domains ? 'validate_url_unicode_authority' : 'validate_url_authority';
return self::isValidMatch($authority, self::$patterns[$authority_pattern]); return self::isValidMatch($authority, self::$patterns[$authority_pattern]);
} }
/** /**
* Check whether a URL is valid. * Check whether a URL is valid.
* *
* @param boolean $unicode_domains Consider the domain to be unicode. * @param bool $unicode_domains Consider the domain to be unicode.
* @param boolean $require_protocol Require a protocol for valid domain? * @param bool $require_protocol Require a protocol for valid domain?
*
* @return bool Whether the URL is valid.
* *
* @return boolean Whether the URL is valid.
* @deprecated since version 1.1.0 * @deprecated since version 1.1.0
*/ */
public function validateURL($unicode_domains = true, $require_protocol = true) public function validateURL($unicode_domains = true, $require_protocol = true)
@ -340,6 +352,7 @@ class Validator extends Regex
* Determines the length of a tweet. Takes shortening of URLs into account. * Determines the length of a tweet. Takes shortening of URLs into account.
* *
* @param string $tweet The tweet to validate. * @param string $tweet The tweet to validate.
*
* @return int the length of a tweet. * @return int the length of a tweet.
*/ */
public function getTweetLength($tweet = null) public function getTweetLength($tweet = null)
@ -353,6 +366,7 @@ class Validator extends Regex
$length += $x['indices'][0] - $x['indices'][1]; $length += $x['indices'][0] - $x['indices'][1];
$length += stripos($x['url'], 'https://') === 0 ? $this->short_url_length_https : $this->short_url_length; $length += stripos($x['url'], 'https://') === 0 ? $this->short_url_length_https : $this->short_url_length;
} }
return $length; return $length;
} }
@ -360,6 +374,7 @@ class Validator extends Regex
* Determines the length of a tweet. Takes shortening of URLs into account. * Determines the length of a tweet. Takes shortening of URLs into account.
* *
* @return int the length of a tweet. * @return int the length of a tweet.
*
* @deprecated since version 1.1.0 * @deprecated since version 1.1.0
*/ */
public function getLength() public function getLength()
@ -372,15 +387,15 @@ class Validator extends Regex
* *
* @param string $string The subject string to test. * @param string $string The subject string to test.
* @param string $pattern The pattern to match against. * @param string $pattern The pattern to match against.
* @param boolean $optional Whether a match is compulsory or not. * @param bool $optional Whether a match is compulsory or not.
* *
* @return boolean Whether an exact match was found. * @return bool Whether an exact match was found.
*/ */
protected static function isValidMatch($string, $pattern, $optional = false) protected static function isValidMatch($string, $pattern, $optional = false)
{ {
$found = preg_match($pattern, $string, $matches); $found = preg_match($pattern, $string, $matches);
if (!$optional) { if (!$optional) {
return (($string || $string === '') && $found && $matches[0] === $string); return ($string || $string === '') && $found && $matches[0] === $string;
} else { } else {
return !(($string || $string === '') && (!$found || $matches[0] !== $string)); return !(($string || $string === '') && (!$found || $matches[0] !== $string));
} }

View file

@ -2,19 +2,18 @@
namespace App\Util\Media; namespace App\Util\Media;
use Storage;
use App\Media; use App\Media;
use Image as Intervention; use Image as Intervention;
use Storage;
class Image { class Image
{
public $square; public $square;
public $landscape; public $landscape;
public $portrait; public $portrait;
public $thumbnail; public $thumbnail;
public $orientation; public $orientation;
public function __construct() public function __construct()
{ {
ini_set('memory_limit', config('pixelfed.memory_limit', '1024M')); ini_set('memory_limit', config('pixelfed.memory_limit', '1024M'));
@ -24,7 +23,7 @@ class Image {
$this->portrait = $this->orientations()['portrait']; $this->portrait = $this->orientations()['portrait'];
$this->thumbnail = [ $this->thumbnail = [
'width' => 293, 'width' => 293,
'height' => 293 'height' => 293,
]; ];
$this->orientation = null; $this->orientation = null;
} }
@ -34,16 +33,16 @@ class Image {
return [ return [
'square' => [ 'square' => [
'width' => 1080, 'width' => 1080,
'height' => 1080 'height' => 1080,
], ],
'landscape' => [ 'landscape' => [
'width' => 1920, 'width' => 1920,
'height' => 1080 'height' => 1080,
], ],
'portrait' => [ 'portrait' => [
'width' => 1080, 'width' => 1080,
'height' => 1350 'height' => 1350,
] ],
]; ];
} }
@ -55,7 +54,7 @@ class Image {
if ($thumbnail) { if ($thumbnail) {
return [ return [
'dimensions' => $this->thumbnail, 'dimensions' => $this->thumbnail,
'orientation' => 'thumbnail' 'orientation' => 'thumbnail',
]; ];
} }
@ -64,9 +63,10 @@ class Image {
$orientation = $aspect === 1 ? 'square' : $orientation = $aspect === 1 ? 'square' :
($aspect > 1 ? 'landscape' : 'portrait'); ($aspect > 1 ? 'landscape' : 'portrait');
$this->orientation = $orientation; $this->orientation = $orientation;
return [ return [
'dimensions' => $this->orientations()[$orientation], 'dimensions' => $this->orientations()[$orientation],
'orientation' => $orientation 'orientation' => $orientation,
]; ];
} }
@ -75,7 +75,6 @@ class Image {
$basePath = storage_path('app/'.$media->media_path); $basePath = storage_path('app/'.$media->media_path);
$this->handleResizeImage($media); $this->handleResizeImage($media);
return;
} }
public function resizeThumbnail(Media $media) public function resizeThumbnail(Media $media)
@ -83,7 +82,6 @@ class Image {
$basePath = storage_path('app/'.$media->media_path); $basePath = storage_path('app/'.$media->media_path);
$this->handleThumbnailImage($media); $this->handleThumbnailImage($media);
return;
} }
public function handleResizeImage(Media $media) public function handleResizeImage(Media $media)
@ -103,8 +101,7 @@ class Image {
$ratio = $this->getAspectRatio($file, $thumbnail); $ratio = $this->getAspectRatio($file, $thumbnail);
$aspect = $ratio['dimensions']; $aspect = $ratio['dimensions'];
$orientation = $ratio['orientation']; $orientation = $ratio['orientation'];
if($media->mime === 'image/gif' && !$thumbnail) if ($media->mime === 'image/gif' && !$thumbnail) {
{
return; return;
} }
@ -132,13 +129,11 @@ class Image {
} }
$media->save(); $media->save();
} catch (Exception $e) { } catch (Exception $e) {
} }
} }
public function setBaseName($basePath, $thumbnail = false, $extension) public function setBaseName($basePath, $thumbnail, $extension)
{ {
$png = false; $png = false;
$path = explode('.', $basePath); $path = explode('.', $basePath);
@ -148,5 +143,4 @@ class Image {
return ['path' => $basePath, 'png' => $png]; return ['path' => $basePath, 'png' => $png];
} }
} }

View file

@ -2,11 +2,8 @@
namespace App\Util\Webfinger; namespace App\Util\Webfinger;
use App\User; class Webfinger
use App\Util\Lexer\Nickname; {
class Webfinger {
public $user; public $user;
public $subject; public $subject;
public $aliases; public $aliases;
@ -16,8 +13,8 @@ class Webfinger {
{ {
$this->user = $user; $this->user = $user;
$this->subject = ''; $this->subject = '';
$this->aliases = array(); $this->aliases = [];
$this->links = array(); $this->links = [];
} }
public function setSubject() public function setSubject()
@ -26,6 +23,7 @@ class Webfinger {
$username = $this->user->username; $username = $this->user->username;
$this->subject = 'acct:'.$username.'@'.$host; $this->subject = 'acct:'.$username.'@'.$host;
return $this; return $this;
} }
@ -33,8 +31,9 @@ class Webfinger {
{ {
$this->aliases = [ $this->aliases = [
$this->user->url(), $this->user->url(),
$this->user->permalink() $this->user->permalink(),
]; ];
return $this; return $this;
} }
@ -46,19 +45,20 @@ class Webfinger {
[ [
'rel' => 'http://webfinger.net/rel/profile-page', 'rel' => 'http://webfinger.net/rel/profile-page',
'type' => 'text/html', 'type' => 'text/html',
'href' => $user->url() 'href' => $user->url(),
], ],
[ [
'rel' => 'http://schemas.google.com/g/2010#updates-from', 'rel' => 'http://schemas.google.com/g/2010#updates-from',
'type' => 'application/atom+xml', 'type' => 'application/atom+xml',
'href' => $user->permalink('.atom') 'href' => $user->permalink('.atom'),
], ],
[ [
'rel' => 'self', 'rel' => 'self',
'type' => 'application/activity+json', 'type' => 'application/activity+json',
'href' => $user->permalink() 'href' => $user->permalink(),
] ],
]; ];
return $this; return $this;
} }
@ -71,10 +71,7 @@ class Webfinger {
return [ return [
'subject' => $this->subject, 'subject' => $this->subject,
'aliases' => $this->aliases, 'aliases' => $this->aliases,
'links' => $this->links 'links' => $this->links,
]; ];
} }
} }

View file

@ -2,18 +2,17 @@
namespace App\Util\Webfinger; namespace App\Util\Webfinger;
use App\User;
use App\Util\Lexer\Nickname; use App\Util\Lexer\Nickname;
class WebfingerUrl { class WebfingerUrl
{
public static function generateWebfingerUrl($url) public static function generateWebfingerUrl($url)
{ {
$url = Nickname::normalizeProfileUrl($url); $url = Nickname::normalizeProfileUrl($url);
$domain = $url['domain']; $domain = $url['domain'];
$username = $url['username']; $username = $url['username'];
$path = "https://{$domain}/.well-known/webfinger?resource={$username}@{$domain}"; $path = "https://{$domain}/.well-known/webfinger?resource={$username}@{$domain}";
return $path; return $path;
} }
} }

View file

@ -36,7 +36,7 @@ return [
'driver' => 'file', // redis, file, pdo, custom 'driver' => 'file', // redis, file, pdo, custom
'path' => storage_path('debugbar'), // For file driver 'path' => storage_path('debugbar'), // For file driver
'connection' => null, // Leave null for default connection (Redis/PDO) 'connection' => null, // Leave null for default connection (Redis/PDO)
'provider' => '' // Instance of StorageInterface for custom driver 'provider' => '', // Instance of StorageInterface for custom driver
], ],
/* /*
@ -148,19 +148,19 @@ return [
'hints' => true, // Show hints for common mistakes 'hints' => true, // Show hints for common mistakes
], ],
'mail' => [ 'mail' => [
'full_log' => false 'full_log' => false,
], ],
'views' => [ 'views' => [
'data' => false, //Note: Can slow down the application, because the data can be quite large.. 'data' => false, //Note: Can slow down the application, because the data can be quite large..
], ],
'route' => [ 'route' => [
'label' => true // show complete route on bar 'label' => true, // show complete route on bar
], ],
'logs' => [ 'logs' => [
'file' => null 'file' => null,
], ],
'cache' => [ 'cache' => [
'values' => true // collect cache values 'values' => true, // collect cache values
], ],
], ],

Some files were not shown because too many files have changed in this diff Show more