Skip to content

Commit

Permalink
Detect automatically the available asset manager
Browse files Browse the repository at this point in the history
  • Loading branch information
francoispluchino committed Jun 6, 2020
1 parent 201420a commit fa54167
Show file tree
Hide file tree
Showing 5 changed files with 251 additions and 9 deletions.
10 changes: 10 additions & 0 deletions Asset/AbstractAssetManager.php
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,16 @@ public function __construct(
$this->fallback = $fallback;
}

/**
* {@inheritdoc}
*/
public function isAvailable()
{
$this->executor->execute($this->getVersionCommand(), $version);

return '' !== trim($version);
}

/**
* {@inheritdoc}
*/
Expand Down
95 changes: 95 additions & 0 deletions Asset/AssetManagerFinder.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
<?php

/*
* This file is part of the Foxy package.
*
* (c) François Pluchino <francois.pluchino@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace Foxy\Asset;

use Foxy\Exception\RuntimeException;

/**
* Asset Manager finder.
*
* @author François Pluchino <francois.pluchino@gmail.com>
*/
class AssetManagerFinder
{
/**
* @var AssetManagerInterface[]
*/
private $managers;

/**
* Constructor.
*
* @param AssetManagerInterface[] $managers The asset managers
*/
public function __construct(array $managers = array())
{
foreach ($managers as $manager) {
if ($manager instanceof AssetManagerInterface) {
$this->addManager($manager);
}
}
}

public function addManager(AssetManagerInterface $manager)
{
$this->managers[$manager->getName()] = $manager;
}

/**
* Find the asset manager.
*
* @param null|string $manager The name of the asset manager
*
* @throws RuntimeException When the asset manager does not exist
* @throws RuntimeException When the asset manager is not found
*
* @return AssetManagerInterface
*/
public function findManager($manager = null)
{
if (null !== $manager) {
if (isset($this->managers[$manager])) {
return $this->managers[$manager];
}

throw new RuntimeException(sprintf('The asset manager "%s" doesn\'t exist', $manager));
}

return $this->findAvailableManager();
}

/**
* Find the available asset manager.
*
* @throws RuntimeException When no asset manager is found
*
* @return AssetManagerInterface
*/
private function findAvailableManager()
{
// find asset manager by lockfile
foreach ($this->managers as $manager) {
if ($manager->hasLockFile()) {
return $manager;
}
}

// find asset manager by availability
foreach ($this->managers as $manager) {
if ($manager->isAvailable()) {
return $manager;
}
}

throw new RuntimeException('No asset manager is found');
}
}
7 changes: 7 additions & 0 deletions Asset/AssetManagerInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,13 @@ interface AssetManagerInterface
*/
public function getName();

/**
* Check if the asset manager is available.
*
* @return bool
*/
public function isAvailable();

/**
* Get the filename of the asset package.
*
Expand Down
15 changes: 6 additions & 9 deletions Foxy.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
use Composer\Script\ScriptEvents;
use Composer\Util\Filesystem;
use Composer\Util\ProcessExecutor;
use Foxy\Asset\AssetManagerFinder;
use Foxy\Asset\AssetManagerInterface;
use Foxy\Config\Config;
use Foxy\Config\ConfigBuilder;
Expand Down Expand Up @@ -76,16 +77,16 @@ class Foxy implements PluginInterface, EventSubscriberInterface
* The list of the classes of asset managers.
*/
private static $assetManagers = array(
'Foxy\Asset\NpmManager',
'Foxy\Asset\YarnManager',
'Foxy\Asset\NpmManager',
);

/**
* The default values of config.
*/
private static $defaultConfig = array(
'enabled' => true,
'manager' => 'npm',
'manager' => null,
'manager-version' => array(
'npm' => '>=5.0.0',
'yarn' => '>=1.0.0',
Expand Down Expand Up @@ -218,16 +219,12 @@ public function solveAssets(Event $event)
*/
protected function getAssetManager(IOInterface $io, Config $config, ProcessExecutor $executor, Filesystem $fs)
{
$manager = $config->get('manager');
$amf = new AssetManagerFinder();

foreach (self::$assetManagers as $class) {
$am = new $class($io, $config, $executor, $fs);

if ($am instanceof AssetManagerInterface && $manager === $am->getName()) {
return $am;
}
$amf->addManager(new $class($io, $config, $executor, $fs));
}

throw new RuntimeException(sprintf('The asset manager "%s" doesn\'t exist', $manager));
return $amf->findManager($config->get('manager'));
}
}
133 changes: 133 additions & 0 deletions Tests/Asset/AssetManagerFinderTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
<?php

/*
* This file is part of the Foxy package.
*
* (c) François Pluchino <francois.pluchino@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace Foxy\Tests\Asset;

use Foxy\Asset\AssetManagerFinder;
use PHPUnit\Framework\TestCase;

/**
* Asset manager finder tests.
*
* @author François Pluchino <francois.pluchino@gmail.com>
*
* @internal
*/
final class AssetManagerFinderTest extends TestCase
{
public function testFindManagerWithValidManager()
{
$am = $this->getMockBuilder('Foxy\Asset\AssetManagerInterface')->getMock();

$am->expects(static::once())
->method('getName')
->willReturn('foo')
;

$amf = new AssetManagerFinder(array($am));
$res = $amf->findManager('foo');

static::assertSame($am, $res);
}

/**
* @expectedException \Foxy\Exception\RuntimeException
* @expectedExceptionMessage The asset manager "bar" doesn't exist
*/
public function testFindManagerWithInvalidManager()
{
$am = $this->getMockBuilder('Foxy\Asset\AssetManagerInterface')->getMock();

$am->expects(static::once())
->method('getName')
->willReturn('foo')
;

$amf = new AssetManagerFinder(array($am));
$amf->findManager('bar');
}

public function testFindManagerWithAutoManagerAndAvailableManagerByLockFile()
{
$am = $this->getMockBuilder('Foxy\Asset\AssetManagerInterface')->getMock();

$am->expects(static::once())
->method('getName')
->willReturn('foo')
;

$am->expects(static::once())
->method('hasLockFile')
->willReturn(true)
;

$am->expects(static::never())
->method('isAvailable')
;

$amf = new AssetManagerFinder(array($am));
$res = $amf->findManager(null);

static::assertSame($am, $res);
}

public function testFindManagerWithAutoManagerAndAvailableManagerByAvailability()
{
$am = $this->getMockBuilder('Foxy\Asset\AssetManagerInterface')->getMock();

$am->expects(static::once())
->method('getName')
->willReturn('foo')
;

$am->expects(static::once())
->method('hasLockFile')
->willReturn(false)
;

$am->expects(static::once())
->method('isAvailable')
->willReturn(true)
;

$amf = new AssetManagerFinder(array($am));
$res = $amf->findManager(null);

static::assertSame($am, $res);
}

/**
* @expectedException \Foxy\Exception\RuntimeException
* @expectedExceptionMessage No asset manager is found
*/
public function testFindManagerWithAutoManagerAndNoAvailableManager()
{
$am = $this->getMockBuilder('Foxy\Asset\AssetManagerInterface')->getMock();

$am->expects(static::atLeastOnce())
->method('getName')
->willReturn('foo')
;

$am->expects(static::once())
->method('hasLockFile')
->willReturn(false)
;

$am->expects(static::once())
->method('isAvailable')
->willReturn(false)
;

$amf = new AssetManagerFinder(array($am));
$amf->findManager(null);
}
}

0 comments on commit fa54167

Please sign in to comment.