Skip to content

Commit

Permalink
Merge pull request #72 from Laravel-Backpack/check-command
Browse files Browse the repository at this point in the history
Basset check command
  • Loading branch information
pxpm authored Aug 1, 2023
2 parents 4c92868 + fe488e3 commit 791bbe2
Show file tree
Hide file tree
Showing 8 changed files with 228 additions and 12 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ jobs:
strategy:
matrix:
php: [8.1, 8.2]
laravel: [^10.7]
laravel: [^10.15]

name: PHP ${{ matrix.php }} / Laravel ${{ matrix.laravel }}

Expand Down
2 changes: 1 addition & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
"analyse": "./vendor/bin/phpstan analyse --level 5 src"
},
"require": {
"laravel/framework": "^10.7",
"laravel/framework": "^10.15",
"guzzlehttp/guzzle": "^7.5"
},
"require-dev": {
Expand Down
21 changes: 21 additions & 0 deletions readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,27 @@ But what if your `script.js` file is not only loaded by `card.blade.php`, but al

That's where this package comes to the rescue. It will load the asset just ONCE, even if it's loaded from multiple blade files.

## FAQ

#### Basset is not working, what may be wrong?

Before making any changes, you can run the command `php artisan basset:check`. It will perform a basic test to initialize, write, and read an asset, giving you better insights into any errors.

The most common reasons for Basset to fail are:

1) **Incorrect APP_URL in the `.env` file.**
Ensure that APP_URL in your `.env` matches your server configuration, including the hostname, protocol, and port number. Incorrect settings can lead to asset loading issues.

2) **Improperly configured disk.**
By default, Basset uses the Laravel `public` disk.
For new Laravel projects, the configuration is usually correct.
If you're upgrading a project and/or changed the `public` disk configuration, it's advised that you change the basset disk in `config/backpack/basset.php` to `basset`. The `basset` disk is a copy of the original Laravel `public` with working configurations.

3) **Missing or broken storage symlink.**
If you use the default `public` disk, Basset requires that the symlink between the storage and the public accessible folder to be created with `php artisan storage:link` command. During installation, Basset attempts to create the symlink. If it fails, you will need to manually create it with `php artisan storage:link`. If you encounter issues (e.g., after moving the project), recreating the symlink should resolve them.

Note for Homestead users: the symlink can't be created inside the virtual machine. You should stop your instance with: `vagrant down`, create the symlink in your local application folder and then `vagrant up` to bring the system back up.

## Change log

Please see the [releases tab](https://github.com/Laravel-Backpack/basset/releases) for more information on what has changed recently.
Expand Down
6 changes: 3 additions & 3 deletions src/BassetManager.php
Original file line number Diff line number Diff line change
Expand Up @@ -243,7 +243,7 @@ public function basset(string $asset, bool|string $output = true, array $attribu
}
// Validate the asset is an absolute path or a CDN
if (! str_starts_with($asset, base_path()) && ! str_starts_with($asset, 'http') && ! str_starts_with($asset, '://')) {
if (! str_starts_with($asset, base_path()) && ! Str::isUrl($asset)) {
// may be an internalized asset (folder or zip)
if ($this->disk->exists($path)) {
$asset = $this->disk->url($path);
Expand Down Expand Up @@ -271,7 +271,7 @@ public function basset(string $asset, bool|string $output = true, array $attribu
}
// Download/copy file
if (str_starts_with($asset, 'http') || str_starts_with($asset, '://')) {
if (Str::isUrl($asset)) {
// when in dev mode, cdn should be rendered
if ($this->dev) {
$output && $this->echoFile($asset, $attributes);
Expand Down Expand Up @@ -422,7 +422,7 @@ public function bassetArchive(string $asset, string $output): StatusEnum
}
// online zip
if (str_starts_with($asset, 'http') || str_starts_with($asset, '://')) {
if (Str::isUrl($asset)) {
// check if directory exists
if ($this->disk->exists($path)) {
return $this->loader->finish(StatusEnum::IN_CACHE);
Expand Down
32 changes: 32 additions & 0 deletions src/BassetServiceProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ class BassetServiceProvider extends ServiceProvider
protected $commands = [
\Backpack\Basset\Console\Commands\BassetCache::class,
\Backpack\Basset\Console\Commands\BassetClear::class,
\Backpack\Basset\Console\Commands\BassetCheck::class,
\Backpack\Basset\Console\Commands\BassetInstall::class,
\Backpack\Basset\Console\Commands\BassetInternalize::class,
\Backpack\Basset\Console\Commands\BassetFresh::class,
Expand All @@ -35,6 +36,9 @@ public function boot(): void
$this->bootForConsole();
}

// Load basset disk
$this->loadDisk();

// Run the terminate commands
$this->app->terminating(fn () => $this->terminate());
}
Expand Down Expand Up @@ -160,6 +164,34 @@ public function terminate(): void
$basset->cacheMap->save();
}

/**
* Loads needed basset disks.
*
* @return void
*/
public function loadDisk(): void
{
// if the basset disk already exists, don't override it
if (app()->config['filesystems.disks.basset']) {
return;
}

// if the basset disk isn't being used at all, don't even bother to add it
if (app()->config['backpack.basset.disk'] !== 'basset') {
return;
}

// add the basset disk to filesystem configuration
// should be kept up to date with https://github.com/laravel/laravel/blob/10.x/config/filesystems.php#L39-L45
app()->config['filesystems.disks.basset'] = [
'driver' => 'local',
'root' => storage_path('app/public'),
'url' => env('APP_URL').'/storage',
'visibility' => 'public',
'throw' => false,
];
}

/**
* Get the services provided by the provider.
*
Expand Down
141 changes: 141 additions & 0 deletions src/Console/Commands/BassetCheck.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
<?php

namespace Backpack\Basset\Console\Commands;

use Backpack\Basset\BassetManager;
use Backpack\Basset\Enums\StatusEnum;
use Exception;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\File;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Str;

/**
* Basset Cache command.
*
* @property object $output
*/
class BassetCheck extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'basset:check
{--installing} : Does this call comes from installing command.';

/**
* The console command description.
*
* @var string
*/
protected $description = 'Check Backpack Basset installation.';

private string $filepath;
private BassetManager $basset;

/**
* Execute the console command.
*
* @return void
*/
public function handle(): void
{
$message = '';
if (! $this->option('installing')) {
$this->components->info('Checking Backpack Basset installation');
}

try {
// init check
$message = 'Initializing basset check';
$this->init();
$this->components->twoColumnDetail($message, '<fg=green;options=bold>DONE</>');

// checking storage
$message = 'Checking cache storage';
$this->testCache();
$this->components->twoColumnDetail($message, '<fg=green;options=bold>DONE</>');

// fetching a basset
$message = 'Fetching a basset';
$this->testFetch();
$this->components->twoColumnDetail($message, '<fg=green;options=bold>DONE</>');
} catch (Exception $e) {
$this->components->twoColumnDetail($message, '<fg=red;options=bold>ERROR</>');
$this->newLine();
$this->components->error($e->getMessage());
$this->line(' <fg=gray>│ Backpack Basset failed to check it\'s working properly.</>');
$this->line(' <fg=gray>│</>');
$this->line(' <fg=gray>│ This may be due to multiple issues. Please ensure:</>');
$this->line(' <fg=gray>│ 1) APP_URL is correctly set in the <fg=white>.env</> file.</>');
$this->line(' <fg=gray>│ 2) Your server is running and accessible at <fg=white>'.url('').'</>.</>');
$this->line(' <fg=gray>│ 3) The <fg=white>'.config('backpack.basset.disk').'</> disk is properly configured in <fg=white>config/filesystems.php</>.</>');
$this->line(' <fg=gray>│ Optionally, basset provides a disk named "basset", you can use it instead.</>');
$this->line(' <fg=gray>│ 4) The storage symlink exists and is valid (by default: public/storage).</>');
$this->line(' <fg=gray>│</>');
$this->line(' <fg=gray>│ For more information and solutions, please visit the Backpack Basset FAQ at:</>');
$this->line(' <fg=gray>│ <fg=white>https://github.com/laravel-backpack/basset#faq</></>');
$this->newLine();
exit(1);
}

if (! $this->option('installing')) {
$this->newLine();
}
}

/**
* Initialize the test.
*
* @return void
*/
private function init(): void
{
$this->basset = app('basset');

// set a local file to run the tests
$this->filepath = base_path('vendor/backpack/basset/tests/Helpers/basset-test.js');

if (! File::exists($this->filepath)) {
throw new Exception('Error accessing the filesystem, the check can not run.');
}
}

/**
* Test cache the asset.
*
* @return void
*/
private function testCache(): void
{
// cache it with basset
$result = $this->basset->basset($this->filepath, false);

if (! in_array($result, [StatusEnum::INTERNALIZED, StatusEnum::IN_CACHE])) {
throw new Exception('Error caching the file.');
}
}

/**
* Test fetch the asset with Http.
*
* @return void
*/
private function testFetch(): void
{
// cache it with basset
$url = $this->basset->getUrl($this->filepath);

if (! Str::isUrl($url)) {
$url = url($url);
}

$result = Http::get($url);

if ($result->body() !== 'test') {
throw new Exception('Error fetching the file.');
}
}
}
35 changes: 28 additions & 7 deletions src/Console/Commands/BassetInstall.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

namespace Backpack\Basset\Console\Commands;

use Exception;
use Illuminate\Console\Command;
use Illuminate\Support\Str;
use Symfony\Component\Process\Process;
Expand Down Expand Up @@ -39,6 +40,9 @@ public function handle(): void
// create symlink
$this->createSymLink();

// create symlink
$this->checkBasset();

// check if artisan storage:link command exists
$this->addComposerCommand();

Expand All @@ -55,14 +59,31 @@ private function createSymLink(): void
{
$message = 'Creating symlink';

if (file_exists(public_path('storage'))) {
$this->components->twoColumnDetail($message, '<fg=yellow;options=bold>ALREADY EXISTED</>');

return;
try {
$this->callSilent('storage:link');
$this->components->twoColumnDetail($message, '<fg=green;options=bold>DONE</>');
} catch (Exception $e) {
$this->components->twoColumnDetail($message, '<fg=red;options=bold>ERROR</>');
$this->line(' <fg=gray>│ '.$e->getMessage().'</>');
$this->newLine();
}
}

$this->call('storage:link');
$this->components->twoColumnDetail($message, '<fg=green;options=bold>DONE</>');
/**
* Check if basset works.
*
* @return void
*/
private function checkBasset(): void
{
$message = 'Check Basset';

try {
$this->call('basset:check', ['--installing' => true]);
$this->components->twoColumnDetail($message, '<fg=green;options=bold>DONE</>');
} catch (Exception $e) {
$this->components->twoColumnDetail($message, '<fg=red;options=bold>ERROR</>');
}
}

/**
Expand All @@ -82,7 +103,7 @@ private function addComposerCommand(): void

if ($this->components->confirm('You will need to run `php artisan storage:link` on every server you deploy the app to. Do you wish to add that command to composer.json\' post-install-script, to make that automatic?', true)) {
$this->components->task($message, function () {
$process = new Process(['composer', 'config', 'scripts.post-install-cmd.-1', 'php artisan storage:link']);
$process = new Process(['composer', 'config', 'scripts.post-install-cmd.-1', 'php artisan storage:link --quiet']);
$process->run();
});
}
Expand Down
1 change: 1 addition & 0 deletions tests/Helpers/basset-test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
test

0 comments on commit 791bbe2

Please sign in to comment.