Composer.php
TLDR
The file Composer.php
contains a class called Composer
that provides methods for managing and manipulating Composer packages and the composer.json
file.
Methods
hasPackage
This method is a protected method that checks if a given Composer package is installed. It reads the composer.json
file to determine if the package appears in the require
or require-dev
sections.
requirePackages
This method allows installing the given Composer packages into the application. It accepts an array of package names, a boolean indicating whether to install them as development dependencies, an optional callback or Symfony OutputInterface
for capturing output, and an optional path to the Composer binary. It constructs a command to execute using Composer and runs it.
removePackages
This method allows removing the given Composer packages from the application. It accepts the same parameters as requirePackages
and constructs and runs a similar command to remove the packages using Composer.
modify
This method modifies the contents of the composer.json
file using the given callback. It reads the file, decodes the JSON content, passes it to the callback for modification, and writes the modified content back to the file.
dumpAutoloads
This method regenerates the Composer autoloader files. It accepts an optional extra argument and an optional path to the Composer binary. It constructs a command to run composer dump-autoload
with the extra argument and executes it.
dumpOptimized
This method regenerates the optimized Composer autoloader files by calling dumpAutoloads
with the --optimize
argument.
findComposer
This method gets the Composer binary or command for the environment. It accepts an optional path to a Composer binary. It checks if the binary path is provided and exists, and if not, it checks if composer.phar
exists in the working path. It returns an array containing the PHP binary and the Composer binary or the default composer
command.
findComposerFile
This method gets the path to the composer.json
file. It checks if the file exists in the working path and throws a RuntimeException
if it doesn't. It returns the path to the file.
phpBinary
This method gets the PHP binary path.
getProcess
This method creates a new Symfony Process
instance. It accepts an array of command arguments and an array of environment variables. It returns the Process
instance.
setWorkingPath
This method sets the working path used by the class. It accepts a string representing the path and returns the current instance of the class.
getVersion
This method gets the version of Composer. It constructs a command to run composer -V --no-ansi
and executes it. It extracts the version from the output or returns null if it cannot be determined.
Classes
No additional classes are defined in the file.
<?php
namespace Illuminate\Support;
use Closure;
use Illuminate\Filesystem\Filesystem;
use RuntimeException;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Process\PhpExecutableFinder;
use Symfony\Component\Process\Process;
class Composer
{
/**
* The filesystem instance.
*
* @var \Illuminate\Filesystem\Filesystem
*/
protected $files;
/**
* The working path to regenerate from.
*
* @var string|null
*/
protected $workingPath;
/**
* Create a new Composer manager instance.
*
* @param \Illuminate\Filesystem\Filesystem $files
* @param string|null $workingPath
* @return void
*/
public function __construct(Filesystem $files, $workingPath = null)
{
$this->files = $files;
$this->workingPath = $workingPath;
}
/**
* Determine if the given Composer package is installed.
*
* @param string $package
* @return bool
*
* @throw \RuntimeException
*/
protected function hasPackage($package)
{
$composer = json_decode(file_get_contents($this->findComposerFile()), true);
return array_key_exists($package, $composer['require'] ?? [])
|| array_key_exists($package, $composer['require-dev'] ?? []);
}
/**
* Install the given Composer packages into the application.
*
* @param array<int, string> $packages
* @param bool $dev
* @param \Closure|\Symfony\Component\Console\Output\OutputInterface|null $output
* @param string|null $composerBinary
* @return bool
*/
public function requirePackages(array $packages, bool $dev = false, Closure|OutputInterface $output = null, $composerBinary = null)
{
$command = collect([
...$this->findComposer($composerBinary),
'require',
...$packages,
])
->when($dev, function ($command) {
$command->push('--dev');
})->all();
return 0 === $this->getProcess($command, ['COMPOSER_MEMORY_LIMIT' => '-1'])
->run(
$output instanceof OutputInterface
? function ($type, $line) use ($output) {
$output->write(' '.$line);
} : $output
);
}
/**
* Remove the given Composer packages from the application.
*
* @param array<int, string> $packages
* @param bool $dev
* @param \Closure|\Symfony\Component\Console\Output\OutputInterface|null $output
* @param string|null $composerBinary
* @return bool
*/
public function removePackages(array $packages, bool $dev = false, Closure|OutputInterface $output = null, $composerBinary = null)
{
$command = collect([
...$this->findComposer($composerBinary),
'remove',
...$packages,
])
->when($dev, function ($command) {
$command->push('--dev');
})->all();
return 0 === $this->getProcess($command, ['COMPOSER_MEMORY_LIMIT' => '-1'])
->run(
$output instanceof OutputInterface
? function ($type, $line) use ($output) {
$output->write(' '.$line);
} : $output
);
}
/**
* Modify the "composer.json" file contents using the given callback.
*
* @param callable(array):array $callback
* @return void
*
* @throw \RuntimeException
*/
public function modify(callable $callback)
{
$composerFile = $this->findComposerFile();
$composer = json_decode(file_get_contents($composerFile), true, 512, JSON_THROW_ON_ERROR);
file_put_contents(
$composerFile,
json_encode(
call_user_func($callback, $composer),
JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE
)
);
}
/**
* Regenerate the Composer autoloader files.
*
* @param string|array $extra
* @param string|null $composerBinary
* @return int
*/
public function dumpAutoloads($extra = '', $composerBinary = null)
{
$extra = $extra ? (array) $extra : [];
$command = array_merge($this->findComposer($composerBinary), ['dump-autoload'], $extra);
return $this->getProcess($command)->run();
}
/**
* Regenerate the optimized Composer autoloader files.
*
* @param string|null $composerBinary
* @return int
*/
public function dumpOptimized($composerBinary = null)
{
return $this->dumpAutoloads('--optimize', $composerBinary);
}
/**
* Get the Composer binary / command for the environment.
*
* @param string|null $composerBinary
* @return array
*/
public function findComposer($composerBinary = null)
{
if (! is_null($composerBinary) && $this->files->exists($composerBinary)) {
return [$this->phpBinary(), $composerBinary];
} elseif ($this->files->exists($this->workingPath.'/composer.phar')) {
return [$this->phpBinary(), 'composer.phar'];
}
return ['composer'];
}
/**
* Get the path to the "composer.json" file.
*
* @return string
*
* @throw \RuntimeException
*/
protected function findComposerFile()
{
$composerFile = "{$this->workingPath}/composer.json";
if (! file_exists($composerFile)) {
throw new RuntimeException("Unable to locate `composer.json` file at [{$this->workingPath}].");
}
return $composerFile;
}
/**
* Get the PHP binary.
*
* @return string
*/
protected function phpBinary()
{
return ProcessUtils::escapeArgument((new PhpExecutableFinder)->find(false));
}
/**
* Get a new Symfony process instance.
*
* @param array $command
* @param array $env
* @return \Symfony\Component\Process\Process
*/
protected function getProcess(array $command, array $env = [])
{
return (new Process($command, $this->workingPath, $env))->setTimeout(null);
}
/**
* Set the working path used by the class.
*
* @param string $path
* @return $this
*/
public function setWorkingPath($path)
{
$this->workingPath = realpath($path);
return $this;
}
/**
* Get the version of Composer.
*
* @return string|null
*/
public function getVersion()
{
$command = array_merge($this->findComposer(), ['-V', '--no-ansi']);
$process = $this->getProcess($command);
$process->run();
$output = $process->getOutput();
if (preg_match('/(\d+(\.\d+){2})/', $output, $version)) {
return $version[1];
}
return explode(' ', $output)[2] ?? null;
}
}