Skip to content

Commit

Permalink
Merge pull request #11 from open-sausages/pulls/1.0/vendor-expose
Browse files Browse the repository at this point in the history
API Add vendor-expose composer command
  • Loading branch information
flamerohr authored Nov 22, 2017
2 parents 4a2f3c1 + 36d42d0 commit ad91e76
Show file tree
Hide file tree
Showing 11 changed files with 399 additions and 84 deletions.
13 changes: 11 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,15 @@ If necessary, you can force the behaviour to one of the below using the
- `none` - Disables all symlink / copy
- `copy` - Performs a copy only
- `symlink` - Performs a symlink only
- `auto` -> Perfrm symlink, but fail over to copy.
- `junction` - Uses a junction (windows only)
- `auto` -> Perfrm symlink (or junction on windows), but fail over to copy.

Any other value will be treated as `auto`
## Updating all exposed folders

A custom composer command can be run at any time to update / refresh all

`composer vendor-expose [<method>]`

You can pass in one of the above methods to force a specific behaviour, otherwise
the default will be chosen based on either a previously used method,
or the `SS_VENDOR_METHOD` environment argument.
6 changes: 6 additions & 0 deletions resources/.htaccess
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
# Block .method file
<Files .method>
Order Allow,Deny
Deny from all
</Files>

# Block 404s
<IfModule mod_rewrite.c>
RewriteCond %{REQUEST_FILENAME} !-f
Expand Down
21 changes: 21 additions & 0 deletions src/Console/VendorCommandProvider.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<?php

namespace SilverStripe\VendorPlugin\Console;

use Composer\Command\BaseCommand;
use Composer\Plugin\Capability\CommandProvider;

class VendorCommandProvider implements CommandProvider
{
/**
* Retreives an array of commands
*
* @return BaseCommand[]
*/
public function getCommands()
{
return [
new VendorExposeCommand()
];
}
}
89 changes: 89 additions & 0 deletions src/Console/VendorExposeCommand.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
<?php

namespace SilverStripe\VendorPlugin\Console;

use Composer\Command\BaseCommand;
use Composer\Factory;
use Composer\IO\ConsoleIO;
use Composer\Util\Filesystem;
use SilverStripe\VendorPlugin\Util;
use SilverStripe\VendorPlugin\VendorExposeTask;
use SilverStripe\VendorPlugin\VendorModule;
use SilverStripe\VendorPlugin\VendorPlugin;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;

/**
* Provides `composer vendor-expose` behaviour
*/
class VendorExposeCommand extends BaseCommand
{
public function configure()
{
$this->setName('vendor-expose');
$this->setDescription('Refresh all exposed vendor module folders');
$this->addArgument(
'method',
InputArgument::OPTIONAL,
'Optional method to use. Defaults to last used value, or ' . VendorPlugin::METHOD_DEFAULT . ' otherwise'
);
$this->setHelp('This command will update all resources for all installed modules using the given method');
}

public function execute(InputInterface $input, OutputInterface $output)
{
$io = new ConsoleIO($input, $output, $this->getHelperSet());

// Check modules to expose
$modules = $this->getAllModules();
if (empty($modules)) {
$io->write("No modules to expose");
return;
}

// Expose all modules
$method = $input->getArgument('method');
$task = new VendorExposeTask($this->getProjectPath(), new Filesystem(), VendorModule::DEFAULT_TARGET);
$task->process($io, $modules, $method);

// Success
$io->write("All modules updated!");
}

/**
* Find all modules
*
* @return VendorModule[]
*/
protected function getAllModules()
{
$modules = [];
$basePath = $this->getProjectPath();
$search = Util::joinPaths($basePath, 'vendor', '*', '*');
foreach (glob($search, GLOB_ONLYDIR) as $modulePath) {
// Filter by non-composer folders
$composerPath = Util::joinPaths($modulePath, 'composer.json');
if (!file_exists($composerPath)) {
continue;
}
// Build module
$name = basename($modulePath);
$vendor = basename(dirname($modulePath));
$module = new VendorModule($basePath, "{$vendor}/{$name}");
// Check if this module has folders to expose
if ($module->getExposedFolders()) {
$modules[] = $module;
}
}
return $modules;
}

/**
* @return string
*/
protected function getProjectPath()
{
return dirname(realpath(Factory::getComposerFile()));
}
}
1 change: 1 addition & 0 deletions src/Methods/CopyMethod.php
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ public function copy($source, $target)
return copy($source, $target);
}
$it = new RecursiveDirectoryIterator($source, RecursiveDirectoryIterator::SKIP_DOTS);
/** @var RecursiveDirectoryIterator $ri */
$ri = new RecursiveIteratorIterator($it, RecursiveIteratorIterator::SELF_FIRST);
$this->filesystem->ensureDirectoryExists($target);
$result = true;
Expand Down
28 changes: 28 additions & 0 deletions src/Methods/JunctionMethod.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<?php

namespace SilverStripe\VendorPlugin\Methods;

use Composer\Util\Platform;
use RuntimeException;

/**
* Expose the vendor module resources via a symlink
*/
class JunctionMethod extends SymlinkMethod
{
const NAME = 'junction';

protected function createLink($source, $target)
{
if (!Platform::isWindows()) {
throw new RuntimeException("Cannot create junction on non-windows environment");
}
$this->filesystem->junction($source, $target);

// Check if this command succeeded
$success = $this->filesystem->isJunction($target);
if (!$success) {
throw new RuntimeException("Could not create symlink at $target");
}
}
}
15 changes: 5 additions & 10 deletions src/Methods/SymlinkMethod.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
namespace SilverStripe\VendorPlugin\Methods;

use Composer\Util\Filesystem;
use Composer\Util\Platform;
use RuntimeException;

/**
Expand Down Expand Up @@ -33,24 +32,20 @@ public function exposeDirectory($source, $target)
$this->filesystem->ensureDirectoryExists($parent);

// Ensure symlink exists
if (!$this->relativeSymlink($source, $target)) {
throw new RuntimeException("Could not create symlink at $target");
}
$this->createLink($source, $target);
}

/**
* Create symlink
*
* @param string $source File source
* @param string $target Place to put symlink
* @return bool
*/
protected function relativeSymlink($source, $target)
protected function createLink($source, $target)
{
if (Platform::isWindows()) {
$this->filesystem->junction($source, $target);
return true;
$success = $this->filesystem->relativeSymlink($source, $target);
if (!$success) {
throw new RuntimeException("Could not create symlink at $target");
}
return $this->filesystem->relativeSymlink($source, $target);
}
}
Loading

0 comments on commit ad91e76

Please sign in to comment.