forked from projects/thebadspace
Cleaned up location controller, responsive fix
The Location Controller was getting too heavy so an Update and Maintenance service class was created to offload most of it's functionality. Location upating was moved to LocationRepository There was also a small issue with responsive list links not adapting properly in Safari that was fixed
This commit is contained in:
parent
03fbd00db1
commit
573054e7d8
6 changed files with 302 additions and 249 deletions
|
@ -2,262 +2,27 @@
|
|||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use Illuminate\Http\Request;
|
||||
use App\Models\Location;
|
||||
use Ramsey\Uuid\Uuid;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use App\Models\Source;
|
||||
use App\Services\UpdateService;
|
||||
|
||||
class LocationController extends Controller
|
||||
{
|
||||
public function addLocation(Request $request)
|
||||
{
|
||||
$fields = $request->validate([
|
||||
'name' => ['required'],
|
||||
'url' => ['required'],
|
||||
'description' => ['required'],
|
||||
'tags' => ['required'],
|
||||
]);
|
||||
protected $update;
|
||||
|
||||
if ($fields) {
|
||||
$examples = [];
|
||||
$files = $request->files->get("loc_examples");
|
||||
if ($request->hasfile('loc_examples')) {
|
||||
foreach ($request->file('loc_examples') as $file) {
|
||||
$path = $file->store('reference');
|
||||
array_push($examples, ["path" => $path]);
|
||||
}
|
||||
}
|
||||
$request->merge(['active' => true]);
|
||||
$request->merge(['uuid' => Uuid::uuid4()]);
|
||||
$request->merge(['images' => json_encode($examples)]);
|
||||
$request->merge(['added_by' => Auth::user()->id]);
|
||||
//NOTE: Laravel gets funky if sequencing isn't explicitly set
|
||||
$new = Location::create($request->all());
|
||||
if ($new) {
|
||||
return back()->with('message', 'New Location Added. Take a break!');
|
||||
} else {
|
||||
return back()->withErrors([
|
||||
'error' => 'Uh oh. There was an inssue',
|
||||
]);
|
||||
}
|
||||
} else {
|
||||
return back()->withErrors([
|
||||
'error' => 'All fields are required',
|
||||
]);
|
||||
}
|
||||
public function __construct(UpdateService $updateService)
|
||||
{
|
||||
$this->update = $updateService;
|
||||
}
|
||||
|
||||
public function updateLocations()
|
||||
{
|
||||
$duplicates = 0;
|
||||
$fresh = 0;
|
||||
$missing = [];
|
||||
$result = $this->update->locations();
|
||||
|
||||
$unified = [];
|
||||
$cleanSources = [];
|
||||
$sources = Source::where("active", true)->get();
|
||||
|
||||
//checks source url to make sure they valid
|
||||
foreach ($sources as $source) {
|
||||
if ($source->type == 'mastodon') {
|
||||
$url = 'https://' . $source->url;
|
||||
} else {
|
||||
$url = $source->url;
|
||||
}
|
||||
|
||||
if ($this->urlExists($url)) {
|
||||
array_push($cleanSources, [
|
||||
'url' => $source->url,
|
||||
'token' => $source->token,
|
||||
'type' => $source->type,
|
||||
'format' => $source->format]);
|
||||
} else {
|
||||
var_dump($url);
|
||||
array_push($missing, ['source' => $url]);
|
||||
}
|
||||
}
|
||||
|
||||
//valid source url get compiled for unified
|
||||
foreach ($cleanSources as $source) {
|
||||
//check url to make sure it's cool
|
||||
|
||||
//parsing for mastodon
|
||||
if ($source['type'] == 'mastodon') {
|
||||
$result = [];
|
||||
if ($source['token'] == null) {
|
||||
$result = \Mastodon::domain('https://' . $source['url'])
|
||||
->get('/instance/domain_blocks');
|
||||
} else {
|
||||
$result = \Mastodon::domain('https://' . $source['url'])
|
||||
->token($source['token'])
|
||||
->get('/instance/domain_blocks');
|
||||
}
|
||||
|
||||
foreach ($result as $item) {
|
||||
$index = array_search($item['domain'], array_column($unified, 'url'));
|
||||
if ($index) {
|
||||
//if there is a match, update the count
|
||||
if ($item['severity'] == "suspend" || $item['severity'] == "defederate") {
|
||||
++$unified[$index]['block_count'];
|
||||
} else {
|
||||
++$unified[$index]['silence_count'];
|
||||
}
|
||||
} else {
|
||||
$silence = 0;
|
||||
$suspend = 0;
|
||||
if ($item['severity'] == "suspend" || $item['severity'] == "defederate") {
|
||||
++$suspend;
|
||||
} else {
|
||||
++$silence;
|
||||
}
|
||||
array_push($unified, [
|
||||
'name' => $item['domain'],
|
||||
'url' => $item['domain'],
|
||||
'rating' => $item['severity'],
|
||||
'comment' => $item['comment'],
|
||||
'block_count' => $suspend,
|
||||
'silence_count' => $silence,
|
||||
]);
|
||||
}
|
||||
}
|
||||
}
|
||||
//parsing for custom csv
|
||||
if ($source['type'] == 'custom' && $source['format'] == 'csv') {
|
||||
$denylist = array_map('str_getcsv', file($source['url']));
|
||||
foreach ($denylist as $item) {
|
||||
$index = array_search($item[0], array_column($unified, 'url'));
|
||||
if ($index) {
|
||||
//if there is a match, update the count
|
||||
if ($item[1] == "suspend" || $item['severity'] == "defederate") {
|
||||
++$unified[$index]['block_count'];
|
||||
} else {
|
||||
++$unified[$index]['silence_count'];
|
||||
}
|
||||
} else {
|
||||
$silence = 0;
|
||||
$suspend = 0;
|
||||
if ($item[1] == "suspend" || $item[1] == "defederate") {
|
||||
++$suspend;
|
||||
} else {
|
||||
++$silence;
|
||||
}
|
||||
array_push($unified, [
|
||||
'name' => $item[0],
|
||||
'url' => $item[0],
|
||||
'rating' => $item[1],
|
||||
'comment' => $item[2],
|
||||
'block_count' => $suspend,
|
||||
'silence_count' => $silence,
|
||||
]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//TODO: maintenance script to set locations to inactive if they haven't been updated
|
||||
// over 90 days
|
||||
|
||||
//$diff=date_diff($location->updated_at, new DateTime());
|
||||
//$days = $diff->format("%R%a days")
|
||||
|
||||
//$interval = $location->updated_at->diff(new DateTime());
|
||||
//$days = $interval->format("%a");
|
||||
|
||||
//get all locations and sort which are present in unified or not
|
||||
/*
|
||||
$sorted = [];
|
||||
$listed = 0;
|
||||
$notlisted = 0;
|
||||
foreach (Location::all() as $location) {
|
||||
if (array_search($location->url, array_column($unified, 'url'))) {
|
||||
++$listed;
|
||||
// locations present in unfied, so updated
|
||||
array_push($sorted, [
|
||||
'location' => $location,
|
||||
'listed' => true
|
||||
]);
|
||||
} else {
|
||||
++$notlisted;
|
||||
//locations not present
|
||||
array_push($sorted, [
|
||||
'location' => $location,
|
||||
'listed' => false
|
||||
]);
|
||||
}
|
||||
};
|
||||
*/
|
||||
|
||||
//once the unified list is created, update current entries or create fresh ones
|
||||
|
||||
foreach ($unified as $item) {
|
||||
$location = Location::where("url", $item['url'])->first();
|
||||
if ($location) {
|
||||
++$duplicates;
|
||||
//update block count for existing item
|
||||
|
||||
$location->block_count = $item['block_count'];
|
||||
$location->silence_count = $item['silence_count'];
|
||||
|
||||
$location->actions_count = $item['block_count'] + $item['silence_count'];
|
||||
|
||||
if (($item['block_count'] + $item['silence_count']) < 2) {
|
||||
$location->active = false;
|
||||
}
|
||||
|
||||
//replace null with empty array
|
||||
if ($location->images == null) {
|
||||
$location->images = [];
|
||||
};
|
||||
$location->save();
|
||||
} else {
|
||||
// make new entries for instances not present
|
||||
++$fresh;
|
||||
$images = [];
|
||||
$rating = ($item['rating'] == 'defederate') ? 'suspend' : $item['rating'];
|
||||
|
||||
$status = true;
|
||||
if (($item['block_count'] + $item['silence_count']) < 2) {
|
||||
$status = false;
|
||||
}
|
||||
|
||||
$new = Location::create([
|
||||
'uuid' => Uuid::uuid4(),
|
||||
'name' => $item['url'],
|
||||
'url' => $item['url'],
|
||||
'description' => ($item['comment'] != null) ? $item['comment'] : "no description",
|
||||
'active' => $status,
|
||||
'rating' => $rating,
|
||||
'added_by' => 1,
|
||||
'tags' => 'poor moderation, hate speech',
|
||||
'images' => json_encode($images),
|
||||
'block_count' => $item['block_count'],
|
||||
'silence_count' => $item['silence_count'],
|
||||
'actions_cont' => $item['block_count'] + $item['silence_count']
|
||||
]);
|
||||
}
|
||||
}
|
||||
//TODO: Send update post to TBS social account
|
||||
|
||||
return back()->with('message', $duplicates . ' UPDATED - ' . $fresh . ' CREATED - ' . count($missing) . ' SOURCE(S) NOT CHECKED');
|
||||
}
|
||||
|
||||
public function urlExists($url)
|
||||
{
|
||||
// Remove all illegal characters from a url
|
||||
$url = filter_var($url, FILTER_SANITIZE_URL);
|
||||
// Validate URI
|
||||
if (
|
||||
filter_var($url, FILTER_VALIDATE_URL) === false || // check only for http/https schemes.
|
||||
!in_array(
|
||||
strtolower(parse_url($url, PHP_URL_SCHEME)),
|
||||
["http", "https"],
|
||||
true
|
||||
)
|
||||
) {
|
||||
return false;
|
||||
} // Check that URL exists
|
||||
$file_headers = @get_headers($url);
|
||||
return !(!$file_headers || $file_headers[0] === "HTTP/1.1 404 Not Found");
|
||||
return back()->with(
|
||||
'message',
|
||||
$result['duplicates'] .
|
||||
' UPDATED - ' . $result['fresh'] .
|
||||
' CREATED - ' . count($result['missing']) .
|
||||
' SOURCE(S) NOT CHECKED'
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,6 +4,8 @@ namespace App\Providers;
|
|||
|
||||
use Illuminate\Support\ServiceProvider;
|
||||
use App\Repositories\LocationRepository;
|
||||
use App\Services\UpdateService;
|
||||
use App\Services\MaintenanceService;
|
||||
use App\Models\Location;
|
||||
|
||||
class AppServiceProvider extends ServiceProvider
|
||||
|
@ -16,6 +18,14 @@ class AppServiceProvider extends ServiceProvider
|
|||
$this->app->bind(LocationRepository::class, function ($app) {
|
||||
return new LocationRepository(new Location());
|
||||
});
|
||||
|
||||
$this->app->bind(UpdateService::class, function ($app) {
|
||||
return new UpdateService(new Location());
|
||||
});
|
||||
|
||||
$this->app->bind(MaintenanceService::class, function ($app) {
|
||||
return new MaintenanceService(new Location());
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -4,6 +4,7 @@ namespace App\Repositories;
|
|||
|
||||
use App\Models\Location;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
|
||||
class LocationRepository
|
||||
{
|
||||
|
@ -70,4 +71,42 @@ class LocationRepository
|
|||
|
||||
return $result = [$locations, $pageCount, $prev, $next];
|
||||
}
|
||||
|
||||
public function addLocation(Request $request)
|
||||
{
|
||||
$fields = $request->validate([
|
||||
'name' => ['required'],
|
||||
'url' => ['required'],
|
||||
'description' => ['required'],
|
||||
'tags' => ['required'],
|
||||
]);
|
||||
|
||||
if ($fields) {
|
||||
$examples = [];
|
||||
$files = $request->files->get("loc_examples");
|
||||
if ($request->hasfile('loc_examples')) {
|
||||
foreach ($request->file('loc_examples') as $file) {
|
||||
$path = $file->store('reference');
|
||||
array_push($examples, ["path" => $path]);
|
||||
}
|
||||
}
|
||||
$request->merge(['active' => true]);
|
||||
$request->merge(['uuid' => Uuid::uuid4()]);
|
||||
$request->merge(['images' => json_encode($examples)]);
|
||||
$request->merge(['added_by' => Auth::user()->id]);
|
||||
//NOTE: Laravel gets funky if sequencing isn't explicitly set
|
||||
$new = Location::create($request->all());
|
||||
if ($new) {
|
||||
return back()->with('message', 'New Location Added. Take a break!');
|
||||
} else {
|
||||
return back()->withErrors([
|
||||
'error' => 'Uh oh. There was an inssue',
|
||||
]);
|
||||
}
|
||||
} else {
|
||||
return back()->withErrors([
|
||||
'error' => 'All fields are required',
|
||||
]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
41
app/Services/MaintenanceService.php
Normal file
41
app/Services/MaintenanceService.php
Normal file
|
@ -0,0 +1,41 @@
|
|||
<?php
|
||||
|
||||
namespace App\Services;
|
||||
|
||||
use App\Models\Location;
|
||||
|
||||
class MaintenanceService
|
||||
{
|
||||
//TODO: maintenance script to set locations to inactive if they haven't been updated
|
||||
// over 90 days
|
||||
|
||||
//$diff=date_diff($location->updated_at, new DateTime());
|
||||
//$days = $diff->format("%R%a days")
|
||||
|
||||
//$interval = $location->updated_at->diff(new DateTime());
|
||||
//$days = $interval->format("%a");
|
||||
|
||||
//get all locations and sort which are present in unified or not
|
||||
/*
|
||||
$sorted = [];
|
||||
$listed = 0;
|
||||
$notlisted = 0;
|
||||
foreach (Location::all() as $location) {
|
||||
if (array_search($location->url, array_column($unified, 'url'))) {
|
||||
++$listed;
|
||||
// locations present in unfied, so updated
|
||||
array_push($sorted, [
|
||||
'location' => $location,
|
||||
'listed' => true
|
||||
]);
|
||||
} else {
|
||||
++$notlisted;
|
||||
//locations not present
|
||||
array_push($sorted, [
|
||||
'location' => $location,
|
||||
'listed' => false
|
||||
]);
|
||||
}
|
||||
};
|
||||
*/
|
||||
}
|
198
app/Services/UpdateService.php
Normal file
198
app/Services/UpdateService.php
Normal file
|
@ -0,0 +1,198 @@
|
|||
<?php
|
||||
|
||||
namespace App\Services;
|
||||
|
||||
use App\Models\Location;
|
||||
use App\Models\Source;
|
||||
use Ramsey\Uuid\Uuid;
|
||||
|
||||
class UpdateService
|
||||
{
|
||||
protected $model;
|
||||
private $limit = 15;
|
||||
|
||||
public function __construct(Location $model)
|
||||
{
|
||||
$this->model = $model;
|
||||
}
|
||||
|
||||
public function locations()
|
||||
{
|
||||
$duplicates = 0;
|
||||
$fresh = 0;
|
||||
$missing = [];
|
||||
|
||||
$unified = [];
|
||||
$cleanSources = [];
|
||||
$sources = Source::where("active", true)->get();
|
||||
|
||||
//checks source url to make sure they valid
|
||||
foreach ($sources as $source) {
|
||||
if ($source->type == 'mastodon') {
|
||||
$url = 'https://' . $source->url;
|
||||
} else {
|
||||
$url = $source->url;
|
||||
}
|
||||
|
||||
if ($this->urlExists($url)) {
|
||||
array_push($cleanSources, [
|
||||
'url' => $source->url,
|
||||
'token' => $source->token,
|
||||
'type' => $source->type,
|
||||
'format' => $source->format]);
|
||||
} else {
|
||||
var_dump($url);
|
||||
array_push($missing, ['source' => $url]);
|
||||
}
|
||||
}
|
||||
|
||||
//valid source url get compiled for unified
|
||||
foreach ($cleanSources as $source) {
|
||||
//check url to make sure it's cool
|
||||
|
||||
//parsing for mastodon
|
||||
if ($source['type'] == 'mastodon') {
|
||||
$result = [];
|
||||
if ($source['token'] == null) {
|
||||
$result = \Mastodon::domain('https://' . $source['url'])
|
||||
->get('/instance/domain_blocks');
|
||||
} else {
|
||||
$result = \Mastodon::domain('https://' . $source['url'])
|
||||
->token($source['token'])
|
||||
->get('/instance/domain_blocks');
|
||||
}
|
||||
|
||||
foreach ($result as $item) {
|
||||
$index = array_search($item['domain'], array_column($unified, 'url'));
|
||||
if ($index) {
|
||||
//if there is a match, update the count
|
||||
if ($item['severity'] == "suspend" || $item['severity'] == "defederate") {
|
||||
++$unified[$index]['block_count'];
|
||||
} else {
|
||||
++$unified[$index]['silence_count'];
|
||||
}
|
||||
} else {
|
||||
$silence = 0;
|
||||
$suspend = 0;
|
||||
if ($item['severity'] == "suspend" || $item['severity'] == "defederate") {
|
||||
++$suspend;
|
||||
} else {
|
||||
++$silence;
|
||||
}
|
||||
array_push($unified, [
|
||||
'name' => $item['domain'],
|
||||
'url' => $item['domain'],
|
||||
'rating' => $item['severity'],
|
||||
'comment' => $item['comment'],
|
||||
'block_count' => $suspend,
|
||||
'silence_count' => $silence,
|
||||
]);
|
||||
}
|
||||
}
|
||||
}
|
||||
//parsing for custom csv
|
||||
if ($source['type'] == 'custom' && $source['format'] == 'csv') {
|
||||
$denylist = array_map('str_getcsv', file($source['url']));
|
||||
foreach ($denylist as $item) {
|
||||
$index = array_search($item[0], array_column($unified, 'url'));
|
||||
if ($index) {
|
||||
//if there is a match, update the count
|
||||
if ($item[1] == "suspend" || $item['severity'] == "defederate") {
|
||||
++$unified[$index]['block_count'];
|
||||
} else {
|
||||
++$unified[$index]['silence_count'];
|
||||
}
|
||||
} else {
|
||||
$silence = 0;
|
||||
$suspend = 0;
|
||||
if ($item[1] == "suspend" || $item[1] == "defederate") {
|
||||
++$suspend;
|
||||
} else {
|
||||
++$silence;
|
||||
}
|
||||
array_push($unified, [
|
||||
'name' => $item[0],
|
||||
'url' => $item[0],
|
||||
'rating' => $item[1],
|
||||
'comment' => $item[2],
|
||||
'block_count' => $suspend,
|
||||
'silence_count' => $silence,
|
||||
]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//once the unified list is created, update current entries or create fresh ones
|
||||
|
||||
foreach ($unified as $item) {
|
||||
$location = Location::where("url", $item['url'])->first();
|
||||
if ($location) {
|
||||
++$duplicates;
|
||||
//update block count for existing item
|
||||
|
||||
$location->block_count = $item['block_count'];
|
||||
$location->silence_count = $item['silence_count'];
|
||||
|
||||
$location->actions_count = $item['block_count'] + $item['silence_count'];
|
||||
|
||||
if (($item['block_count'] + $item['silence_count']) < 2) {
|
||||
$location->active = false;
|
||||
}
|
||||
|
||||
//replace null with empty array
|
||||
if ($location->images == null) {
|
||||
$location->images = [];
|
||||
};
|
||||
$location->save();
|
||||
} else {
|
||||
// make new entries for instances not present
|
||||
++$fresh;
|
||||
$images = [];
|
||||
$rating = ($item['rating'] == 'defederate') ? 'suspend' : $item['rating'];
|
||||
|
||||
$status = true;
|
||||
if (($item['block_count'] + $item['silence_count']) < 2) {
|
||||
$status = false;
|
||||
}
|
||||
|
||||
$new = Location::create([
|
||||
'uuid' => Uuid::uuid4(),
|
||||
'name' => $item['url'],
|
||||
'url' => $item['url'],
|
||||
'description' => ($item['comment'] != null) ? $item['comment'] : "no description",
|
||||
'active' => $status,
|
||||
'rating' => $rating,
|
||||
'added_by' => 1,
|
||||
'tags' => 'poor moderation, hate speech',
|
||||
'images' => json_encode($images),
|
||||
'block_count' => $item['block_count'],
|
||||
'silence_count' => $item['silence_count'],
|
||||
'actions_cont' => $item['block_count'] + $item['silence_count']
|
||||
]);
|
||||
}
|
||||
}
|
||||
//TODO: Send update post to TBS social account
|
||||
|
||||
return ['duplicates' => $duplicates, 'fresh' => $fresh, 'missing' => $missing];
|
||||
}
|
||||
|
||||
public function urlExists($url)
|
||||
{
|
||||
// Remove all illegal characters from a url
|
||||
$url = filter_var($url, FILTER_SANITIZE_URL);
|
||||
// Validate URI
|
||||
if (
|
||||
filter_var($url, FILTER_VALIDATE_URL) === false || // check only for http/https schemes.
|
||||
!in_array(
|
||||
strtolower(parse_url($url, PHP_URL_SCHEME)),
|
||||
["http", "https"],
|
||||
true
|
||||
)
|
||||
) {
|
||||
return false;
|
||||
} // Check that URL exists
|
||||
$file_headers = @get_headers($url);
|
||||
return !(!$file_headers || $file_headers[0] === "HTTP/1.1 404 Not Found");
|
||||
}
|
||||
}
|
|
@ -128,7 +128,7 @@ a.list-link > .item-block > .item-icon {
|
|||
a.list-link {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr 1fr 1fr 1fr;
|
||||
grid-template-rows: 100% auto 30px 30px;
|
||||
grid-template-rows: auto auto 30px 30px;
|
||||
gap: 5px;
|
||||
height: auto;
|
||||
padding-bottom: 20px;
|
||||
|
|
Loading…
Reference in a new issue