Fix languages and feeds
This commit is contained in:
parent
f2947b57c0
commit
1c772e63cb
12 changed files with 171 additions and 20 deletions
|
|
@ -57,9 +57,6 @@ public function store(StoreFeedRequest $request): JsonResponse
|
|||
$validated['url'] = $adapter->getHomepageUrl();
|
||||
$validated['type'] = 'website';
|
||||
|
||||
// Remove provider from validated data as it's not a database column
|
||||
unset($validated['provider']);
|
||||
|
||||
$feed = Feed::create($validated);
|
||||
|
||||
return $this->sendResponse(
|
||||
|
|
|
|||
|
|
@ -90,11 +90,17 @@ public function options(): JsonResponse
|
|||
->orderBy('name')
|
||||
->get(['id', 'platform_instance_id', 'name', 'display_name', 'description']);
|
||||
|
||||
// Get feed providers from config
|
||||
$feedProviders = collect(config('feed.providers', []))
|
||||
->filter(fn($provider) => $provider['is_active'])
|
||||
->values();
|
||||
|
||||
return $this->sendResponse([
|
||||
'languages' => $languages,
|
||||
'platform_instances' => $platformInstances,
|
||||
'feeds' => $feeds,
|
||||
'platform_channels' => $platformChannels,
|
||||
'feed_providers' => $feedProviders,
|
||||
], 'Onboarding options retrieved successfully.');
|
||||
}
|
||||
|
||||
|
|
@ -215,6 +221,7 @@ public function createFeed(Request $request): JsonResponse
|
|||
'name' => $validated['name'],
|
||||
'url' => $url,
|
||||
'type' => $type,
|
||||
'provider' => $provider,
|
||||
'language_id' => $validated['language_id'],
|
||||
'description' => $validated['description'] ?? null,
|
||||
'is_active' => true,
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@
|
|||
* @property string $name
|
||||
* @property string $url
|
||||
* @property string $type
|
||||
* @property string $provider
|
||||
* @property int $language_id
|
||||
* @property Language|null $language
|
||||
* @property string $description
|
||||
|
|
@ -38,6 +39,7 @@ class Feed extends Model
|
|||
'name',
|
||||
'url',
|
||||
'type',
|
||||
'provider',
|
||||
'language_id',
|
||||
'description',
|
||||
'settings',
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@
|
|||
namespace App\Services\Factories;
|
||||
|
||||
use App\Contracts\ArticleParserInterface;
|
||||
use App\Models\Feed;
|
||||
use App\Services\Parsers\VrtArticleParser;
|
||||
use App\Services\Parsers\BelgaArticleParser;
|
||||
use Exception;
|
||||
|
|
@ -33,6 +34,25 @@ public static function getParser(string $url): ArticleParserInterface
|
|||
throw new Exception("No parser found for URL: {$url}");
|
||||
}
|
||||
|
||||
public static function getParserForFeed(Feed $feed, string $parserType = 'article'): ?ArticleParserInterface
|
||||
{
|
||||
if (!$feed->provider) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$providerConfig = config("feed.providers.{$feed->provider}");
|
||||
if (!$providerConfig || !isset($providerConfig['parsers'][$parserType])) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$parserClass = $providerConfig['parsers'][$parserType];
|
||||
if (!class_exists($parserClass)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return new $parserClass();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<int, string>
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -36,10 +36,20 @@ public static function getParser(string $url): HomepageParserInterface
|
|||
|
||||
public static function getParserForFeed(Feed $feed): ?HomepageParserInterface
|
||||
{
|
||||
try {
|
||||
return self::getParser($feed->url);
|
||||
} catch (Exception) {
|
||||
if (!$feed->provider) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$providerConfig = config("feed.providers.{$feed->provider}");
|
||||
if (!$providerConfig || !isset($providerConfig['parsers']['homepage'])) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$parserClass = $providerConfig['parsers']['homepage'];
|
||||
if (!class_exists($parserClass)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return new $parserClass();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
56
backend/config/feed.php
Normal file
56
backend/config/feed.php
Normal file
|
|
@ -0,0 +1,56 @@
|
|||
<?php
|
||||
|
||||
return [
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Feed Providers
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| This array contains the configuration for available feed providers.
|
||||
| Each provider should have a unique code, display name, description,
|
||||
| type (website or rss), and active status.
|
||||
|
|
||||
*/
|
||||
|
||||
'providers' => [
|
||||
'vrt' => [
|
||||
'code' => 'vrt',
|
||||
'name' => 'VRT News',
|
||||
'description' => 'Belgian public broadcaster news',
|
||||
'type' => 'website',
|
||||
'is_active' => true,
|
||||
'parsers' => [
|
||||
'homepage' => \App\Services\Parsers\VrtHomepageParserAdapter::class,
|
||||
'article' => \App\Services\Parsers\VrtArticleParser::class,
|
||||
'article_page' => \App\Services\Parsers\VrtArticlePageParser::class,
|
||||
],
|
||||
],
|
||||
'belga' => [
|
||||
'code' => 'belga',
|
||||
'name' => 'Belga News Agency',
|
||||
'description' => 'Belgian national news agency',
|
||||
'type' => 'rss',
|
||||
'is_active' => true,
|
||||
'parsers' => [
|
||||
'homepage' => \App\Services\Parsers\BelgaHomepageParserAdapter::class,
|
||||
'article' => \App\Services\Parsers\BelgaArticleParser::class,
|
||||
'article_page' => \App\Services\Parsers\BelgaArticlePageParser::class,
|
||||
],
|
||||
],
|
||||
],
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Default Feed Settings
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Default configuration values for feed processing
|
||||
|
|
||||
*/
|
||||
|
||||
'defaults' => [
|
||||
'fetch_interval' => 3600, // 1 hour in seconds
|
||||
'max_articles_per_fetch' => 50,
|
||||
'article_retention_days' => 30,
|
||||
],
|
||||
];
|
||||
51
backend/config/languages.php
Normal file
51
backend/config/languages.php
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
<?php
|
||||
|
||||
return [
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Supported Languages
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| This array contains all supported languages in the application.
|
||||
| Each language has a short_code, display name, native name, and active status.
|
||||
|
|
||||
*/
|
||||
|
||||
'supported' => [
|
||||
'en' => [
|
||||
'short_code' => 'en',
|
||||
'name' => 'English',
|
||||
'native_name' => 'English',
|
||||
'is_active' => true,
|
||||
],
|
||||
'nl' => [
|
||||
'short_code' => 'nl',
|
||||
'name' => 'Dutch',
|
||||
'native_name' => 'Nederlands',
|
||||
'is_active' => true,
|
||||
],
|
||||
'fr' => [
|
||||
'short_code' => 'fr',
|
||||
'name' => 'French',
|
||||
'native_name' => 'Français',
|
||||
'is_active' => true,
|
||||
],
|
||||
'de' => [
|
||||
'short_code' => 'de',
|
||||
'name' => 'German',
|
||||
'native_name' => 'Deutsch',
|
||||
'is_active' => true,
|
||||
],
|
||||
],
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Default Language
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| The default language code when no language is specified
|
||||
|
|
||||
*/
|
||||
|
||||
'default' => 'en',
|
||||
];
|
||||
|
|
@ -19,6 +19,7 @@ public function definition(): array
|
|||
'name' => $this->faker->words(3, true),
|
||||
'url' => $this->faker->url(),
|
||||
'type' => $this->faker->randomElement(['website', 'rss']),
|
||||
'provider' => $this->faker->randomElement(['vrt', 'belga']),
|
||||
'language_id' => null,
|
||||
'description' => $this->faker->optional()->sentence(),
|
||||
'settings' => [],
|
||||
|
|
@ -61,4 +62,20 @@ public function language(Language $language): static
|
|||
'language_id' => $language->id,
|
||||
]);
|
||||
}
|
||||
|
||||
public function vrt(): static
|
||||
{
|
||||
return $this->state(fn (array $attributes) => [
|
||||
'provider' => 'vrt',
|
||||
'url' => 'https://www.vrt.be/vrtnws/en/',
|
||||
]);
|
||||
}
|
||||
|
||||
public function belga(): static
|
||||
{
|
||||
return $this->state(fn (array $attributes) => [
|
||||
'provider' => 'belga',
|
||||
'url' => 'https://www.belganewsagency.eu/',
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
|
@ -14,6 +14,7 @@ public function up(): void
|
|||
$table->string('name'); // "VRT News", "Belga News Agency"
|
||||
$table->string('url'); // "https://vrt.be" or "https://feeds.example.com/rss.xml"
|
||||
$table->enum('type', ['website', 'rss']); // Feed type
|
||||
$table->string('provider'); // Feed provider code (vrt, belga, etc.)
|
||||
$table->foreignId('language_id')->nullable()->constrained();
|
||||
$table->text('description')->nullable();
|
||||
$table->json('settings')->nullable(); // Custom settings per feed type
|
||||
|
|
|
|||
|
|
@ -10,13 +10,7 @@ public function run(): void
|
|||
{
|
||||
$this->call([
|
||||
SettingsSeeder::class,
|
||||
]);
|
||||
|
||||
// Seed languages in local/dev environment only to avoid conflicts in tests
|
||||
if (app()->environment('local')) {
|
||||
$this->call([
|
||||
LanguageSeeder::class,
|
||||
]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,12 +9,7 @@ class LanguageSeeder extends Seeder
|
|||
{
|
||||
public function run(): void
|
||||
{
|
||||
$languages = [
|
||||
['short_code' => 'en', 'name' => 'English', 'native_name' => 'English', 'is_active' => true],
|
||||
['short_code' => 'nl', 'name' => 'Dutch', 'native_name' => 'Nederlands', 'is_active' => true],
|
||||
['short_code' => 'fr', 'name' => 'French', 'native_name' => 'Français', 'is_active' => true],
|
||||
['short_code' => 'de', 'name' => 'German', 'native_name' => 'Deutsch', 'is_active' => true],
|
||||
];
|
||||
$languages = config('languages.supported', []);
|
||||
|
||||
foreach ($languages as $language) {
|
||||
DB::table('languages')->updateOrInsert(
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ class FeedTest extends TestCase
|
|||
|
||||
public function test_fillable_fields(): void
|
||||
{
|
||||
$fillableFields = ['name', 'url', 'type', 'language_id', 'description', 'settings', 'is_active', 'last_fetched_at'];
|
||||
$fillableFields = ['name', 'url', 'type', 'provider', 'language_id', 'description', 'settings', 'is_active', 'last_fetched_at'];
|
||||
$feed = new Feed();
|
||||
|
||||
$this->assertEquals($fillableFields, $feed->getFillable());
|
||||
|
|
@ -240,6 +240,7 @@ public function test_feed_creation_with_explicit_values(): void
|
|||
'name' => 'Test Feed',
|
||||
'url' => 'https://example.com/feed',
|
||||
'type' => 'rss',
|
||||
'provider' => 'vrt',
|
||||
'language_id' => $language->id,
|
||||
'description' => 'Test description',
|
||||
'settings' => $settings,
|
||||
|
|
|
|||
Loading…
Reference in a new issue