Laravel has no built-in vendor:unpublish or rollback command. But here it may be useful during the package development or using packages which are in very raw active development state.
So vendor:publish should be extended to unambiguously track what was written and where, which folders and files were created, deleted, renamed etc by which exact version. And write manifest about it i.e. somewhere to EVO_STORAGE_PATH.
So a custom vendor:unpublish command will be possible. The main issue is not discovering the destinations. The issue is deleting them safely.
<?php
namespace App\Console\Commands;
use Illuminate\Console\Command;
use Illuminate\Filesystem\Filesystem;
use Illuminate\Support\ServiceProvider;
class VendorUnpublishCommand extends Command
{
protected $signature = 'vendor:unpublish
{--provider= : The service provider class}
{--tag= : The publish tag}
{--force : Delete without confirmation}';
protected $description = 'Delete files published by a package service provider';
public function handle(Filesystem $files): int
{
$provider = $this->option('provider');
$tag = $this->option('tag');
$paths = ServiceProvider::pathsToPublish($provider, $tag);
if ($paths === []) {
$this->error('No publishable paths were found.');
return self::FAILURE;
}
foreach ($paths as $source => $destination) {
$this->line($destination);
}
if (
! $this->option('force')
&& ! $this->confirm('Delete all listed destinations?')
) {
return self::SUCCESS;
}
foreach ($paths as $source => $destination) {
if ($files->isDirectory($source)) {
$this->deletePublishedDirectory($files, $source, $destination);
} elseif ($files->exists($destination)) {
$files->delete($destination);
}
}
return self::SUCCESS;
}
private function deletePublishedDirectory(
Filesystem $files,
string $source,
string $destination
): void {
foreach ($files->allFiles($source) as $sourceFile) {
$relativePath = $sourceFile->getRelativePathname();
$publishedPath = $destination.DIRECTORY_SEPARATOR.$relativePath;
if ($files->exists($publishedPath)) {
$files->delete($publishedPath);
}
}
$directories = $files->allDirectories($destination);
usort(
$directories,
static fn (string $a, string $b): int => strlen($b) <=> strlen($a)
);
foreach ($directories as $directory) {
if ($files->isDirectory($directory) && $files->files($directory) === []) {
$files->deleteDirectory($directory);
}
}
if (
$files->isDirectory($destination)
&& $files->files($destination) === []
&& $files->directories($destination) === []
) {
$files->deleteDirectory($destination);
}
}
}
Usage:
php artisan vendor:unpublish \
--provider="Vendor\Package\PackageServiceProvider"
Or by tag:
php artisan vendor:unpublish --tag=package-config
Laravel has no built-in vendor:unpublish or rollback command. But here it may be useful during the package development or using packages which are in very raw active development state.
So vendor:publish should be extended to unambiguously track what was written and where, which folders and files were created, deleted, renamed etc by which exact version. And write manifest about it i.e. somewhere to EVO_STORAGE_PATH.
So a custom vendor:unpublish command will be possible. The main issue is not discovering the destinations. The issue is deleting them safely.
Usage:
Or by tag: