Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
6 changes: 4 additions & 2 deletions app/Console/Commands/ImportResourcesFromExcel.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ class ImportResourcesFromExcel extends Command
*
* @var string
*/
protected $signature = 'resources:import {file : Path to the Excel file}';
protected $signature = 'resources:import {file : Path to the Excel file} {--focus : Focus create related attributes}';

/**
* The console command description.
Expand All @@ -29,6 +29,7 @@ class ImportResourcesFromExcel extends Command
*/
public function handle()
{
$focus = $this->option('focus');
$filePath = $this->argument('file');
$excelPath = realpath($filePath);

Expand All @@ -39,13 +40,14 @@ public function handle()

$excelDir = dirname($excelPath);
$imagesDir = $excelDir . DIRECTORY_SEPARATOR . 'images';
$pdfsDir = $excelDir . DIRECTORY_SEPARATOR . 'links';

if (!is_dir($imagesDir)) {
$this->warn("Warning: Images folder not found at $imagesDir. Continuing without images.");
}

try {
Excel::import(new ResourcesImport($imagesDir), $filePath);
Excel::import(new ResourcesImport($imagesDir, $pdfsDir, $focus), $filePath);

$this->info('Import completed successfully.');
return 0;
Expand Down
92 changes: 87 additions & 5 deletions app/Imports/ResourcesImport.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,39 @@

class ResourcesImport extends DefaultValueBinder implements ToModel, WithCustomValueBinder, WithHeadingRow
{
/**
* Folder images upload to S3
*/
protected $imagesDir;

/**
* Folder PDF upload to S3
*/
protected $pdfsDir;

protected $focus;

// public
private $disk = 'resources';

public function __construct($imagesDir = null)
public function __construct($imagesDir = null, $pdfsDir = null, $focus = false)
{
$this->imagesDir = $imagesDir;
$this->focus = $focus;
$this->pdfsDir = $pdfsDir;
}

protected function createOrGetModel($class, $name)
{
$name = ucwords(mb_strtolower(trim($name)));

return $class::create([
'name' => $name,
'position' => 0,
'active' => true,
'teach' => true,
'learn' => true,
]);
}

protected function parseArray($value)
Expand All @@ -43,7 +68,7 @@ public function model(array $row): ?Model
Log::warning('[ResourcesImport] Missing name_of_the_resource', $row);
return null;
}

$thumbnail = null;
if (!empty($row['image']) && $this->imagesDir) {
$localPath = $this->imagesDir . DIRECTORY_SEPARATOR . $row['image'];
Expand All @@ -56,16 +81,52 @@ public function model(array $row): ?Model
Log::warning("[ResourcesImport] Image not found: $localPath");
}
}


$pdfLink = null;
if (!empty($row['link']) && stripos($row['link'], 'http://') !== 0 && stripos($row['link'], 'https://') !== 0 && $this->pdfsDir) {
$groupName = !empty($row['group_name']) ? trim($row['group_name']) : '';
$groupSlug = $groupName ? Str::slug($groupName) : 'default';

$searchBase = $groupName ? $this->pdfsDir . DIRECTORY_SEPARATOR . $groupName : $this->pdfsDir;
$pdfFilename = basename($row['link']);
$pdfLocalPath = null;

if (is_dir($searchBase)) {
$rii = new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($searchBase));
foreach ($rii as $file) {
if ($file->isFile() && strcasecmp($file->getFilename(), $pdfFilename) === 0) {
$pdfLocalPath = $file->getPathname();
break;
}
}
}

if ($pdfLocalPath && file_exists($pdfLocalPath)) {
$ext = pathinfo($pdfFilename, PATHINFO_EXTENSION) ?: 'pdf';
$basename = Str::slug(pathinfo($pdfFilename, PATHINFO_FILENAME)) . '-' . time() . '.' . $ext;
$storagePath = $groupSlug . '/' . $basename;
Storage::disk($this->disk)->put($storagePath, file_get_contents($pdfLocalPath));
$pdfLink = Storage::disk($this->disk)->url($storagePath);
} else {
Log::warning("[ResourcesImport] PDF not found: {$row['link']} in {$searchBase}");
}
}

$groups = [];
if (!empty($row['category'])) {
$groups = $this->parseArray($row['category']);
}

$item = new ResourceItem([
'name' => trim($row['name_of_the_resource']),
'source' => trim($row['link'] ?? ''),
'source' => $pdfLink ?: trim($row['link'] ?? ''),
'description' => trim($row['description'] ?? ''),
'thumbnail' => $thumbnail,
'learn' => true,
'teach' => true,
'active' => true,
'weight' => \Carbon\Carbon::now()->format('Y')
'weight' => \Carbon\Carbon::now()->format('Y'),
'groups' => $groups,
]);
$item->save();

Expand All @@ -76,6 +137,9 @@ public function model(array $row): ?Model
$model = ResourceType::whereRaw('LOWER(name) = ?', [mb_strtolower(trim($type))])->first();
if ($model) {
$item->types()->attach($model->id);
} elseif ($this->focus) {
$model = $this->createOrGetModel(ResourceType::class, trim($type));
$item->types()->attach($model->id);
} else {
Log::warning("[ResourcesImport] ResourceType not found: $type");
}
Expand All @@ -87,6 +151,9 @@ public function model(array $row): ?Model
$model = ResourceLevel::whereRaw('LOWER(name) = ?', [mb_strtolower(trim($aud))])->first();
if ($model) {
$item->levels()->attach($model->id);
} elseif ($this->focus) {
$model = $this->createOrGetModel(ResourceLevel::class, trim($aud));
$item->levels()->attach($model->id);
} else {
Log::warning("[ResourcesImport] ResourceLevel (target_audience) not found: $aud");
}
Expand All @@ -98,6 +165,9 @@ public function model(array $row): ?Model
$model = ResourceLevel::whereRaw('LOWER(name) = ?', [mb_strtolower(trim($level))])->first();
if ($model) {
$item->levels()->attach($model->id);
} elseif ($this->focus) {
$model = $this->createOrGetModel(ResourceLevel::class, trim($level));
$item->levels()->attach($model->id);
} else {
Log::warning("[ResourcesImport] ResourceLevel (level_of_difficulty) not found: $level");
}
Expand All @@ -109,6 +179,9 @@ public function model(array $row): ?Model
$model = ResourceProgrammingLanguage::whereRaw('LOWER(name) = ?', [mb_strtolower(trim($lang))])->first();
if ($model) {
$item->programmingLanguages()->attach($model->id);
} elseif ($this->focus) {
$model = $this->createOrGetModel(ResourceProgrammingLanguage::class, trim($lang));
$item->programmingLanguages()->attach($model->id);
} else {
Log::warning("[ResourcesImport] ResourceProgrammingLanguage not found: $lang");
}
Expand All @@ -120,6 +193,9 @@ public function model(array $row): ?Model
$model = ResourceSubject::whereRaw('LOWER(name) = ?', [mb_strtolower(trim($subject))])->first();
if ($model) {
$item->subjects()->attach($model->id);
} elseif ($this->focus) {
$model = $this->createOrGetModel(ResourceSubject::class, trim($subject));
$item->subjects()->attach($model->id);
} else {
Log::warning("[ResourcesImport] ResourceSubject not found: $subject");
}
Expand All @@ -131,6 +207,9 @@ public function model(array $row): ?Model
$model = ResourceCategory::whereRaw('LOWER(name) = ?', [mb_strtolower(trim($topic))])->first();
if ($model) {
$item->categories()->attach($model->id);
} elseif ($this->focus) {
$model = $this->createOrGetModel(ResourceCategory::class, trim($topic));
$item->categories()->attach($model->id);
} else {
Log::warning("[ResourcesImport] ResourceCategory (topic) not found: $topic");
}
Expand All @@ -142,6 +221,9 @@ public function model(array $row): ?Model
$model = ResourceLanguage::whereRaw('LOWER(name) = ?', [mb_strtolower(trim($lang))])->first();
if ($model) {
$item->languages()->attach($model->id);
} elseif ($this->focus) {
$model = $this->createOrGetModel(ResourceLanguage::class, trim($lang));
$item->languages()->attach($model->id);
} else {
Log::warning("[ResourcesImport] ResourceLanguage not found: $lang");
}
Expand Down
2 changes: 2 additions & 0 deletions app/Nova/ResourceItem.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
use Illuminate\Http\Request;
use Laravel\Nova\Fields\BelongsToMany;
use Laravel\Nova\Fields\Boolean;
use Laravel\Nova\Fields\Code;
use Laravel\Nova\Fields\ID;
use Laravel\Nova\Fields\Number;
use Laravel\Nova\Fields\Text;
Expand Down Expand Up @@ -66,6 +67,7 @@ public function fields(Request $request): array
Text::make('Description')->sortable()->hideFromIndex(),
Text::make('Source')->sortable()->hideFromIndex(),
Number::make('weight')->sortable(),
Code::make('Groups', 'groups')->json(),
Boolean::make('Teach'),
Boolean::make('Learn'),

Expand Down
23 changes: 22 additions & 1 deletion app/ResourceItem.php
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,22 @@ class ResourceItem extends Model
'teach' => false,
];

protected $fillable = [
'name',
'source',
'description',
'thumbnail',
'learn',
'teach',
'active',
'weight',
'groups',
];

protected $casts = [
'groups' => 'array',
];

protected $appends = ['thumbnail'];

public function scopeFilter($query, ResourceFilters $filters)
Expand All @@ -84,7 +100,12 @@ public function getThumbnailAttribute($value)
return $value;
}

return config('codeweek.resources_url') . ltrim($value, '/');
if ($value) {
return config('codeweek.resources_url') . ltrim($value, '/');
}
else {
return 'https://s3-eu-west-1.amazonaws.com/codeweek-dev/events/pictures/event_default_picture.png';
}
}

public function levels(): BelongsToMany
Expand Down
1 change: 1 addition & 0 deletions app/ResourceLanguage.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
*
* @property int $id
* @property string $name
* @property string $code
* @property int $position
* @property int $active
* @property int $teach
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::table('resource_items', function (Blueprint $table) {
$table->json('groups')->nullable();
});
}

/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::table('resource_items', function (Blueprint $table) {
$table->dropColumn('groups');
});
}
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::table('resource_languages', function (Blueprint $table) {
$table->string('code')->nullable();
});
}

/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::table('resource_languages', function (Blueprint $table) {
$table->dropColumn('code');
});
}
};
1 change: 1 addition & 0 deletions public/build/assets/app-BXGezakj.css

Large diffs are not rendered by default.

Loading
Loading