1.0.4 - fix instal.php

This commit is contained in:
2026-06-03 11:18:20 +02:00
parent 7381d86362
commit 25168debc0
7 changed files with 164 additions and 105 deletions
+15 -18
View File
@@ -1,31 +1,23 @@
<?php
declare(strict_types=1);
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Facades\Schema;
class AppSetting extends Model
{
protected $table = 'app_settings';
protected $fillable = [
'logo',
'logo_small',
'logo_path',
'logo_small_path',
'nome_applicazione',
'nome_organizzazione',
'footer_text',
'app_version',
'dashboard_welcome',
'show_version',
'backup_path',
'backup_retention_days',
'backup_include_files',
'backup_include_env',
'backup_auto_enabled',
'backup_auto_frequency',
'backup_auto_hour',
'logo', 'logo_small', 'logo_path', 'logo_small_path',
'nome_applicazione', 'nome_organizzazione',
'footer_text', 'app_version', 'dashboard_welcome', 'show_version',
'backup_path', 'backup_retention_days', 'backup_include_files',
'backup_include_env', 'backup_auto_enabled', 'backup_auto_frequency', 'backup_auto_hour',
'documenti_storage_disk', 'documenti_storage_path',
];
protected function casts(): array
@@ -36,11 +28,16 @@ class AppSetting extends Model
'backup_include_env' => 'boolean',
'backup_auto_enabled' => 'boolean',
'backup_auto_hour' => 'integer',
'show_version' => 'boolean',
];
}
public static function getSetting(string $key, $default = null)
public static function getSetting(string $key, mixed $default = null): mixed
{
if (!Schema::hasTable('app_settings')) {
return $default;
}
$setting = self::first();
return $setting?->{$key} ?? $default;
}
@@ -0,0 +1,46 @@
<?php
declare(strict_types=1);
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
public function up(): void
{
if (Schema::hasTable('app_settings')) {
return;
}
Schema::create('app_settings', function (Blueprint $table) {
$table->id();
$table->string('nome_applicazione')->nullable();
$table->string('nome_organizzazione')->nullable();
$table->string('logo')->nullable();
$table->string('logo_small')->nullable();
$table->string('logo_path')->nullable();
$table->string('logo_small_path')->nullable();
$table->string('footer_text')->nullable();
$table->string('app_version')->nullable();
$table->string('dashboard_welcome')->nullable();
$table->boolean('show_version')->default(false);
$table->string('documenti_storage_disk')->default('local');
$table->string('documenti_storage_path')->default('documenti');
$table->string('backup_path')->default('backups');
$table->integer('backup_retention_days')->default(30);
$table->boolean('backup_include_files')->default(true);
$table->boolean('backup_include_env')->default(true);
$table->boolean('backup_auto_enabled')->default(false);
$table->string('backup_auto_frequency', 20)->default('daily');
$table->integer('backup_auto_hour')->default(3);
$table->timestamps();
});
}
public function down(): void
{
Schema::dropIfExists('app_settings');
}
};
@@ -8,10 +8,21 @@ return new class extends Migration
{
public function up(): void
{
Schema::table('app_settings', function (Blueprint $table) {
$table->string('logo_path')->nullable()->after('logo');
$table->string('logo_small_path')->nullable()->after('logo_small');
});
if (!Schema::hasTable('app_settings')) {
return;
}
if (!Schema::hasColumn('app_settings', 'logo_path')) {
Schema::table('app_settings', function (Blueprint $table) {
$table->string('logo_path')->nullable()->after('logo');
});
}
if (!Schema::hasColumn('app_settings', 'logo_small_path')) {
Schema::table('app_settings', function (Blueprint $table) {
$table->string('logo_small_path')->nullable()->after('logo_small');
});
}
}
public function down(): void
@@ -8,12 +8,24 @@ return new class extends Migration
{
public function up(): void
{
Schema::table('app_settings', function (Blueprint $table) {
$table->string('footer_text')->nullable()->after('nome_organizzazione');
$table->string('app_version')->nullable()->after('footer_text');
$table->string('dashboard_welcome')->nullable()->after('app_version');
$table->boolean('show_version')->default(false)->after('dashboard_welcome');
});
if (!Schema::hasTable('app_settings')) {
return;
}
$columns = ['footer_text', 'app_version', 'dashboard_welcome', 'show_version'];
foreach ($columns as $column) {
if (!Schema::hasColumn('app_settings', $column)) {
Schema::table('app_settings', function (Blueprint $table) use ($column) {
match ($column) {
'footer_text' => $table->string('footer_text')->nullable()->after('nome_organizzazione'),
'app_version' => $table->string('app_version')->nullable()->after('footer_text'),
'dashboard_welcome' => $table->string('dashboard_welcome')->nullable()->after('app_version'),
'show_version' => $table->boolean('show_version')->default(false)->after('dashboard_welcome'),
};
});
}
}
}
public function down(): void
@@ -8,10 +8,21 @@ return new class extends Migration
{
public function up(): void
{
Schema::table('app_settings', function (Blueprint $table) {
$table->string('documenti_storage_disk')->default('local')->after('show_version');
$table->string('documenti_storage_path')->default('documenti')->after('documenti_storage_disk');
});
if (!Schema::hasTable('app_settings')) {
return;
}
if (!Schema::hasColumn('app_settings', 'documenti_storage_disk')) {
Schema::table('app_settings', function (Blueprint $table) {
$table->string('documenti_storage_disk')->default('local')->after('show_version');
});
}
if (!Schema::hasColumn('app_settings', 'documenti_storage_path')) {
Schema::table('app_settings', function (Blueprint $table) {
$table->string('documenti_storage_path')->default('documenti')->after('documenti_storage_disk');
});
}
}
public function down(): void
@@ -10,15 +10,31 @@ return new class extends Migration
{
public function up(): void
{
Schema::table('app_settings', function (Blueprint $table) {
$table->string('backup_path')->default('backups')->after('show_version');
$table->integer('backup_retention_days')->default(30)->after('backup_path');
$table->boolean('backup_include_files')->default(true)->after('backup_retention_days');
$table->boolean('backup_include_env')->default(true)->after('backup_include_files');
$table->boolean('backup_auto_enabled')->default(false)->after('backup_include_env');
$table->string('backup_auto_frequency', 20)->default('daily')->after('backup_auto_enabled');
$table->integer('backup_auto_hour')->default(3)->after('backup_auto_frequency');
});
if (!Schema::hasTable('app_settings')) {
return;
}
$columns = [
'backup_path' => ['type' => 'string', 'default' => 'backups'],
'backup_retention_days' => ['type' => 'integer', 'default' => 30],
'backup_include_files' => ['type' => 'boolean', 'default' => true],
'backup_include_env' => ['type' => 'boolean', 'default' => true],
'backup_auto_enabled' => ['type' => 'boolean', 'default' => false],
'backup_auto_frequency' => ['type' => 'string', 'length' => 20, 'default' => 'daily'],
'backup_auto_hour' => ['type' => 'integer', 'default' => 3],
];
foreach ($columns as $column => $config) {
if (!Schema::hasColumn('app_settings', $column)) {
Schema::table('app_settings', function (Blueprint $table) use ($column, $config) {
match ($config['type']) {
'string' => $table->string($column, $config['length'] ?? 255)->default($config['default'])->after('show_version'),
'integer' => $table->integer($column)->default($config['default'])->after('show_version'),
'boolean' => $table->boolean($column)->default($config['default'])->after('show_version'),
};
});
}
}
}
public function down(): void
@@ -773,7 +773,7 @@ echo 'Utente creato con successo!';
</div>
<div class="card-body">
<h5>Panoramica</h5>
<p>L'installazione avviene tramite comandi <strong>Artisan</strong> da terminale. Non esiste un wizard web interattivo. Supporta due modalita:</p>
<p>L'installazione avviene tramite l'interattivo <code>install.php</code> che guida passo-passo. Supporta due modalita:</p>
<div class="row">
<div class="col-md-6">
<div class="callout callout-info">
@@ -827,19 +827,37 @@ git clone &lt;URL_REPOSITORY&gt; glastree
# Opzione B — ZIP (se non hai git)
# unzip /percorso/del/glastree.zip -d glastree
cd glastree
composer install --no-dev --optimize-autoloader
npm ci && npm run build</code></pre>
<div class="alert alert-info">
<i class="fas fa-info-circle"></i>
Se non hai accesso a npm, puoi saltare il build. L'interfaccia usera comunque AdminLTE via CDN.
cd glastree</code></pre>
<h6>Passo 3: Eseguire l'installer</h6>
<p>Lancerai l'installer interattivo che ti guidera attraverso tutte le fasi:</p>
<pre><code>php install.php</code></pre>
<p>L'installer ti chiedera:</p>
<ol>
<li><strong>Modalità</strong>: Fresh Install (Apache/Docker) o Restore da Backup</li>
<li><strong>Parametri generali</strong>: nome sito, amministratore (nome, email, password), URL pubblico</li>
<li><strong>Database</strong>: MySQL (host, porta, nome, utente, password) o SQLite</li>
</ol>
<p>L'installer esegue automaticamente:</p>
<ul>
<li>Generazione <code>.env</code> e <code>APP_KEY</code></li>
<li>Creazione del database</li>
<li><code>composer install</code> e registrazione pacchetti</li>
<li>Migration e seed dei dati di base</li>
<li>Creazione dell'utente amministratore</li>
<li>Compilazione asset frontend (se npm disponibile)</li>
<li>Impostazione permessi cartelle</li>
</ul>
<div class="callout callout-info">
<h6><i class="fas fa-info-circle"></i> Docker</h6>
<p>Se scegli la modalita Docker, l'installer builda l'immagine, avvia i container e crea l'admin all'interno del container.</p>
</div>
<div class="callout callout-success">
<h6><i class="fas fa-upload"></i> Restore da Backup</h6>
<p>Se scegli Restore, l'installer ti chiedera il percorso del file ZIP di backup, ripristinera il database, i file e la configurazione.</p>
</div>
<h6>Passo 3: Permessi cartelle</h6>
<pre><code>sudo chown -R www-data:www-data storage bootstrap/cache
sudo chmod -R 775 storage bootstrap/cache</code></pre>
<h6>Passo 4: Configurare Apache</h6>
<h6 class="mt-4">Passo 4: Configurare Apache (solo modalita Fresh Install)</h6>
<pre><code>sudo tee /etc/apache2/sites-available/glastree.conf &lt;&lt;APACHE
&lt;VirtualHost *:80&gt;
ServerName glastree.esempio.it
@@ -859,58 +877,6 @@ APACHE
sudo a2dissite 000-default.conf
sudo a2ensite glastree.conf
sudo systemctl reload apache2</code></pre>
<h6>Passo 5: Configurare l'ambiente</h6>
<pre><code># Copia il file di configurazione di esempio
cp .env.example .env
# Genera la chiave di crittografia (obbligatorio)
php artisan key:generate
# Modifica .env con i parametri del tuo database:
# nano .env
# DB_DATABASE=glastree
# DB_USERNAME=glastree
# DB_PASSWORD=la_tua_password</code></pre>
<h6>Passo 6: Eseguire l'installazione</h6>
<p>Scegli la modalita in base alle tue esigenze:</p>
<h6 class="mt-3"><i class="fas fa-rocket"></i> Fresh Install</h6>
<pre><code># Esegui migration e seed dei dati di base
php artisan migrate --seed
# Crea il collegamento storage
php artisan storage:link
# Crea l'utente amministratore
php artisan tinker --execute="
\$u = new \App\Models\User;
\$u->name = 'Admin';
\$u->email = 'admin@esempio.it';
\$u->password = bcrypt('password_sicura');
\$u->save();
"</code></pre>
<div class="callout callout-info">
<h6><i class="fas fa-info-circle"></i> Dopo l'installazione</h6>
<p>Accedi con le credenziali create, vai in <strong>Impostazioni → Generali</strong> per configurare nome app, logo e parametri email.</p>
</div>
<h6 class="mt-3"><i class="fas fa-upload"></i> Restore da Backup</h6>
<pre><code># Crea il database e importa il backup
# mysql -u root -p glastree &lt; database.sql
# Ripristina i file dei documenti
# tar -xzf storage.tar.gz -C storage/
# Rigenera APP_KEY (invalida dati criptati esistenti!)
php artisan key:generate
# Crea il collegamento storage
php artisan storage:link</code></pre>
<div class="callout alert alert-warning">
<i class="fas fa-exclamation-triangle"></i>
<strong>Importante:</strong> Il restore da backup richiede che tu abbia un file ZIP generato dalla pagina <strong>Admin → Backup</strong> del server originale. Estrai manualmente il contenuto seguendo la struttura del progetto.
</div>